Repository navigation
ci(lanes): run the maintenance eval and propose lanes on the three-leg chain - #13626
Conversation
…g chain The maintenance role's lanes now run its API key, then its subscription token, then FALLBACK_CLAUDE_CODE_OAUTH_TOKEN, one credential per job or step, with the check-key-credit gate and a lane-outcome record per leg. - maintenance-measure-skill-edit.yml propose: a key leg before the subscription leg, a propose-key-credit gate, and the key's credit-stop marker. - eval-hill-climb-pass.yml and eval-browser-dispatch.yml: pass and eval split into key, subscription and fallback jobs behind a credit gate. eval-handoff.mjs reads the probe's stream and every errored run's kept trace with run-claude-cli's own classifier (lane.cjs judgeLeg and classify.cjs isCreditStop at b8bdd7f) and hands off on the same stops. - lane-funding.json, the retention table and the guard tests follow; the maintenance LEG_EXEMPTIONS entries are gone. Refs: #13586 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…full-chain # Conflicts: # .github/actions/resolve-config/callers.test.mjs
…exit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. |
💡 Codex ReviewIf an eval crashes or is interrupted before writing its results JSON, ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
claude-review reviewed Incremental code review: ec5bbea → ae1e5ce (blocking only)No blocking findings in this push. This lane already reviewed an earlier head of this PR, so this round reports blocking findings only and drops advisory ones. This push changed one file, What changed
Checks
Prior and settled
VerificationI ran nothing. The "257/257 pass" in the owner's reply is the author's claim and was not checked here. Other checks
|
|
claude-security-review reviewed Security review of PR #13626, changes from ec5bbea to ae1e5ceWhat I reviewed. One file changed since the last head this lane reviewed: Result: no security issues found. critical-findings: 0 What changed and what I checked
Prior findingsThe earlier SUGGESTION on SpendNone. The change is test-only. |
…lassifier in CI The real-classifier cases skipped unless a local ci-workflows checkout was named, so a run-claude-cli pin bump that reshaped judgeLeg's return passed every test. The test now fetches lane.cjs, classify.cjs and their helper at the pin the eval workflows check out, checks every leg names that one pin, and asserts the fields eval-handoff reads: failureClass, resets and the last message's api_error_status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The pr-verify verifier failed head What it wrote (36 lines)This pull request leaves the merge queue, and ci-status holds it out while it carries |
…l and probe steps The claude-cli clause of readsFallback accepted the fallback token in any `claude <anything>` run step of any lane. It now accepts it only when every step that reads it is a `claude plugin eval` run or that job's `probe` step, each as CLAUDE_CODE_OAUTH_TOKEN, and a fixture shows any other step on the token failing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs: #13586
Summary
The maintenance role's lanes move onto the chain every other model lane runs: role API key, then role subscription token, then
FALLBACK_CLAUDE_CODE_OAUTH_TOKEN. Each lane also gets thecheck-key-creditgate and a lane-outcome record per leg. The owner decided in #13586 to add the maintenance key (Q2, "You add a maintenance key (Recommended)") and to make every lane "consistent and uniform".MAINTENANCE_CLAUDE_API_KEYis now an org secret.maintenance-measure-skill-edit.ymlproposepropose-key-creditgateeval-hill-climb-pass.ymlpass(pass-a, pass-a2, pass-b)pass,pass-subscription,pass-fallbackjobs behind a newgatejobeval-browser-dispatch.ymlevaleval,eval-subscription,eval-fallbackjobs behind a neweval-key-creditjobFix
How the eval passes hand off.
claude plugin evaldoes not launch throughrun-claude-cli, so the new.github/scripts/plugin-eval/eval-handoff.mjsreadsclaude plugin eval's output with run-claude-cli's own classifier (option (a) in the issue).b8bdd7f):lane.cjsforjudgeLegandlinesToMessages,classify.cjsforisCreditStop, and one helperlane.cjsloads.lane.cjshandoffReason, which is not exported:--thresholdalso exits 1.traceas "The session as JSON, one message per line".--keep-temprun on Claude Code 2.1.318 kept a trace with the SDK'ssystem/assistant/rate_limit_event/resultmessages, and itsresultcarriedis_errorandapi_error_status.ANTHROPIC_API_KEYexited 2 withpartial: true, partialReason: auth_failed. Its one run haderror: "exit 1: Invalid API key"and a trace whoseresulthadapi_error_status: 401, andeval-handoff.mjshanded that off asauthon the key leg.partial. So the per-run traces are where a limit or credit stop shows.Credentials. The eval reads the provider credentials from its environment (plugin-evals, Run evals in CI: "credentials in the environment such as
ANTHROPIC_API_KEY").LANE_API_KEY, and the script exports it asANTHROPIC_API_KEYand unsetsLANE_API_KEYbeforeclauderuns, soCLAUDE_CODE_SUBPROCESS_ENV_SCRUBstrips it from Bash subprocesses. callers.test.mjs reads anyANTHROPIC_*env name as a secret, which is why the step env does not use it directly.CLAUDE_CODE_OAUTH_TOKEN.The probe now writes
--output-format stream-json --verbose, so a credit or limit stop in it is classified the same way. The stream'sresultline still carriespermission_denials, which the deny checks read withjq -s 'last(...)'. A probe that ends on the credential's own stop hands off instead of failing red. The leak check runs first and now checks for the leg's own credential.Legs.
--scaffoldand, on dispatch,Bash(...)grants, so each eval leg is its own job, held equal to the key leg's steps by a shape test, as the tidy lane is.proposestays one job. Its model has Read, Grep and Glob only, no Bash (run-claude-cli's one-job rule), following adjudicate-feedback.Credit gate.
key-credit-stop-<workflow>-<key job>after a credit stop.eval-hill-climb-pass.ymlis a called workflow whosegithubcontext is the caller's (Reusing workflow configurations: "thegithubcontext is always associated with the caller workflow"), so its marker iskey-credit-stop-maintenance-measure-skill-edit.yml-pass.continue-on-error.actions: readonly, and the pass callers grantactions: readfor theirs.Telemetry.
report-lane-outcomerecord withlane-id, credential, outcome, handoff and fallback reason.durationMsandcostUsdcome from an execution file of oneresultmessage that carries the suite's owndurationSecondsandcostUsdand nothing a run wrote.outcome: skip,class: credit-stop,handoff: truerecord.Catalog and tests.
lane-funding.jsonlists the new legs, and.github/artifact-retention.jsonhas a row for each of the three new markers.LEG_EXEMPTIONSentries are gone, along with theproposeentry inRECORDLESS_LEGS.claude plugin evalleg (theclaude-clilauncher) reading the role key, and the fallback token reaching such a leg'sclaudesteps or the eval pass workflow.hill-climb-workflow.test.mjs's run-claude-cli count goes from 2 to 3, for the new key step;$credential;steps.judge.outputs.handoff != 'true'.Verification
Node suites.
node --test ".github/scripts/**/*.test.mjs" ".github/actions/**/*.test.mjs"(this covers.github/scripts/lib): 8210 tests, 8207 pass, 0 fail, 3 skipped. The 3 skipped are the real-classifier cases ineval-handoff.test.mjs, which needEVAL_HANDOFF_CI_WORKFLOWS.Real classifier. With
EVAL_HANDOFF_CI_WORKFLOWSpointing at the three files atb8bdd7f,eval-handoff.test.mjsran 7 of 7, using the observed spend-limit and rejected-key shapes from ci-workflowsclassify.test.cjs.callers.test.mjs. 256 pass after merging main. A shape mutation in
pass-fallbackfails the new leg test.Bash suites:
write-runner-never-rules.test.shcheck-artifact-retention.test.shcheck-app-key-references.test.shcheck-read-caller-keys.test.shcheck-lane-coverage.test.shcheck-scan-carrier-secret-shadow.test.shworkflow-self-paths.test.shcredential-sweep.test.shrun-zizmor.test.shci-review-lanes.test.shplan-test-lanes.test.shaffected-tests-live.shGates, all clean:
runner-policy.mjs --root .(passed, so no standards contract change is needed);check-read-caller-keys.sh,check-app-key-references.shandcheck-artifact-retention.sh --check(120 uploads, 82 families);check-test-tmp-cleanup.sh,check-silent-skips.sh,check-discriminating-test-skips.shandcheck-lane-coverage.sh --check.Simulated probe steps. The rendered probe steps of both workflows ran in bash with a stub
claude, which also confirmedLANE_API_KEYnever reachesclaude:Remaining
actions/checkoutof the publicmelodic-software/ci-workflowsat a pinned SHA with the job token;rejectedrate_limit_eventin an eval trace: the limit-stop rule is tested on fixtures, and a real trace showed only anallowedevent.LEG_EXEMPTIONSentry follow in ci(lanes): run the mutation lane on run-claude-cli, mutants in a job with no secret #13632, the last pull request for that issue.Related
🤖 Generated with Claude Code