Skip to content

feat(cli): let the agent finish an upgrade the user started - #609

Merged
theCodeDrift merged 3 commits into
fix/environment-steps-run-initfrom
fix/agent-applies-rules-after-upgrade
Nov 4, 2026
Merged

theCodeDrift merged 3 commits into
fix/environment-steps-run-initfrom
fix/agent-applies-rules-after-upgrade

Conversation

@theCodeDrift

@theCodeDrift theCodeDrift commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Stack (root → tip):

Stacked on #608. Moving the CLI stays the user's decision. This makes the rest of the flow work around that decision.

The user upgrades, then the agent applies the rules

  • The cli and skill steps stay the user's. They name init, and say that in a terminal the same command without init opens the installer.
  • A rules step on its own is now the agent's: it runs the command and follows the recipe to the last step. If the command is refused, it goes to the user.
  • Beside an upgrade, the rules step waits for the confirming agent ok, because a newer CLI can owe a different reconcile.
  • The passage explains declining: the project stays on this CLI, the report keeps listing the upgrade, and rules owed on this CLI still get applied.
  • A launcher run names npx for the upgrade rather than the agent-fill marker.

The instruction fits the harness
agent ok recognizes the harness from a fixed table of environment variables and shows the command with the prefix that harness documents. Detection shapes wording only, and no environment value reaches the output. Another terminal is always offered.

Harness Offered Detected by
Claude Code CLI ! CLAUDECODE, with CLAUDE_CODE_ENTRYPOINT being cli or unset
Cursor /shell , stating its 30-second limit CURSOR_AGENT
OpenCode ! OPENCODE
Codex ! CODEX_THREAD_ID, which is undocumented
Gemini CLI ! GEMINI_CLI
Devin ! AI_AGENT starting devin_

Crush, the Claude Code VS Code extension, and anything unrecognized get another terminal only. Only the Claude Code variables were observed live. The rest come from each product's docs or source, and a miss falls back to the terminal.

check's notice keeps its plain commands.

@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 4m 36s —— View job


Review complete

Review mode: incremental — read 0 prior review thread(s) before reviewing. The .prior-review.json snapshot contained no prior review threads, no review summaries, and no top-level comments other than the @claude /review trigger itself, so this is the first review of this PR.

  • Read prior review data
  • Fetch PR diff and metadata
  • Review core logic (harness-shell.ts, recipes.ts, agent.ts, freshness.ts)
  • Review tests
  • Review spec/doc changes (openspec, SKILL.md)
  • Post inline comments for findings
  • Post final summary

Findings

One inline comment posted:

  • [New] packages/cli/test/agent-ok.test.ts:150 — vi.stubEnv("CLAUDECODE") is called with no value, unlike every other stubEnv call in the file. Assigning to process.env coerces the value to the string "undefined" rather than actually unsetting it (this is documented Node.js behavior), so env.CLAUDECODE !== undefined stays true. Since the Claude Code entry in HARNESS_SHELLS (src/detect/harness-shell.ts) is checked before Cursor's and still matches (CLAUDECODE set, CLAUDE_CODE_ENTRYPOINT unset defaults to "cli"), the test ends up exercising the Claude Code branch rather than Cursor's — the opposite of what it claims to test. Production detection is unaffected; this is a test-only defect.

Everything else

  • detectHarnessShell's fixed-table approach (harness-shell.ts) matches its design doc: no environment value reaches rendered output, every row is sourced from a comment citing where the variable/prefix is documented, and an unrecognized or falsely-recognized harness only ever downgrades to "another terminal" — never a wrong authorization.
  • environmentStatusBlock (prompts/recipes.ts) correctly branches on rulesOwed/personOwed/upgradeOwed: the agent applies the rules step on its own only when nothing else is owed, waits for a confirming agent ok when a CLI/skill step is also owed, and the decline explanation is scoped to the cli part only, matching the proposal's intent. Cross-checked against the new prompts.test.ts cases and the archived spec scenarios — all consistent.
  • freshness.ts's new INSTALLER_NOTE is appended to exactly one command-bearing step when both cli and skill are out of date (the skill step defers to the cli step's command), so the note isn't duplicated.
  • package-manager.ts's projectLauncher export and agent.ts's npx-on-launcher-run logic match the stated design rationale (a project launcher hides how the CLI was first installed).
  • installed-documentation.test.ts assertions compare against whitespace-normalized prose (skill.replaceAll(/\s+/g, " ")), so the line-wrapped phrases in SKILL.md (e.g. "declines an\nupgrade") still match correctly — initially looked suspicious but isn't.
  • Could not run the build/lint/test suite in this environment (review-only, no code execution permissions beyond read-only inspection) — the single test-logic issue above was found by tracing the code paths rather than by running the suite, so it's worth confirming against an actual CI run.

Comment thread packages/cli/test/agent-ok.test.ts Resolved
@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 4m 36s"
#609 (comment)

The one finding is fixed in 314af3b and its thread is resolved. The typecheck failure was that same line; nothing else in the summary needs a change.

— AI Coding Agent

agent ok told the agent to hand every step to the user. Moving the CLI stays the user's decision, but the rules step runs the recorded version, so the agent now applies it once no upgrade is pending, and explains what declining means.
agent ok named Claude Code's ! prefix to every agent. It now recognizes the harness from a fixed table of environment variables, for wording only, and shows the command with the prefix that harness documents. Another terminal is always offered.
The call took one argument, which failed typecheck. Passing undefined keeps
what it meant: vitest deletes the variable, so the Cursor branch runs even
when the suite is itself inside Claude Code, where CLAUDECODE is set.
@theCodeDrift
theCodeDrift force-pushed the fix/agent-applies-rules-after-upgrade branch from 314af3b to e8ee2ee Compare November 4, 2026 20:23
@theCodeDrift
theCodeDrift added this pull request to stack #610 November 4, 2026 20:33
@theCodeDrift
theCodeDrift merged commit 02157a2 into main Nov 4, 2026
4 checks passed
@theCodeDrift
theCodeDrift deleted the fix/agent-applies-rules-after-upgrade branch November 4, 2026 20:33
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.

1 participant