Skip to content

v1.91.254.0 pregate: starter policy, benign-finding allowlist, environment vs diff failures, per-run scratch - #3480

Merged
capy-ai[bot] merged 8 commits into
mainfrom
gsta-112/pregate-ergonomics
Oct 26, 2026
Merged

capy-ai[bot] merged 8 commits into
mainfrom
gsta-112/pregate-ergonomics

Conversation

@garrytan

@garrytan garrytan commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner
{
  "schema_version": 1,
  "pr": 3480,
  "head": "c3c96b3ad0af6a486958872020ace795e83a8f2d",
  "version": "1.91.248.0",
  "base": "main",
  "gate": {
    "pregate.json/remote_gate": {
      "pass": 21503,
      "fail": 0,
      "skip": 0
    },
    "local-pregate-suite": {
      "pass": 324,
      "fail": 0,
      "skip": 0
    }
  },
  "spend_usd": 0.12,
  "session_kind": "unattended",
  "pregate": "requires-remote cleared @a5e9fd18dd36 (1 checks, current for c3c96b3ad0af)",
  "requires_remote": [
    "free-tests.yml/cso-macos-launcher: https://github.com/garrytan/gstack/actions/runs/40356546176",
    "free-tests.yml/macos-named-regressions: https://github.com/garrytan/gstack/actions/runs/40356546176",
    "windows-free-tests.yml/windows-free-shard: https://github.com/garrytan/gstack/actions/runs/40356546444",
    "pregate.json/remote_gate: remote-gate tree=a5e9fd18dd36 tests=21503"
  ],
  "issues": {
    "fixes": [],
    "refs": [],
    "flakes": []
  }
}

What changed

A touched file with no test lane in a repository that has no .gstack/pregate.json: before, a hard PREGATE_NO_LANE fail (exit 1) with no way forward; after, a warn under PREGATE_NO_POLICY with a starter policy printed, the selected tests still run, and the lane log lives under the state root's per-run scratch instead of /tmp.

A touched file with no test lane in a repository that has no .gstack/pregate.json: before, a hard PREGATE_NO_LANE fail (exit 1) with no way forward; after, a warn under PREGATE_NO_POLICY with a starter policy printed, the selected tests still run, and the lane log lives under the state root's per-run scratch instead of /tmp.

Before/after as text: A touched file with no test lane in a repository that has no .gstack/pregate.json: before, a hard PREGATE_NO_LANE fail (exit 1) with no way forward; after, a warn under PREGATE_NO_POLICY with a starter policy printed, the selected tests still run, and the lane log lives under the state root's per-run scratch instead of /tmp.
--- Before · before.txt · captured output
+++ After · after.txt · captured output
+PREGATE: tests requires-remote (1 uncleared) in 0.4s — lanes: 1 tests ran in 1 file(s), exit 0; 1 requires-remote obligation(s); 1 touched file(s) with no test lane under no policy (starter printed)
-PREGATE: tests fail in 0.2s — lanes: 1 touched file(s) with no test lane: lib/orphan-widget.js
 pregate: policy origin/main@0a5411755ab6 (no .gstack/pregate.json); registry origin/main@0a5411755ab6:.gstack/generated.json; base origin/main@0a5411755ab6; 2 touched file(s); platform linux
 stage      check     status            time  detail
+preflight  regen     pass                121 ms  no registered input or output touched (2 entries)
+preflight  secrets   pass                218 ms  2 added lines clean
+preflight  strays    pass                142 ms  1 added file(s), none stray
+preflight  literals  pass                150 ms  no exported constant or named timeout literal changed in 1 modified source file(s)
+preflight  timing    pass                132 ms  no timing assertion in the added lines of 0 test file(s)
+preflight  guards    pass                129 ms  no guards declared (origin/main@0a5411755ab6 (no .gstack/pregate.json))
+tests      lanes     requires-remote     410 ms  1 tests ran in 1 file(s), exit 0; 1 requires-remote obligation(s); 1 touched file(s) with no test lane under no policy (starter printed) (PREGATE_NO_POLICY)
+    lanes: no policy: lib/orphan-widget.js have no test lane (a warning under no policy; the starter below maps them)
-preflight  regen     pass                119 ms  no registered input or output touched (2 entries)
-preflight  secrets   pass                199 ms  2 added lines clean
-preflight  strays    pass                148 ms  1 added file(s), none stray
-preflight  literals  pass                143 ms  no exported constant or named timeout literal changed in 1 modified source file(s)
-preflight  timing    pass                120 ms  no timing assertion in the added lines of 0 test file(s)
-preflight  guards    pass                111 ms  no guards declared (origin/main@0a5411755ab6 (no .gstack/pregate.json))
-tests      lanes     fail                153 ms  1 touched file(s) with no test lane: lib/orphan-widget.js (PREGATE_NO_LANE)
-    lanes: FAIL lanes — lib/orphan-widget.js has no test lane
     lanes: requires-remote windows.yml/windows-shard (windows): 1 test(s) — test/util.test.js
     lanes: Tiers ran: unit; requires-remote: windows
+    lanes: runtime: PATH (no eligible Bun in the runtime store, $BUN_INSTALL/bin, ~/.bun/bin or PATH); install verdict: not checked (no GSTACK_CAPY=1 and no verdict for this checkout and project)
+    lanes: progress: none (no progress adapter for this runner; serial files and heartbeats only)
+    lanes: ran: node --test 'test/util.test.js'
+    lanes: log: <state root>/projects/gstack-pregate-fx-BbLYQb-origin/pregate/runs/20261026T162856Z-1414517-b31a/lanes/lanes.log
+    lanes: PREGATE_STARTER: no .gstack/pregate.json on origin/main and no user-owned policy at <state root>/projects/gstack-pregate-fx-BbLYQb-origin/pregate.json; a starter drafted from this repository follows. Review it, write it with gstack-pregate init, edit each TODO, then commit it on the base branch (from then on an unmapped file is PREGATE_NO_LANE)
+    lanes: PREGATE_STARTER: runner node --test {files}
+    lanes: PREGATE_STARTER: test directories: test, test/nightly
+    lanes: PREGATE_STARTER: CI lanes: free-tests.yml/unit (linux), windows.yml/windows-shard (windows, matrix computed; declare selection)
+    lanes: PREGATE_STARTER: begin .gstack/pregate.json
+    lanes: {
+    lanes:   "$schema": "https://github.com/garrytan/gstack/docs/pregate.md#pregate-v1",
+    lanes:   "runner": "node --test {files}",
+    lanes:   "dependencies": {}
+    lanes: }
+    lanes: PREGATE_STARTER: end
+    lanes: TODO lib/orphan-widget.js: no test lane and no nearby test; add a test, map it under dependencies, or declare [] if no test can cover it
+stage 1 (mechanical preflight): 893 ms
+stage 2 (test execution): 410 ms
+scratch: <state root>/projects/gstack-pregate-fx-BbLYQb-origin/pregate/runs/20261026T162856Z-1414517-b31a
-    lanes: fix: add a test that names the file, or declare its lane (or []) under dependencies — or empty_lanes for other documentation — in .gstack/pregate.json
-stage 1 (mechanical preflight): 841 ms
-stage 2 (test execution): 153 ms
 requires-remote: windows.yml/windows-shard (windows) 1 test(s) — uncleared; clear with gstack-pregate clear --remote windows.yml/windows-shard --run-url <url>
+PREGATE: requires-remote (1 uncleared) tree=d02c5e316094 head=7bffb7e35d75 checks=7
-PREGATE: fail tree=d02c5e316094 head=7bffb7e35d75 checks=7
-gstack-pregate: lanes: 1 touched file(s) with no test lane: lib/orphan-widget.js; fix: add a test that names the file, or declare its lane (or []) under dependencies — or empty_lanes for other documentation — in .gstack/pregate.json (PREGATE_NO_LANE)
 pregate.json: <repo>/.gstack/tmp/pregate.json
 GSTACK_RESULT: skill=pregate status=complete run=<repo>/.gstack/tmp/pregate.json
 

Why

Three Captains lost their first /ship pass to PREGATE_NO_LANE in a repository with no .gstack/pregate.json yet, the non-downgradable secrets check refused 1,800 dummy per-trial tokens and run ids read as phone numbers, a lane whose runner could not start read as the diff's failure, and pregate's /tmp logs were shared between parallel runs and wiped between Capy wakes (harness-codify Lane D; Garry, 2026-10-26: "Do it and also improve it: fix the issues all the captains have seen in this Capy project"). GSTA-114's GSTACK_CAPY_WRAPPER=2 → 3 edit then flagged 575 test files under PREGATE_LITERALS, so the consumersOf fix rides here. A user now gets a warn with a starter instead of a dead end, can name a benign finding with a scoped, reasoned allowlist entry (never a real credential value), sees whether a failure was the machine's or the diff's and how certain that is, and finds the lane log where the fix: line says.

Approvals

Date Asked Exact words Outcome Covers Still pending
2026-10-26 Approve the harness-codify plan (Lane D: pregate ergonomics for a repository that is not gstack) “Do it and also improve it: fix the issues all the captains have seen in this Capy project” (Garry (via GStack Minder)) approved the harness-codify plan at full scope, every recommendation; Lane D = starter policy instead of PREGATE_NO_LANE, allowlists for benign secrets/pii findings, environment vs diff failures, per-run scratch none
2026-10-26 Take the literals consumersOf false-positive fix (GSTA-114 flood) into #3480 ahead of other items “now, ahead of your other items” (GStack Minder) approved lib/pregate/checks/literals.ts consumersOf: stem as a path fragment, constant name required for a one-character value, regression case none

Source: gstack-approvals record for gsta-112/pregate-ergonomics (display only; not an approval citation).

Summary

Pregate ergonomics for a repository that is not gstack (harness-codify Lane D; plan rows E4–E6). Three Captains lost their first /ship pass to PREGATE_NO_LANE in a repo with no .gstack/pregate.json yet; the non-downgradable secrets check refused 1,800 dummy per-trial tokens, 11-digit Actions run ids and a vendor's public web key; a lane whose runner could not start read as the diff's failure and got waived by test name; and pregate's logs under os.tmpdir() were shared between parallel runs and wiped by a Capy wake.

No policy → warn plus a printed starter, never a hard PREGATE_NO_LANE

When the base branch carries no .gstack/pregate.json and no user-owned policy exists, a touched file with no lane is a warn row under the new code PREGATE_NO_POLICY. The selected tests still run (a red lane is still fail; an unknown platform matrix is still a requires-remote obligation) and the table prints a starter drafted from the repository between PREGATE_STARTER: begin and end: detected runner, test directories, CI lanes, a dependencies entry per unmapped touched file (nearest tests or same stem, never []), and a TODO line per file nothing covers. run writes nothing; gstack-pregate init is the explicit write. Once any policy exists, an unmapped file is PREGATE_NO_LANE as before.

allowlist in the policy, with env.value and the secret category un-allowlistable

allowlist: [{ finding, paths?, pattern?, reason }] (lib/pregate/allowlist.ts). finding is a gstack-redact id or one of the categories pii, internal, hygiene, legal; one scope (paths or pattern) and a reason are required; pattern is matched at the finding's column and must end at a token boundary. The secrets row says N allowlisted (<ids>), names each allowlisted finding with its entry and reason, and records the entries' digest as inputs.allowlist. Naming env.value, secret or an engine.* scanner refusal is a PREGATE_CONFIG_INVALID at allowlist[i].finding, and the matcher never consults the list for env.value, so a hand-edited policy cannot silence a real credential value either (test: a pattern: ".*" entry injected past validation still fails). A pattern entry that named a finding the scanner gave no position for is reported as not tested instead of silently inert.

