From 3986ac5669f7ec8dd8f92165a4682b16da21734d Mon Sep 17 00:00:00 2001 From: garrytan Date: Mon, 19 Oct 2026 07:39:14 +0000 Subject: [PATCH] v1.91.145.0 feat(ship-queue): merge trains with pattern bisect and train-record verify (GSTA-49 T1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --- CHANGELOG.md | 19 +++++++++++++++++++ VERSION | 2 +- agents-digest/gstack-AGENTS.md | 2 +- lib/ship-policy.ts | 2 +- package.json | 2 +- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 566320d96..87f632dd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## [1.91.145.0] - 2026-10-19 + +**`gstack-ship-queue` can run merge trains: several READY PRs share one full gate, merge one by one only while main's tree matches the prefix that gate tested, and a red train is bisected on its red cases alone.** The surface is off unless the base revision's `.gstack/ship-policy.json` declares a `train` block. Without one, `ready --pr ` prints exactly the block it prints today. gstack's own policy does not turn trains on yet: that waits for the workflow side (the train-nonce record, the `cases` and `prefix_shas` inputs and the dispatched screen) and one dry-run train. Walkthrough: [docs/ship-policy.md#run-a-merge-train](docs/ship-policy.md#run-a-merge-train). Plan GSTA-49, lane T1. + +### Added +- **`train build --prs @,…`** merges the pinned, unstamped heads in slot order onto main inside object storage (version files take the prefix's side, the CHANGELOG merges by section) and records every prefix tree T0..Tk. Screened PRs go first in READY order. When `max_size` or more unscreened PRs wait, they form their own train. A train below `max_size` waits up to `fill_hours` for its oldest READY, unless `--urgent`. It writes `train.json` before pushing `train/`, requires a green `free_workflow` run on that exact SHA, then dispatches one full gate through eval-bg's nonce. `--dry-run` writes, pushes and dispatches nothing. Fork heads, moved heads, PRs without a READY receipt and conflicts are refused before any spend; a conflict line names the build without that PR. +- **`train status`** never spends. It rebuilds local records from `refs/notes/gstack-trains`, where every train, attempt, READY receipt and freeze is mirrored before any remote effect. It reconciles an unconfirmed dispatch by nonce, and only a dispatch it finds absent is sent again, under the same nonce. **`train verdict`** is GREEN only for a complete census bound to the train's nonce, head and tree, with the `full_gate_check` check run published. INFRA/INCOMPLETE panels, unbound, partial or cancelled shards, slices killed before upload and missing records are never green. +- **`train bisect --spend-cap `** runs only the red cases on every prefix, after an ancestry check against `train/`. It reserves every case×prefix trial, launches what fits the cap and resumes without repeating a prefix. `ATTRIBUTED #` is reported only for a monotone pattern, and red on every prefix with T0 included is red on main. An all-green bisect earns exactly one unchanged `train rebuild`, with both runs reported. An INFRA/INCOMPLETE-only census earns the single re-dispatch `EVAL_POLICY.infraRedispatch` allows (`--infra`). A second red stays red. +- **`verify --pr --train `** prints `MERGE_CONDITION` only when main's tree equals the prefix before the PR modulo stamps and the PR is still at its pin, and confirms each merge against the prefix after it. When a train stops partway after earlier slots merged, the queue freezes. The freeze is recorded locally and on the notes ref first, then the backstop gate runs on main's SHA. One `train build --repair` PR is admitted, and verify clears the freeze when it lands. +- **`ready --screen [--broad] | --no-screen`** under a train policy. Without a choice, `ready` prints the screen selection and recommendation, then refuses. `--screen` dispatches one screen on the PR's merge SHA with `screen_pr`, `screen_merge_sha` and `screen_policy`. Dollar figures arrive with the cost replay. **`train prune`** deletes the branches of merged, superseded and dropped trains. +- **The `train` policy key** (introduced in 1.91.145.0; needs `min_gstack_version`) and 18 result codes with troubleshooting anchors: `QUEUE_TRAIN_*` and `READY_SCREEN_CHOICE_REQUIRED`. + +### Changed +- **eval-bg's nonce key** can carry a purpose (screen, train, bisect, backstop) and a screen policy, so a broad screen never adopts a narrow run and a train never adopts a bisect. Plain lane keys are unchanged. Every dispatch input name now lives in `DISPATCH_INPUTS`. +- **Gate integrity:** `test/ship-policy-compat.test.ts` now reads the newest version in `POLICY_KEY_INTRODUCED` instead of hard-coding the ship-queue keys' version, so each new key doesn't need another edit. It is exactly as strict: an unknown key is still `POLICY_INVALID`, naming the newest version this gstack reads. The rebuild-once count is defined in the train module (`REBUILD_ONCE = 1`) until `EVAL_POLICY` records it. No threshold, trial count or case kind changed. + +### If you… +- **…coordinate a queue:** add a `train` block with `min_gstack_version` on the base branch only after every lane runs this gstack. Remove it to return every lane to the per-PR queue at once. + ## [1.91.144.0] - 2026-10-18 **The paid PR gate now tests Claude Opus 5.5 instead of Fable 5.1. Its first full Opus gate went 132/132 green and recorded $32.33, against Fable's $93.16 mean over ten full gates.** Garry's direction (2026-10-18) is to test each lab's best code model. Calibration run 39157502890 passed all 108 rule cases and 24 judges on one attempt each, with no reused receipts, on the same case set every Fable gate passed. Opus 5.5 sessions cost $30.86 (Fable: $90.49), judges $1.44 and Haiku side calls $0.08; with the unrecorded PTY sessions estimated, the full-gate scale is $37.13 against $106.17. Output tokens fell 37% (thinking 69%) and session time from 11,859 s to 6,159 s. The Claude CLI runs Opus 5.5 at medium effort by default and Fable at high. diff --git a/VERSION b/VERSION index 86cb1072d..3a1f6f11b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.91.144.0 +1.91.145.0 diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md index 6456dbd20..597099b8f 100644 --- a/agents-digest/gstack-AGENTS.md +++ b/agents-digest/gstack-AGENTS.md @@ -1,4 +1,4 @@ -# gstack digest v1.91.144.0 — regenerate/re-copy after upgrading gstack +# gstack digest v1.91.145.0 — regenerate/re-copy after upgrading gstack Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed for agent hosts without a full skill install. The full skills add workflows, diff --git a/lib/ship-policy.ts b/lib/ship-policy.ts index 3a7d55b3a..432df1cdf 100644 --- a/lib/ship-policy.ts +++ b/lib/ship-policy.ts @@ -148,7 +148,7 @@ export const POLICY_EXPLANATIONS: Record = { */ export const POLICY_COMPAT_FLOOR = '1.91.98.0'; export const SHIP_QUEUE_KEYS_VERSION = '1.91.108.0'; -export const TRAIN_KEYS_VERSION = '1.91.138.0'; +export const TRAIN_KEYS_VERSION = '1.91.145.0'; export const POLICY_KEY_INTRODUCED: Record = { bump: '1.91.73.0', queue_mode: '1.91.73.0', release_tool: '1.91.73.0', release_outputs: '1.91.73.0', stamp_paths: '1.91.73.0', changelog: '1.91.73.0', mirror: '1.91.73.0', history: '1.91.73.0', preregistration_shas: '1.91.73.0', stamp_sensitive_gates: '1.91.73.0', diff --git a/package.json b/package.json index 59d46a149..002f7ece6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.91.144", + "version": "1.91.145", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module",