From a07460adc0bf4e0c91b96d593a7e6429c39b89f5 Mon Sep 17 00:00:00 2001 From: garrytan Date: Sat, 31 Oct 2026 09:36:00 +0000 Subject: [PATCH] docs: pregate timeout order, PREGATE_TIMEOUT_S, head-policy follow-ups in TODOS Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- TODOS.md | 5 +++++ changelog.d/gsta195-pregate-head-timeout.md | 2 +- docs/pregate.md | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/TODOS.md b/TODOS.md index a5246b162..be61d763d 100644 --- a/TODOS.md +++ b/TODOS.md @@ -7,6 +7,11 @@ - **Derive `carry.covers` from depth.** A carried receipt's `covers` is the fixed `CARRY_COVERS` list (lib/ship-receipt.ts); derive it from the recorded `review_depth` so a light review's carry does not claim the checks a full review ran (plan item 5, deferred at /ship). **Effort:** S. **Priority:** P1. - **Bound the queue's recompute time.** `gstack-ship-queue` recomputes each receipt's needed depth at READY and at train build; add a test that a five-PR train recomputes within a fixed budget, so a large diff cannot stall the train. **Effort:** S. **Priority:** P1. +### P2/P3: pregate head-policy follow-ups (filed 2026-10-31, from the GST-419/GST-420 /ship review) +- **`finish` fallback drops head-policy lanes (P2)** — `lib/ship-release.ts` reruns pregate on the stamped tree under the base policy, so after a version bump a lane the branch added under `--policy-from head` is gone and `finish` reports `PREGATE: fail (rerun on the stamped tree)`. GSTA-194 owns that file and has the note. **Effort:** S. **Priority:** P2. +- **The 3600 s preflight and `finish` wrapper deadline (P3)** — it caps the whole pregate run, so several runners that each fit `timeout_s` can still be cut off together. Derive the wrapper deadline from `timeout_s` and the lane count, or document the cap. **Effort:** S. **Priority:** P3. +- **A bootstrap head policy can still certify itself without `--remote` (P3)** — with no trusted policy, the head file may set `remote_gate: null`, or produce an obligation that `gstack-pregate clear --receipt` accepts from the branch's own gate. Decide what a bootstrap `pregate.json` may certify, then enforce it in `verify` from the recorded policy label instead of per entry point. The `--remote` refusal also prints the generic `PREGATE_HEAD_POLICY_LOOSENS` fix line, which does not apply when there is no trusted policy. **Effort:** S. **Priority:** P3. + ### P3: `/codex --effort` follow-ups (filed 2026-10-11, from the #3146 autoplan review) - **Show the effort that ran.** Step 0.5 prints `CODEX_EFFORT: (source: /codex --effort)` once, but the result footers do not repeat the effort, so it scrolls away. Add an `Effort:` line to the review, challenge and consult result footers. Blocked on skeleton bytes in `codex/SKILL.md` (cap 60,200). **Effort:** S. **Priority:** P3. diff --git a/changelog.d/gsta195-pregate-head-timeout.md b/changelog.d/gsta195-pregate-head-timeout.md index 814504c6c..f98d6c535 100644 --- a/changelog.d/gsta195-pregate-head-timeout.md +++ b/changelog.d/gsta195-pregate-head-timeout.md @@ -6,7 +6,7 @@ ### Changed - **A head policy may only add test lanes** (`PREGATE_HEAD_POLICY_LOOSENS`). It may add a `dependencies` glob with at least one test, or add tests to a glob the trusted policy already maps. Anything else that differs from the trusted policy refuses the run and names each difference. The trusted policy is the base copy, or the user-owned file when the base has none. A branch behind its base is measured from the copy at its merge base and runs the base tip's policy plus its additions. A head file with no trusted policy anywhere is still a bootstrap. -- **`--remote` works with `--policy-from head`** once that check passes, so a lane on a machine with under 8 cores can clear its obligation. It still runs the trusted copy's `remote_gate`. +- **`--remote` works with `--policy-from head`** once that check passes, so a lane on a machine with under 8 cores can clear its obligation. It still runs the trusted copy's `remote_gate`. With no trusted policy at all, `--remote` under head is refused, because a bootstrap head file's own `remote_gate` would be clearing its own obligation. - **Under `--policy-from head`, an invalid user-owned policy now refuses** (`PREGATE_CONFIG_INVALID`) instead of being ignored, because it is the policy the head file is compared with. - **A `[]` declaration added only on the branch is refused under `--policy-from head`**, the Dart device-test workaround included: declare `"**/integration_test/**": []` on the base branch first. The `PREGATE_NO_LANE` fix line and docs say so. diff --git a/docs/pregate.md b/docs/pregate.md index b0a379dab..b3b5ef4ed 100644 --- a/docs/pregate.md +++ b/docs/pregate.md @@ -334,9 +334,9 @@ Two stages with separate clocks, both printed: the project's `engines.bun` (the row prints `runtime: bun from `), so a Capy host's older image Bun cannot flip the verdict. - Every test-tier command (the lanes runner, each guard, the `--remote` gate) - runs supervised: see [supervision](#supervision). `--timeout` bounds each - runner process (the unit-file group, each serial file, each guard without - its own `timeout_s`), not their total; the stall timeout catches a hung or + runs supervised: see [supervision](#supervision). `--timeout` (else the + policy's `timeout_s`, else 600 s) bounds each runner process (the unit-file + group, each serial file, each guard without its own `timeout_s`), not their total; the stall timeout catches a hung or silent one sooner. - Under 8 cores, a `remote_gate` in the active policy or a remote `test_backend` (`gstack-config set test_backend ubicloud`) records the local test tier as a @@ -412,9 +412,10 @@ test-tier command: (`--stall-timeout `, else `stall_timeout_s`, else 300; `0` disables): the check is `incomplete` with `PREGATE_STALLED` and names the last file started; the next serial file still runs; -- is killed as **timed out** when that runner process reaches `--timeout` - (per runner process, so many serial files that each fit still pass); the - check is `incomplete` and the next serial file still runs. +- is killed as **timed out** when that runner process reaches its timeout + (`--timeout `, else `timeout_s`, else 600; per runner process, so many + serial files that each fit still pass): the check is `incomplete`, its detail + names which of the three set the timeout, and the next serial file still runs. A kill is SIGTERM to the group, then SIGKILL after 5 s (a group that ignores SIGTERM still dies). SIGINT or SIGTERM to `gstack-pregate` itself SIGKILLs every @@ -445,8 +446,9 @@ the supervision above. Close the obligation one of two ways: which runs the declared `remote_gate` now (under `--policy-from head`, still the trusted copy's gate; a `test_backend` without `remote_gate` cannot be run this way). The gate runs in the repository root with `PREGATE_TREE` (the working-tree fingerprint - being tested), `PREGATE_FILES_FILE` (the selected files, one per line) and - `PREGATE_SPEND_CAP_USD`, and must print + being tested), `PREGATE_FILES_FILE` (the selected files, one per line), + `PREGATE_SPEND_CAP_USD` and `PREGATE_TIMEOUT_S` (this run's per-process + timeout in whole seconds), and must print `PREGATE_REMOTE: tree= tests= failed= [spent=]`, reporting the tree it actually tested. The obligation clears only when that tree is `PREGATE_TREE`, `tests` > 0, `failed` = 0 and the gate exits 0; anything else