Environment failures apart from diff failures

lib/pregate/environment.ts classifies a check that could not run because of the machine (missing binary / exit 127 / ENOENT, network, quota, disk, runtime, gstack's own scanner not finishing) as incomplete with the new code PREGATE_ENVIRONMENT, cause: "environment" and environment: { kind, evidence, proof } in pregate.json, and an environment: table line. proof is launch (the command could not start, its own binary is off PATH, the runtime or a gstack tool refused: "the diff is not at fault") or output (a rule matched the command's text before any test was counted, which the diff's own output could have written: the line says (inferred from output) and the fix asks for confirmation on another machine or with --remote). PREGATE_LANE_FAILED, PREGATE_GUARD_FAILED and PREGATE_SECRETS carry cause: "diff". The classifier is conservative: a counted test failure is the diff's whatever its log says; a local lane with no summary is read from its output only when the runner was not seen starting a test file; exit 127 and command not found are missing-binary only when the command's own binary is off PATH, so a runner, guard or gate script the diff controls that exits 127 is the diff's; a remote gate is environment only when it printed no PREGATE_REMOTE: line and the cause is in its first 40 lines, before any test output could stream; a runner killed by a signal, stalls and timeouts keep PREGATE_INCOMPLETE / PREGATE_STALLED. verify prints PREGATE_ENVIRONMENT: <n> check(s) blocked by the environment (<kinds>), not by the diff when every incomplete check is environment-caused, naming any check inferred from output alone.

One scratch directory per run under the state root

<state root>/projects/<slug>/pregate/runs/<run id>/ (0700; --run <id> names it) holds the secrets scan's added-line copies (deleted after the scan), lanes/lanes.log, guards/<id>.log and the remote gate's files. pregate.json records it as scratch, the table prints scratch: <dir>; a --run <id> whose directory already exists takes <id>-2 … -9 instead of sharing (and truncating) a live run's logs; runs older than 7 days are pruned; an unwritable state root falls back to a private per-run directory under os.tmpdir() and says so.

Outside lib/pregate/**, additive

  • lib/result-codes-release.ts: the two new rows (lib/result-codes.ts sits at the 800-line ratchet, and the doctor/cathedral/stop-hook tests copy a fixed list of lib files, so a new module there broke them).
  • lib/headless-artifacts.ts: the pregate schema accepts cause, environment, scratch.
  • scripts/lib/windows-curation.ts: the four new tests excluded on Windows (POSIX binaries and modes).
  • bin/gstack-doctor-components.sh: regenerated (gen:skill-docs) for the two anchors.
  • test/pregate-invalidation.test.ts: 30 s per-test timeouts; it ran 4.2 s on main alone and timed out at Bun's 5 s default under a loaded 28-file run.

literals no longer floods on a common module stem (GSTA-114)

consumersOf counted a test as a consumer of a changed constant when it merely contained the source file's stem as a bare word (install, retry), so GSTACK_CAPY_WRAPPER=2 → 3 in capy/skill/gstack/scripts/install.sh flagged 575 test files. The module now counts as its full file name (install.sh) or as a path fragment (/retry.js), and a one-character old value needs the constant's name on the line. Probe on the real tree: 575 → 5 consumers, all naming GSTACK_CAPY_WRAPPER.

Tests (red before, green after)

test/pregate-starter.test.ts (4), test/pregate-allowlist.test.ts (6), test/pregate-environment.test.ts (9, incl. the spoof: a bun test that prints fetch failed and exits before the summary is at most an output-inferred cause whose fix never clears the diff), test/pregate-scratch.test.ts (3), the consumersOf regression in test/pregate-selection.test.ts. Red outputs before the change: exit 1 (PREGATE_NO_LANE) on a no-policy fixture; exit 1 (PREGATE_SECRETS) | 1 credential finding(s) in added lines (env.kv) on a dummy sk-trial-… token; PREGATE_LANE_FAILED cause= undefined | local lane exited 127 on a missing runner; log: /tmp/gstack-pregate-lanes-*/lanes.log, no scratch field. Existing no-policy fixtures in pregate-selection, pregate-docs-lane-review, pregate-non-js, pregate-rust, pregate-dart now assert the warn contract / PREGATE_ENVIRONMENT.

Checks run: bun run typecheck; every test/pregate-*.test.ts except the pre-existing pregate-regate red (identical on origin/main); gstack-doctor, module-size ratchet, troubleshooting anchors, changelog, headless-artifacts schema, parity suite, bun-entry isolation. Pregate stage 1 clean on the final tree; remote free tier on a standard-4 VM: 21503 tests, 0 failed on tree a5e9fd18dd36 ($0.04); CI green at c3c96b3.

Test Coverage

All new code paths have test coverage (Step 7 coverage audit at 213ffe9; no weak gaps named). Tests ran: pregate.json/remote_gate 21503 (0 failed); local pregate/doctor/ratchet/parity suite 324 (0 failed).

Pre-Landing Review

Pass 1 (whole diff, 6 specialists): 27 INFORMATIONAL, 0 CRITICAL; 21 auto-fixed in 213ffe9, 6 advisory skipped (performance notes in starter.ts/allowlist.ts/secrets.ts/run-scratch.ts, two test-shape notes). Pass 2 (range e9f9c21..213ffe9): 1 INFORMATIONAL, fixed in e890d0d (consumersOf also demanded a separator before the full file name). Pass 3 (range 213ffe9..f2a3246, the cap): 5 INFORMATIONAL, none at the blocking floor, deferred and named here:

  • lib/pregate/environment.ts classifyCommandEnvironment: a relative-path command (./scripts/gate.sh) is resolved against the process cwd, not the command's cwd; a diff that deletes a base-policy script reads as missing-binary/launch. Incomplete never passes; follow-up: resolve against the command's cwd and treat a slash-bearing path as the diff's.
  • lib/pregate/checks/lanes.ts local-lane comment overstates observedStart (set only when a progress adapter is active; single-file and serial runs never set it, so a single-file spoof is still an output-inferred cause with its caveat). Follow-up: detect headers for single-file runs too.
  • lib/headless-artifacts.ts pregate schema does not declare environment.proof (permissive; validates).
  • No test for the signal-death branch (PREGATE_INCOMPLETE "ended without an exit code").
  • MAX_RUN_ID_SIBLINGS counts directories tried, not siblings (naming).
    Gate edits: none detected (no gate finding in any pass; nothing kept, restored or open).
    Outside review: Codex unavailable on this machine (not installed); native Claude adversarial passes only.

Adversarial Review

Pass 1 at 213ffe9: 9 findings. Fixed in f2a3246: a test in the diff could relabel its failure as environment by printing a network line and exiting before the summary (now vetoed when the runner was seen starting a file, and every output-inferred cause carries proof: output with a fix that never clears the diff); the remote gate was classified from its whole output (now its first 40 lines); guard exit 127 was unconditionally environment (now only when the guard's own binary is off PATH); signal death read as missing-binary (now PREGATE_INCOMPLETE); a reused --run <id> shared a scratch directory between concurrent runs (now a numbered sibling); engine.* was allowlistable; pattern entries were silently inert without a column. Accepted as-is: secret-category ids allowlistable by path scope alone (the policy is base-branch or user-owned, which a PR author cannot write), a cosmetic label, the absolute scratch path in pregate.json. Pass 2 at f2a3246 verified each fix; residuals, all advisory: a single-file or serial lane can still label itself PREGATE_ENVIRONMENT with proof: output (verify stays not-ok and the caveat prints); the relative-path veto edge above; the remote preamble is read from the last 4 MiB of a very large log; the tenth duplicate --run id falls back to a tmpdir under a "state root not writable" explain line; a guard killed by a signal reads as the diff's (pre-existing, safe direction). Recommendation: ship.

Exploratory QA

Not run (CLI library change; the pregate fixture suites and the remote free tier are the behavioural evidence).

Design Review

No frontend files changed — design review skipped.

Eval Results

No prompt-related files changed — evals skipped.

Scope Drift

Scope Check: CLEAN against the Lane D spec; one addition requested by GStack Minder (the literals consumersOf fix for GSTA-114).

Plan Completion

Lane D spec: 21 items done, 3 changed (the starter is written by the existing gstack-pregate init verb rather than a new --write flag; the two new result-code rows live in lib/result-codes-release.ts because lib/result-codes.ts sits at the 800-line ratchet; the scratch module is run-scratch.ts because the strays rule rejects scratch* basenames), 1 unverifiable (GBrain practice 10, below).

Deferred (not in this diff)

GBrain practice 10 (a known-infra-flakes entry granting one named infra rerun) is a /ship + ready-validator concern, not a pregate.json one; noted for the ship lane. docs/state-root.md's project-bucket inventory should mention pregate/runs/<run id>/ (outside this lane; routed to GStack Minder).

Verification Results

Pregate verify: ok, requires-remote cleared, current for tree a5e9fd18dd36 (remote gate 21503/0 at $0.04; the three CI lanes cleared with run 40356546176 (Free Tests) and 40356546444 (Windows Free Tests)). CI at f2a3246 saw one flaky red (browse/test/terminal-agent-lifecycle.test.ts 5 s timeout on the macOS runner, a file this branch does not touch; green on gh run rerun --failed, logged in the crew flaky ledger); CI at c3c96b3 green first time.

TODOS

No TODO items completed in this PR.

Documentation

Status: current for c3c96b3 after two read-only audits (gsta112-docs-1 at 213ffe9, gsta112-docs-2 at f2a3246); every correction they named inside this lane is applied, the last one (the PREGATE_INCOMPLETE anchor naming a signal-killed runner) in c3c96b3, a docs-only commit after audit 2, read back against lib/pregate/checks/lanes.ts.

Scope. 33 committed files against main@5755601dac5d. Docs in the diff: docs/pregate.md (synopsis, stage-1 guards and stage-2 lanes bullets, Publication list, #no-policy, #allowlist, #environment, #scratch), docs/troubleshooting.md (PREGATE_NO_POLICY, PREGATE_ENVIRONMENT, PREGATE_GUARD_FAILED, PREGATE_SECRETS, PREGATE_INCOMPLETE, PREGATE_NO_LANE), CHANGELOG.md [Unreleased], gstack-pregate --help. Verified against lib/pregate/**: 64-entry allowlist cap; env.value, secret and engine.* refused at validation and kept by the matcher; anchored pattern with token boundary; inputs.allowlist digest; environment.proof launch|output with its two fix tails and the (inferred from output) suffix; the binary-on-PATH veto; the remote gate's first-40-lines rule; signal death as PREGATE_INCOMPLETE; 0700 per-run scratch, 7-day prune, tmpdir fallback, numbered sibling for a taken --run id; init refusing without --force; anchors registered in the result-code table and the doctor's map.

Debt. docs/state-root.md project-bucket inventory omits pregate/runs/<run id>/ (outside this lane; routed to GStack Minder). docs/pregate.md stage-1 secrets bullet could cross-reference #allowlist; PREGATE_CONFIG_INVALID does not list the new allowlist refusals (its messages are self-describing). No tutorial for the new surfaces, consistent with the rest of the pregate docs. No ARCHITECTURE diagram names pregate: no diagram drift.

…es, per-run scratch

A repository with no .gstack/pregate.json now gets a warn (PREGATE_NO_POLICY)
with a starter policy printed, instead of PREGATE_NO_LANE on every touched
file; gstack-pregate init remains the explicit write. The policy gains an
allowlist for benign secrets/pii findings (env.value and secret never
allowlistable). Checks that cannot run because of the machine report
PREGATE_ENVIRONMENT (incomplete, with kind and evidence) apart from diff
failures. Every run writes its scratch under the state root, per run id.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

garrytan and others added 6 commits October 26, 2026 15:07
…o its test

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…tant name for a one-character value

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
guards: an exited guard is the machine's only on exit 127, never from its output;
secrets: clear an interrupted run's added-line copies before scanning;
environment: one fix table per kind, one ANSI strip, hoisted not-found vocabulary;
starter returns its lines; allowlistDigest reuses sha256; stale headers and the
PREGATE_INCOMPLETE fix clause updated; tests for the mixed verify branch, disk
precedence, allowlist boundaries, a positionless finding, head-policy strictness,
run-id edges and the unwritable state root.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…sumer

consumersOf anchored both the stem and the full basename on a path
separator, so run('install.sh') or bash install.sh without a directory
stopped counting for a multi-character old value. Only the bare stem
needs the separator; the full file name is specific on its own.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…n --run id gets its own directory

Adversarial review of the environment classifier and the scratch layout:

- exit 127 and 'command not found' are missing-binary only when the
  command's own binary is off PATH (runner, guard and remote gate alike);
  a script the diff controls that exits 127 is the diff's failure
- a local lane with no test summary is classified from its output only
  when the runner was not seen starting a test file; a remote gate only
  from its first 40 lines, before any test output could stream
- environment.proof records launch (certain) or output (inferred); an
  output-inferred cause never says 'the diff is not at fault', its line
  says '(inferred from output)', and verify names such checks
- a runner killed by a signal is PREGATE_INCOMPLETE, not missing-binary
- a --run id whose directory exists takes <id>-2 .. -9 instead of
  sharing (and truncating) a live run's logs
- engine.* findings are never allowlistable; a pattern entry the scanner
  gave no position for is reported as not tested instead of silently inert
- docs: synopsis --run, no-policy lanes wording, verify's code list,
  guard exit 127 carve-out, PREGATE_SECRETS allowlist pointer, scratch

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…ELOG lists every doc edit

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…nment vs diff failures, per-run scratch

Merge origin/main (4d48d39, v1.91.253.0) and restamp at slot 1.

FILES: CHANGELOG.md VERSION agents-digest/gstack-AGENTS.md package.json
MERGE_CONDITION: sha=c3c96b3ad0af6a486958872020ace795e83a8f2d
NEW_VERSION=1.91.254.0

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@github-actions github-actions Bot changed the title pregate: starter policy, benign-finding allowlist, environment vs diff failures, per-run scratch v1.91.254.0 pregate: starter policy, benign-finding allowlist, environment vs diff failures, per-run scratch Oct 26, 2026
@capy-ai
capy-ai Bot merged commit 568cd5a into main Oct 26, 2026
63 checks passed
garrytan added a commit that referenced this pull request Oct 26, 2026
…tamp-only

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
garrytan added a commit that referenced this pull request Oct 26, 2026
Rule 19 grant (train 15 QUEUE_TRAIN_CONFLICT). CHANGELOG additive. test/fixtures/context-budget.json by hand: canary keeps the hoisted ceiling (main did not change it; the conflict was main's adjacent new captain row); captain (new on main, now hoisted) and five loaded-skill ceilings lowered to a fresh capture (captain 12011 -> 6551, autoplan, office-hours, plan-ceo-review, plan-devex-review, plan-eng-review by 2-22). No ceiling raised. Generated files and ship goldens regenerated.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
garrytan added a commit that referenced this pull request Oct 26, 2026
…or stands in for it

Merging origin/main b004c06 (#3480) into this branch created a semantic
conflict between two individually correct parents: #3480 made
verifyPregate return PREGATE_ENVIRONMENT (instead of PREGATE_INCOMPLETE)
when every incomplete check was caused by the environment, and this
branch's by-tree mirror reader in ready() treated only PREGATE_LANE_FAILED
and PREGATE_INCOMPLETE as final. Merged, a local record whose secrets scan
never finished fell through to a same-tree tests-only mirror and ready
passed without a secrets scan, against the rule this branch documents
("a record whose own checks failed or stayed incomplete is never
overridden").

ready() now keeps a PREGATE_ENVIRONMENT record final as well.

Regression in test/gstack-ship-queue.test.ts ("one READY block ..."): an
environment-incomplete secrets record beside a passing same-tree mirror
is refused with (PREGATE_ENVIRONMENT) and no "from the state root"
suffix. Red on the bare merge 28b64d7 (expected exit 3, received 0),
green with this fix.

Found by the pass-4 delta review of the merge.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
capy-ai Bot added a commit that referenced this pull request Oct 27, 2026
… train-gated commit; cross-repo refs, run ids, pr-body section merge, pregate by tree (#3483)

* fix(release-cut,ship-queue): the weekly release accepts a train-gated commit, and five lane frictions seen in operation

scripts/release-cut.ts gates a main commit either by a successful backstop check
run or by a green/merging/merged train record in refs/notes/gstack-trains whose
merged[] names its sha or tree (CANDIDATE: ... gated by train <nonce>); a red
check, a running run, the required check and the freeze are judged as before.
--required-check, --backstop-check and --notes-ref make the names configurable.
lib/issue-links.ts reads (name #N[, #M]), (name PR #N) and (name issue #N) as
cross-repo references. lib/gstack-post.ts allowlists an 11-digit run id after a
run word or chained after one, and pr-body merges by ## section into the PR's
current body (--replace overwrites). gstack-pregate mirrors each record under
<state root>/pregate/by-tree/<tree>.json and ready reads the mirror for its tree
when the checkout's record is missing or for another tree. docs/troubleshooting.md
gains #redact-run-id-as-phone, #gate-error-no-base and #gstack-post-pr-body-merge.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (pass 1)

Fence-length-aware section splitting in gstack-post pr-body (an unclosed
receipt fence or a four-backtick block no longer exposes a heading to the
merge), the run-id allowlist drops generic words (id, job, attempt,
workflow), ready accepts a by-tree pregate mirror only from a complete run
against origin/<base> under a reviewed policy and prints no home path,
release-cut skips non-object notes and never substitutes train evidence
for the required check when both names are equal, issue-links treats
closing/cf./e.g./v1.2 as words rather than repositories.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (pass 2)

An unclosed receipt fence makes the body from that line on one section
the merge never matches, so posted leading prose cannot replace it and a
closed receipt before it stays a receipt; the by-tree pregate mirror must
hold the tests stage (what --stage tests --remote writes) rather than
every check; empty sha/tree strings in a train note are not evidence;
(v1.2.3-rc1 #301) is a version word, not a repository.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CANDIDATE line names its gate; issue-links reference documents the (name #N) form

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship-queue): a PREGATE_ENVIRONMENT local record is final; no mirror stands in for it

Merging origin/main b004c06 (#3480) into this branch created a semantic
conflict between two individually correct parents: #3480 made
verifyPregate return PREGATE_ENVIRONMENT (instead of PREGATE_INCOMPLETE)
when every incomplete check was caused by the environment, and this
branch's by-tree mirror reader in ready() treated only PREGATE_LANE_FAILED
and PREGATE_INCOMPLETE as final. Merged, a local record whose secrets scan
never finished fell through to a same-tree tests-only mirror and ready
passed without a secrets scan, against the rule this branch documents
("a record whose own checks failed or stayed incomplete is never
overridden").

ready() now keeps a PREGATE_ENVIRONMENT record final as well.

Regression in test/gstack-ship-queue.test.ts ("one READY block ..."): an
environment-incomplete secrets record beside a passing same-tree mirror
is refused with (PREGATE_ENVIRONMENT) and no "from the state root"
suffix. Red on the bare merge 28b64d7 (expected exit 3, received 0),
green with this fix.

Found by the pass-4 delta review of the merge.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* v1.91.262.0 stamp

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant