Skip to content

feat(progress): replace file-based comment ID with CASCADE_PROGRESS_COMMENT_ID env var#638

Merged
zbigniewsobiecki merged 6 commits intodevfrom
feat/env-var-progress-comment-id
Mar 7, 2026
Merged

feat(progress): replace file-based comment ID with CASCADE_PROGRESS_COMMENT_ID env var#638
zbigniewsobiecki merged 6 commits intodevfrom
feat/env-var-progress-comment-id

Conversation

@aaight
Copy link
Copy Markdown
Collaborator

@aaight aaight commented Mar 7, 2026

Summary

Replaces the file-based progress comment ID mechanism (.cascade-progress-comment-id) with an env var (CASCADE_PROGRESS_COMMENT_ID), following the existing CASCADE_* naming pattern.

  • progressState.ts — Fully rewrites all functions to use process.env.CASCADE_PROGRESS_COMMENT_ID instead of reading/writing a file. Removes all fs imports, STATE_FILE_NAME constant, and repoDir parameters.
  • pmPoster.ts — Removes repoDir from PMProgressPosterConfig, removes maybeWriteStateFile() helper, and calls writeProgressCommentId(cardId, commentId) directly (no repoDir).
  • progressMonitor.ts — Updates start() to call writeProgressCommentId(cardId, commentId) without repoDir guard, and updates stop() to call clearProgressCommentId() with no args.
  • env.ts — Adds CASCADE_PROGRESS_COMMENT_ID to ALLOWED_ENV_EXACT so it passes through to Claude Code subprocesses.
  • secretBuilder.ts — Adds injectProgressCommentId() helper to inject the pre-seeded ack comment ID into projectSecrets for the subprocess.
  • adapter.ts — Calls injectProgressCommentId() after building project secrets so the subprocess gets the env var from startup (pre-seeded case, ~90% of runs).
  • hooks.ts — Removes STATE_FILE_NAME import and the filter that excluded the state file from uncommitted-changes detection.
  • .gitignore — Removes .cascade-progress-comment-id entry (no longer written to disk).
  • Tests — All test files updated to use env-var-based assertions; file-based tempDir setup removed.

Test plan

  • All 3801 unit tests pass
  • Lint passes with zero errors
  • TypeScript typecheck passes with zero errors
  • progressState.test.ts — new env-var read/write/clear tests
  • pmPoster.test.ts — updated to remove repoDir from fixtures
  • progress.test.ts — updated integration tests use new no-arg signatures
  • postComment.test.ts — no changes needed (already used no-arg signatures)
  • claude-code-hooks.test.ts — removed .cascade-progress-comment-id filter tests

Known limitation

Env vars set after subprocess start aren't visible to it. For the pre-seeded case (~90% of runs), the env var is injected into projectSecrets before subprocess launch — works perfectly. For the dynamic case (postInitial() fires after subprocess start), the env var is set in the parent process only — this is an accepted gap (same behavior as before since the file was also only visible due to shared filesystem, not process injection).

Card: https://trello.com/c/69abd4249587f02974b0c3d6

🤖 Generated with Claude Code

Cascade Bot and others added 2 commits March 7, 2026 07:51
The file-based progress comment ID mechanism has been replaced with the
CASCADE_PROGRESS_COMMENT_ID env var. Remove the previously tracked state
file and its .gitignore entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean, well-scoped migration from file-based to env-var-based progress comment state. The implementation is correct, all tests pass, and the known limitation (dynamic case cross-process visibility) is properly documented and was already present in the previous design.

Should Fix

  • src/backends/secretBuilder.ts:79 — The env var name CASCADE_PROGRESS_COMMENT_ID is hardcoded as a string literal instead of importing ENV_VAR_NAME from progressState.ts. Same in src/backends/claude-code/env.ts:31. If the name ever changes, it would need updating in three places. Consider importing the constant.

  • Missing tests for injectProgressCommentId — The existing secretBuilder.test.ts covers augmentProjectSecrets and resolveGitHubToken but the new injectProgressCommentId function has no unit tests. It would be good to add tests for the three cases: (1) string ackCommentId with cardId → injects, (2) numeric ackCommentId → skips, (3) missing cardId → skips.

Nitpick

  • ProgressMonitorConfig.repoDir is now deadrepoDir is still defined in the interface (line 39 of progressMonitor.ts) and still passed by buildProgressMonitorConfig in adapter.ts (line 174), but this.config.repoDir is never read in the ProgressMonitor class. Consider removing it from the interface and the config builder in a follow-up.

Comment thread src/backends/secretBuilder.ts Outdated
ackCommentId: string | number | undefined,
): void {
if (cardId && typeof ackCommentId === 'string' && ackCommentId) {
projectSecrets.CASCADE_PROGRESS_COMMENT_ID = `${cardId}:${ackCommentId}`;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This hardcodes the env var name as a string literal. Consider importing ENV_VAR_NAME from progressState.ts to keep a single source of truth. Same applies to env.ts line 31.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — both secretBuilder.ts and env.ts now import ENV_VAR_NAME from progressState.ts instead of hardcoding the string literal. Single source of truth for the env var name.

if (cardId && typeof ackCommentId === 'string' && ackCommentId) {
projectSecrets.CASCADE_PROGRESS_COMMENT_ID = `${cardId}:${ackCommentId}`;
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No unit tests for injectProgressCommentId. The existing secretBuilder.test.ts has thorough coverage for the other two exports — adding a few cases (string ackCommentId with cardId injects, numeric ackCommentId skips, missing cardId skips) would maintain the same standard.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 5 unit tests for injectProgressCommentId in secretBuilder.test.ts, covering all branches: string ackCommentId with cardId (injects), numeric ackCommentId (skips), missing cardId (skips), undefined ackCommentId (skips), and empty string ackCommentId (skips).

Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean, well-scoped refactor that replaces file-based state with an env var, reducing filesystem side-effects and simplifying the API. The implementation correctly covers both the pre-seeded path (via projectSecrets injection before subprocess launch) and the dynamic path (in-process process.env mutation). CI is green.

Should Fix (non-blocking)

  • Dead repoDir property: ProgressMonitorConfig.repoDir (progressMonitor.ts:39) is still declared and still passed from buildProgressMonitorConfig (adapter.ts:174), but nothing inside ProgressMonitor reads this.config.repoDir anymore. This is harmless dead code, but removing it would complete the cleanup and prevent confusion about whether it's still needed. Minor enough to leave for a follow-up.

@zbigniewsobiecki
Copy link
Copy Markdown
Member

@aaight address code review concerns

Cascade Bot and others added 4 commits March 7, 2026 08:07
- Import ENV_VAR_NAME from progressState.ts in secretBuilder.ts and env.ts
  instead of hardcoding 'CASCADE_PROGRESS_COMMENT_ID' string literal
- Add 5 unit tests for injectProgressCommentId covering: string ackCommentId
  with cardId injects, numeric ackCommentId skips, missing cardId skips,
  undefined ackCommentId skips, empty string ackCommentId skips

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…state

Tests from dev branch (PR #637) used old file-based signatures for
writeProgressCommentId and clearProgressCommentId. Updated to match
the new env-var-based API (no repoDir parameter).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The file may still be created by running cascade processes (e.g. the
orchestrator session itself). Keeping the gitignore entry prevents it
from appearing as an uncommitted change and triggering the stop hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean, well-executed refactoring. The file-based → env-var migration is correct and simplifies the codebase significantly (removes all fs operations, .gitignore entries, and stop-hook filtering for the state file). All 148 related tests pass.

Minor Cleanup (not blocking)

repoDir in ProgressMonitorConfig (progressMonitor.ts:39) is now entirely unused — it's still set in buildProgressMonitorConfig() (adapter.ts:174) but never read by ProgressMonitor or any delegate. Consider removing it in a follow-up to avoid confusion about whether it's still needed.

Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean, well-structured migration from file-based state to env-var-based state for progress comment IDs. The change correctly addresses the cross-process communication need for the pre-seeded case (~90% of runs) via projectSecrets injection, and honestly documents the accepted gap for the dynamic case. All 139 relevant tests pass, CI is green, and the prior review feedback has been addressed.

Code Issues

Should Fix

  • ProgressMonitorConfig.repoDir is now dead — it's still declared in progressMonitor.ts:39 and still set in adapter.ts:174 (buildProgressMonitorConfig), but is never read by ProgressMonitor after this PR. Consider removing the field from the interface and the assignment in buildProgressMonitorConfig to avoid confusing future readers into thinking it's still relevant to progress state.

  • secretBuilder.ts:80 duplicates the ${cardId}:${ackCommentId} format string from progressState.ts:26. Since injectProgressCommentId writes to a Record<string, string> (not process.env), it can't reuse writeProgressCommentId directly — but extracting a formatProgressCommentValue(workItemId, commentId) helper into progressState.ts would keep the format as a single source of truth. Minor, since the format is trivial.

@zbigniewsobiecki zbigniewsobiecki merged commit 5025f1b into dev Mar 7, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants