From 8f8d951fda9295ee5c59a2bda2e769a4e14f130b Mon Sep 17 00:00:00 2001 From: garrytan Date: Sat, 17 Oct 2026 02:32:30 +0000 Subject: [PATCH] refactor: move the release-path result codes to lib/result-codes-release.ts (module-size ratchet); fit the periodic plan's 38 slices Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- .github/workflows/evals-periodic.yml | 6 +- bin/gstack-doctor-components.sh | 26 ++++----- lib/result-codes-release.ts | 79 ++++++++++++++++++++++++++ lib/result-codes.ts | 71 +---------------------- scripts/pr-dependencies.ts | 2 +- test/fixtures/module-size-ratchet.json | 1 + 6 files changed, 100 insertions(+), 85 deletions(-) create mode 100644 lib/result-codes-release.ts diff --git a/.github/workflows/evals-periodic.yml b/.github/workflows/evals-periodic.yml index de384351b..45aeae1ce 100644 --- a/.github/workflows/evals-periodic.yml +++ b/.github/workflows/evals-periodic.yml @@ -150,7 +150,7 @@ jobs: - name: Emit run manifest (ALL periodic tests minus reasoned excludes) env: EVALS_ALL: "1" - run: EVALS_TIER=periodic bun --no-install run scripts/test-paid-shards.ts --tier periodic --emit-plan /tmp/paid-plan/manifest.json --slice-budget 420 --jobs 2 --max-parallel 37 + run: EVALS_TIER=periodic bun --no-install run scripts/test-paid-shards.ts --tier periodic --emit-plan /tmp/paid-plan/manifest.json --slice-budget 420 --jobs 2 --max-parallel 38 # Codex-only slices run on the host-run eval-codex-slices job; the # container executor runs every other slice. @@ -258,7 +258,7 @@ jobs: fail-fast: false # Every planned slice starts at once; test/evals-workflow-wiring.test.ts # fails when the live plan outgrows this cap. - max-parallel: 37 + max-parallel: 38 matrix: slice: ${{ fromJSON(needs.plan-slices.outputs.periodic_slices) }} steps: @@ -397,7 +397,7 @@ jobs: packages: read strategy: fail-fast: false - max-parallel: 37 + max-parallel: 38 matrix: slice: ${{ fromJSON(needs.plan-slices.outputs.periodic_codex_slices) }} steps: diff --git a/bin/gstack-doctor-components.sh b/bin/gstack-doctor-components.sh index c34c23dc8..e0506885f 100644 --- a/bin/gstack-doctor-components.sh +++ b/bin/gstack-doctor-components.sh @@ -239,19 +239,6 @@ gstack_result_anchor() { EVAL_MODEL_DENIED) printf '%s' 'eval-model-denied' ;; EVAL_MODEL_OLD_GENERATION) printf '%s' 'eval-model-old-generation' ;; EVAL_MODEL_GENERATION_UNRESOLVED) printf '%s' 'eval-model-generation-unresolved' ;; - POLICY_GSTACK_TOO_OLD) printf '%s' 'policy-gstack-too-old' ;; - QUEUE_NOT_READY) printf '%s' 'queue-not-ready' ;; - QUEUE_PROOF_MISSING) printf '%s' 'queue-proof-missing' ;; - QUEUE_STAMP_NOT_STAMP_ONLY) printf '%s' 'queue-stamp-not-stamp-only' ;; - QUEUE_VERIFY_MISMATCH) printf '%s' 'queue-verify-mismatch' ;; - QUEUE_GATE_MISSING) printf '%s' 'queue-gate-missing' ;; - GATE_AHEAD_ATTEMPT_INVALID) printf '%s' 'gate-ahead-attempt-invalid' ;; - PREGATE_TIMING_ASSERTION) printf '%s' 'pregate-timing-assertion' ;; - APPROVAL_CLASSES_INVALID) printf '%s' 'approval-classes-invalid' ;; - APPROVAL_CLASS_FOUND) printf '%s' 'approval-class-found' ;; - APPROVAL_CITATION_MISSING) printf '%s' 'approval-citation-missing' ;; - APPROVAL_SOURCE_UNAVAILABLE) printf '%s' 'approval-source-unavailable' ;; - STATE_MATRIX_INCOMPLETE) printf '%s' 'state-matrix-incomplete' ;; DX_CAPTURE_USAGE) printf '%s' 'dx-capture-usage' ;; DX_CAPTURE_BAD_DEADLINE) printf '%s' 'dx-capture-bad-deadline' ;; DX_CAPTURE_BAD_MAX_BYTES) printf '%s' 'dx-capture-bad-max-bytes' ;; @@ -266,6 +253,19 @@ gstack_result_anchor() { DX_CAPTURE_INTERRUPTED) printf '%s' 'dx-capture-interrupted' ;; DX_CAPTURE_REDACTION_FAILED) printf '%s' 'dx-capture-redaction-failed' ;; DX_CAPTURE_INTERNAL) printf '%s' 'dx-capture-internal' ;; + POLICY_GSTACK_TOO_OLD) printf '%s' 'policy-gstack-too-old' ;; + QUEUE_NOT_READY) printf '%s' 'queue-not-ready' ;; + QUEUE_PROOF_MISSING) printf '%s' 'queue-proof-missing' ;; + QUEUE_STAMP_NOT_STAMP_ONLY) printf '%s' 'queue-stamp-not-stamp-only' ;; + QUEUE_VERIFY_MISMATCH) printf '%s' 'queue-verify-mismatch' ;; + QUEUE_GATE_MISSING) printf '%s' 'queue-gate-missing' ;; + GATE_AHEAD_ATTEMPT_INVALID) printf '%s' 'gate-ahead-attempt-invalid' ;; + PREGATE_TIMING_ASSERTION) printf '%s' 'pregate-timing-assertion' ;; + APPROVAL_CLASSES_INVALID) printf '%s' 'approval-classes-invalid' ;; + APPROVAL_CLASS_FOUND) printf '%s' 'approval-class-found' ;; + APPROVAL_CITATION_MISSING) printf '%s' 'approval-citation-missing' ;; + APPROVAL_SOURCE_UNAVAILABLE) printf '%s' 'approval-source-unavailable' ;; + STATE_MATRIX_INCOMPLETE) printf '%s' 'state-matrix-incomplete' ;; *) return 1 ;; esac } diff --git a/lib/result-codes-release.ts b/lib/result-codes-release.ts new file mode 100644 index 000000000..1e929a5dc --- /dev/null +++ b/lib/result-codes-release.ts @@ -0,0 +1,79 @@ +/** + * Result codes for the release path: gstack-ship-queue and the ship-policy + * floor, pregate timing, approval classes and the state-machine matrix. Kept + * beside lib/result-codes.ts (which spreads this table into RESULT_CODES) so + * the owner module stays within the module-size ratchet; the same rules apply: + * one stable docs/troubleshooting.md anchor, a summary and a fix clause each. + */ +import type { ResultCode } from './result-codes'; + +export const RELEASE_RESULT_CODES = { + // Field list 2, W1: gstack-ship-queue and the ship-policy compatibility floor. + POLICY_GSTACK_TOO_OLD: { + anchor: 'policy-gstack-too-old', + summary: 'the ship policy sets min_gstack_version above this gstack, so this gstack refuses to read it', + fix: 'upgrade gstack (bin/gstack-upgrade, or the session install with --for ) to the version named, then rerun', + }, + QUEUE_NOT_READY: { + anchor: 'queue-not-ready', + summary: 'the lane is not ready to report: the working tree, HEAD or CI state does not match the pushed PR head', + fix: 'commit and push the work (or wait for CI on that exact head), then rerun gstack-ship-queue ready', + }, + QUEUE_PROOF_MISSING: { + anchor: 'queue-proof-missing', + summary: 'a proof input the queue step needs is missing or does not match (gated head, base, stamp journal, version or tree)', + fix: 'supply the named input (fetch the gated head, pass the expected sha), or regate; nothing was written', + }, + QUEUE_STAMP_NOT_STAMP_ONLY: { + anchor: 'queue-stamp-not-stamp-only', + summary: 'the stamp commit differs from the gated head by more than stamps, so the gate does not cover it', + fix: 'inspect the printed residual paths; drop the stray edit, or run the gate again on the stamped head', + }, + QUEUE_VERIFY_MISMATCH: { + anchor: 'queue-verify-mismatch', + summary: 'the coordinator could not reproduce the lane’s stamp claim: the PR head, the recomputed gate-ahead merge or the gated tree differs', + fix: 'do not merge; ask the lane to rerun gstack-ship-queue stamp (or gate-ahead) on the current queue and report again', + }, + QUEUE_GATE_MISSING: { + anchor: 'queue-gate-missing', + summary: 'the policy sets full_e2e and no passing full-gate record is bound to this tree', + fix: 'run the gate the policy names (gstack-ship-queue gate-ahead, then --record) or pass the record of a passing run on this head', + }, + GATE_AHEAD_ATTEMPT_INVALID: { + anchor: 'gate-ahead-attempt-invalid', + summary: 'the gate-ahead attempt is unknown, already recorded, or its worktree no longer holds the gated commit', + fix: 'list attempts with gstack-ship-queue gate-ahead --list, then record the live one, or prepare a new attempt', + }, + // Field list 2 W4 (pregate `timing`). + PREGATE_TIMING_ASSERTION: { + anchor: 'pregate-timing-assertion', + summary: 'an added or changed test line compares an elapsed wall-clock or CPU time against a bound, or sleeps and then asserts (a warning, not a block)', + fix: 'assert on the outcome, an injected clock or a forced deadline instead; when the bound is the contract, add `gstack-timing-ok: ` in a comment on the line or the line above', + }, + // Field list 2, W2 (approval classes) and W3 (state-machine round-trip matrix). + APPROVAL_CLASSES_INVALID: { + anchor: 'approval-classes-invalid', + summary: '`.gstack/approval-classes.json` is malformed, a class matches nothing, or a path escapes the repository', + fix: 'keep `classes` a non-empty list of uniquely named classes, each with `paths`, `patterns` or `migrations: true`, and every glob repo-relative (`gstack-approval-classes validate` checks the working-tree copy)', + }, + APPROVAL_CLASS_FOUND: { + anchor: 'approval-class-found', + summary: 'the branch changes something a declared approval class covers', + fix: 'get the owner\'s approval and put `Approved by via for @` in the PR body, using the APPROVAL_SCOPE token the check printed', + }, + APPROVAL_CITATION_MISSING: { + anchor: 'approval-citation-missing', + summary: 'a declared approval class has no citation that resolves and binds to its current effects, so no receipt was written', + fix: 'add an `Approved by` line whose plan (with --approval-run ) or maintainer comment names the APPROVAL_SCOPE token or the class and every effect path; for evidence gstack cannot read, attest it with `for @` on the line. Only the owner approves: never write the line without their approval', + }, + APPROVAL_SOURCE_UNAVAILABLE: { + anchor: 'approval-source-unavailable', + summary: 'origin/ is not a resolvable commit, so the committed .gstack/approval-classes.json cannot be read and nothing was checked', + fix: 'git fetch origin (classes are never read from the working tree)', + }, + STATE_MATRIX_INCOMPLETE: { + anchor: 'state-matrix-incomplete', + summary: 'the state-machines specialist output lacks a kind × owner action cell, maps a cell to a test that does not exist, or leaves an untested cell without a CRITICAL finding', + fix: 'rerun the state-machines specialist on the same diff; its review coverage stays incomplete until gstack-state-matrix check passes', + }, +} as const satisfies Record; diff --git a/lib/result-codes.ts b/lib/result-codes.ts index 60a2528f5..d7adaf05e 100644 --- a/lib/result-codes.ts +++ b/lib/result-codes.ts @@ -10,6 +10,8 @@ * agent greps the code, never the prose. test/troubleshooting-anchors.test.ts * checks every anchor exists; add a row here before printing a new code. */ +import { RELEASE_RESULT_CODES } from './result-codes-release'; + export interface ResultCode { /** Stable `` in docs/troubleshooting.md. */ anchor: string; @@ -694,74 +696,6 @@ export const RESULT_CODES = { summary: 'the eval model rules declare families (newest generation only) and an arm names a model in none of them, so its generation cannot be checked', fix: 'add the model to its family in .gstack/eval-models.json (newest first) in a reviewed PR, or pick a model a family lists', }, - // Field list 2, W1: gstack-ship-queue and the ship-policy compatibility floor. - POLICY_GSTACK_TOO_OLD: { - anchor: 'policy-gstack-too-old', - summary: 'the ship policy sets min_gstack_version above this gstack, so this gstack refuses to read it', - fix: 'upgrade gstack (bin/gstack-upgrade, or the session install with --for ) to the version named, then rerun', - }, - QUEUE_NOT_READY: { - anchor: 'queue-not-ready', - summary: 'the lane is not ready to report: the working tree, HEAD or CI state does not match the pushed PR head', - fix: 'commit and push the work (or wait for CI on that exact head), then rerun gstack-ship-queue ready', - }, - QUEUE_PROOF_MISSING: { - anchor: 'queue-proof-missing', - summary: 'a proof input the queue step needs is missing or does not match (gated head, base, stamp journal, version or tree)', - fix: 'supply the named input (fetch the gated head, pass the expected sha), or regate; nothing was written', - }, - QUEUE_STAMP_NOT_STAMP_ONLY: { - anchor: 'queue-stamp-not-stamp-only', - summary: 'the stamp commit differs from the gated head by more than stamps, so the gate does not cover it', - fix: 'inspect the printed residual paths; drop the stray edit, or run the gate again on the stamped head', - }, - QUEUE_VERIFY_MISMATCH: { - anchor: 'queue-verify-mismatch', - summary: 'the coordinator could not reproduce the lane’s stamp claim: the PR head, the recomputed gate-ahead merge or the gated tree differs', - fix: 'do not merge; ask the lane to rerun gstack-ship-queue stamp (or gate-ahead) on the current queue and report again', - }, - QUEUE_GATE_MISSING: { - anchor: 'queue-gate-missing', - summary: 'the policy sets full_e2e and no passing full-gate record is bound to this tree', - fix: 'run the gate the policy names (gstack-ship-queue gate-ahead, then --record) or pass the record of a passing run on this head', - }, - GATE_AHEAD_ATTEMPT_INVALID: { - anchor: 'gate-ahead-attempt-invalid', - summary: 'the gate-ahead attempt is unknown, already recorded, or its worktree no longer holds the gated commit', - fix: 'list attempts with gstack-ship-queue gate-ahead --list, then record the live one, or prepare a new attempt', - }, - // Field list 2 W4 (pregate `timing`). - PREGATE_TIMING_ASSERTION: { - anchor: 'pregate-timing-assertion', - summary: 'an added or changed test line compares an elapsed wall-clock or CPU time against a bound, or sleeps and then asserts (a warning, not a block)', - fix: 'assert on the outcome, an injected clock or a forced deadline instead; when the bound is the contract, add `gstack-timing-ok: ` in a comment on the line or the line above', - }, - // Field list 2, W2 (approval classes) and W3 (state-machine round-trip matrix). - APPROVAL_CLASSES_INVALID: { - anchor: 'approval-classes-invalid', - summary: '`.gstack/approval-classes.json` is malformed, a class matches nothing, or a path escapes the repository', - fix: 'keep `classes` a non-empty list of uniquely named classes, each with `paths`, `patterns` or `migrations: true`, and every glob repo-relative (`gstack-approval-classes validate` checks the working-tree copy)', - }, - APPROVAL_CLASS_FOUND: { - anchor: 'approval-class-found', - summary: 'the branch changes something a declared approval class covers', - fix: 'get the owner\'s approval and put `Approved by via for @` in the PR body, using the APPROVAL_SCOPE token the check printed', - }, - APPROVAL_CITATION_MISSING: { - anchor: 'approval-citation-missing', - summary: 'a declared approval class has no citation that resolves and binds to its current effects, so no receipt was written', - fix: 'add an `Approved by` line whose plan (with --approval-run ) or maintainer comment names the APPROVAL_SCOPE token or the class and every effect path; for evidence gstack cannot read, attest it with `for @` on the line. Only the owner approves: never write the line without their approval', - }, - APPROVAL_SOURCE_UNAVAILABLE: { - anchor: 'approval-source-unavailable', - summary: 'origin/ is not a resolvable commit, so the committed .gstack/approval-classes.json cannot be read and nothing was checked', - fix: 'git fetch origin (classes are never read from the working tree)', - }, - STATE_MATRIX_INCOMPLETE: { - anchor: 'state-matrix-incomplete', - summary: 'the state-machines specialist output lacks a kind × owner action cell, maps a cell to a test that does not exist, or leaves an untested cell without a CRITICAL finding', - fix: 'rerun the state-machines specialist on the same diff; its review coverage stays incomplete until gstack-state-matrix check passes', - }, // #3226: gstack-error-capture (lib/dx-error-capture.ts) prints these; exit codes and recovery live there. DX_CAPTURE_USAGE: { anchor: 'dx-capture-usage', @@ -833,6 +767,7 @@ export const RESULT_CODES = { summary: 'unexpected helper failure; the line names the error class and its first stack frame', fix: 'rerun once; if it repeats, report the printed frame to the gstack maintainers', }, + ...RELEASE_RESULT_CODES, } as const satisfies Record; export type ResultCodeName = keyof typeof RESULT_CODES; diff --git a/scripts/pr-dependencies.ts b/scripts/pr-dependencies.ts index b2ddcc93d..fbf1ef43d 100644 --- a/scripts/pr-dependencies.ts +++ b/scripts/pr-dependencies.ts @@ -81,7 +81,7 @@ export const SELECTION_DATA_MODULES: readonly string[] = [ // The build entry list: every compiled binary, which skills reach through their `--outfile` path instead. 'scripts/build.sh', // The reason-code table: its `fix:` prose names the command a person reruns, not a file the module consumes. - 'lib/result-codes.ts', + 'lib/result-codes.ts', 'lib/result-codes-release.ts', ]; const DEFAULT_JUDGE_OWNER = 'test/skill-llm-eval.test.ts'; diff --git a/test/fixtures/module-size-ratchet.json b/test/fixtures/module-size-ratchet.json index 602841ba8..6a6555c98 100644 --- a/test/fixtures/module-size-ratchet.json +++ b/test/fixtures/module-size-ratchet.json @@ -65,6 +65,7 @@ { "file": "lib/gate-diff/render.ts", "movedFrom": "(new: gate-edit detector stdout contract, W1)" }, { "file": "lib/gate-diff/index.ts", "movedFrom": "(new: gate-edit detector pure core, W1)" }, { "file": "lib/result-codes.ts", "movedFrom": "(new: result codes and troubleshooting anchors for unattended runs, multi-agent wave B0)" }, + { "file": "lib/result-codes-release.ts", "movedFrom": "lib/result-codes.ts (the release-path rows: ship queue, pregate timing, approval classes, state matrix; field list 2 wave B)" }, { "file": "lib/headless-artifacts.ts", "movedFrom": "(new: the unattended artifact contract: schemas, validator, result grammar, B0)" }, { "file": "lib/gate-list.ts", "movedFrom": "(new: the final gate list renderer and reply grammar, B9)" }, { "file": "lib/autoplan-timing.ts", "movedFrom": "(new: autoplan phase timing, estimate and cycle summary, B10)" },