Repository navigation
fix(run-claude-cli)!: run the subscription leg as its own job - #803
Conversation
run-claude-cli now runs one leg per invocation: exactly one of api-key and subscription-token must be set, and the in-step fallback is gone. A key leg that ends in a credit stop sets lane-class `credit-stop`, written after the step files are cut back. intake-triage runs the key in the claude job and the token in a new claude-intake-triage-subscription job on ubuntu-24.04, gated on an exact `credit-stop` (or an empty key), with a fresh checkout and the same hardening, and no artifact or cache from the first job. Only the job that triaged applies and reports; claude-intake-triage-status reports the one outcome. Caller inputs and secrets are unchanged. verifyManagedSettings also requires allowManagedHooksOnly or disableAllHooks, and apply-claude-managed-settings refuses settings that set neither. BREAKING CHANGE: run-claude-cli fails closed when both api-key and subscription-token are set, and reports a key-leg credit stop as lane-class `credit-stop` instead of `rate-limit`. Callers that relied on the in-step fallback run the subscription leg as a second job (README, two-job pattern). Closes #799 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q6B1MWhz73WFRYyyrKjtjY
…rsion The step's file-command files are now bound read-only in the leg's bwrap mount namespace, so a process the leg leaves behind cannot write them after the leg ends. After the leg they are restored to their exact content, not just their size, before the launcher writes its own outputs. The CLI version defaults to 2.1.304 in run-claude-cli and intake-triage instead of latest. The intake header also notes that rerunning only the subscription job does not rerun the author gate. Refs #799 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q6B1MWhz73WFRYyyrKjtjY
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @kyle-sexton's task in 9m 54s —— View job Security review
No security findings. This review (and an independent adversarial hunter pass) found no issue meeting the high-signal, concrete-exploit-path bar. GitHub Actions hardening concerns (dangerous triggers, expression injection, permission widening, action pins) are zizmor's lane and out of scope here. What I checked:
One sub-finding-grade observation, not raised as a finding (no attacker-reachable path on a standard GitHub-hosted runner): |
|
Claude finished @kyle-sexton's task in 4m 30s —— View job Code reviewNo blocking or high-signal findings. This is a careful, narrowly-scoped
Two notes, neither blocking:
|
|
claude-review has reviewed this pull request through 9ce02f5; a later push is reviewed from there. |
|
claude-security-review has reviewed this pull request through 9ce02f5; a later push is reviewed from there. |
Closes #799
Summary
Runs the API-key leg and the subscription leg as separate jobs instead of two legs of one step, per the design decision on #799.
run-claude-clinow runs one leg per invocation, andintake-triagesplits into a key job and a subscription job.Fix
run-claude-cli: exactly one ofapi-keyandsubscription-tokenmust be set (fails closed on none or both); the in-step fallback loop is removed. A key leg that ends in a credit stop setslane-classtocredit-stop, still written after the launcher cuts back the step files.verifyManagedSettingsalso requiresallowManagedHooksOnly: trueordisableAllHooks: true;apply-claude-managed-settings(whose default already setsallowManagedHooksOnly) refuses settings that set neither.intake-triage.yml:claude-intake-triage(caller's runner) runs the key leg only.claude-intake-triage-subscriptionruns only when that job'slane-classis exactlycredit-stop(or its key was empty), on a fixedubuntu-24.04runner, with a fresh checkout and the same managed-settings, sudo/docker removal and bubblewrap steps. It takes no artifact or cache from the first job, and it is the only job that references the OAuth secret.claude-intake-triage-statusreads both jobs and reports one outcome.README: documents single-leg use and the two-job pattern for callers.
Review follow-ups:
npm viewreturned on 2026-10-20, instead oflatest.Breaking for direct
run-claude-clicallers: passing both credentials now fails, and a key credit stop reportscredit-stopinstead ofrate-limit. Versioning: this repository keeps no changelog file and cuts SemVer tags withrelease-tag.yml; the!title marks the break, and the release after merge should take the breaking bump (onv0.x, a minor bump per the README). The pr-verify migration in claude-code-plugins follows that release and pins to it.Verification
node --test .github/scripts/*.test.cjs: 471 pass, 0 failnode --test .github/actions/report-lane-outcome/*.test.cjs .github/actions/run-claude-cli/*.test.cjs: 88 pass, 0 fail, 0 skipped, including a background process that tries to appendlane-class=credit-stopafter the leg ends (it gets EROFS and the output keeps the launcher's value) and a same-size rewrite that is put back byte for byterunrefuses both before any leg starts)credit-stoplane-classruns-on, its exact gate, no artifact or cache, steps equal to the key job's but for the credential, and the status job's outcome selectionruns-on, the status class mapping and the exactly-one rule each made the new tests fail.actionlint,zizmor --config .github/zizmor.yml .(no findings),biome ci,markdownlint-cli2 README.md,typos,editorconfig-checkerand composite-run shellcheck: all clean.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01Q6B1MWhz73WFRYyyrKjtjY