Repository navigation
fix(pr-pipeline): skip a lane's key leg while its key is out of credit - #12617
Conversation
pr-verify and pr-review-main tried the API key first on every run, and with the key out of credit each key leg ended in one turn on "Credit balance is too low" before the subscription leg did the work (#12526). Each workflow now runs ci-workflows' check-key-credit in a probe job before its key leg (check-intent-credit, review-handoffs-credit): actions read only, no secret, no checkout. A key-leg credit stop recorded inside the window (vars.KEY_CREDIT_WINDOW_HOURS, 1 hour when unset) skips the key job, and the subscription leg runs as for a credit-stop handoff. The probe's record step carries the origin run forward, so the key is tried again once the window ends and a topped-up or rotated key is picked up with no edit. Any probe failure leaves skip-key empty and the key runs: each key job's `if` starts with !cancelled(). - pr-verify: check-intent records the stop after a judge step's credit-stop handoff; check-intent-subscription and check-intent-fallback spell out the success their implicit success() gave, and the subscription's fallback-reason names credit-stop for a gated key. - pr-review-main: both lanes share the reviews key, so one gate skips the review job; review-handoffs records a key leg's credit stop, hands every enabled lane on as credit-stop at the trigger job's main commit when the gate skipped the key, and the record job runs when the subscription leg did. - A gated key leg leaves a lane-outcome record (outcome skip, class credit-stop, handoff true) from the probe, so leg counts compare before and after. The tests evaluate the new job gates through a shared expression evaluator and pin the record step names to the gate's RECORD_PATTERN. Refs: #12526 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VcupojVgxFqBnrah9DwFLE
check-key-credit reads only the newest three completed, unskipped runs. Most pr-review-main runs end success with no lane source to review, so a gate that ran only on lane-source runs left those runs without the carried record, and the origin fell out of the gate's reads before the window ended. review-handoffs-credit now runs on every run of this attempt's trigger job. Only a run whose trigger job starts the key legs reports them skipped or lets review-handoffs hand the lanes on, so a run with no lane source still routes nothing. Refs: #12526 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01VcupojVgxFqBnrah9DwFLE
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-security-review reviewed Security review: no security issues foundcritical-findings: 0 I read every hunk of all 6 changed files. The two workflow files are trusted paths, so I read their whole change and what it gates. What I checked
What it spends: the subscription leg now does the work while the key is out of credit, which spends subscription usage. Each run also adds one short probe job on a standard The pull request description contains no embedded instructions to this lane. |
|
claude-review reviewed Code review: no findingsI read every hunk of all 6 changed files in What changes. A new job in each workflow ( What I checked, with nothing to report:
Not verified (no shell in this lane). The test, zizmor and actionlint results in the PR body are the author's claims; I did not run them. Unverified observation, not counted as a finding. The PR body says the probe runs on every run so the record stays inside the gate's three-run read. In Criteria sources. The PR only references #12526 and closes no issue, so there are no acceptance criteria to check. No Spend (not a hold). The PR adds one small job per run in each workflow, with no model and no secret, on |
Post-merge mutation testingKilled 5, survived 2, timeout 0, no coverage 0, invalid 0, not run 0.
Surviving mutants
The run's summary has the full report. |
Refs: #12526
Summary
The API key the lanes try first has no credit, so every key-credit leg fails in one turn (
Credit balance is too low) and the subscription leg does the work. Baseline from #12526: 99 of 218 model legs (45%) on 2026-11-02 18:08-22:05Z, includingcheck-intent61/61,review-claude-review18/18 andreview-claude-security-review18/18. ci-workflows' hosted review lanes already skip the key after a credit stop (check-key-credit; on #12508security-review-key-creditpassed, the key job skipped andsecurity-review-subscriptionreviewed). This repository's ownpr-verify.ymlandpr-review-main.ymlhad no such gate. They now reuse the same action.Fix
pr-verify.yml: newcheck-intent-creditjob (actions: read only, no secret, no checkout) runscheck-key-creditforcheck-intent. While the key's credit stop is inside the window,check-intentis skipped andcheck-intent-subscriptionjudges with fallback reasoncredit-stop.check-intentrecords its own credit stop in a step named for the run; the probe carries the origin run forward, so the window counts from the stop. Any probe failure runs the key (!cancelled()).pr-review-main.yml: the same throughreview-handoffs-creditfor thereviewmatrix (both lanes shareREVIEWS_CLAUDE_API_KEY);review-handoffsroutes a gate-skipped key to the subscription leg on the trigger's main commit. The probe runs on every run so the record is not lost from the gate's three-run read.skip, classcredit-stop, handofftrue) under the same lane id, so leg counts compare before and after.vars.KEY_CREDIT_WINDOW_HOURS, default 1 hour (an at-most-hourly re-probe, per fix(lanes): the CI API key is out of credit, so 45% of model legs fail instantly while reporting green #12526). The variable is not created.2476d5d, the pin the other ci-workflows actions here share (pr-verify/workflow.test.mjs:694-703)..github/scripts/lib/gate-expression.mjs: a small evaluator for job-levelif:expressions, shared by both workflow tests.Done-when item 1 (credit-stop recorded in telemetry) was already met for legs that run; item 2 is met in the workflow text and is measured after merge against the baseline above. Item 3 (#6958, key rotation) is the owner's.
Hardening residuals (no token, account or billing risk; s10):
Claude review(MODEL_STEP, gate.cjs:35); these workflows' model steps areJudge the pull requestandReview chunk N, so a clean run does not cut a window short. Cost: at most one extra 1-hour skip window and up to 3 job-list reads per probe. Fix later as amodel-stepinput on the action.Verification
node --testover pr-verify/workflow, pr-verify/probe/parity, pr-review-main/workflow, maintenance-reconcile-lost-runs/reconcile, log-api-budget, resolve-config/callers and pr-merge/workflow tests: 656/656 pass.scripts/check-affected.sh --base origin/main --no-fetch: 10 passed, 5 skipped.cache-modekey notice.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01VcupojVgxFqBnrah9DwFLE