fix(gstack-gate): --help and GATE_REPLY_UNPARSED show the current rec / as-is grammar (#3282) by szsunyuan · Pull Request #3310 · garrytan/gstack · GitHub
Skip to content

fix(gstack-gate): --help and GATE_REPLY_UNPARSED show the current rec / as-is grammar (#3282) - #3310

Open
szsunyuan wants to merge 1 commit into
garrytan:mainfrom
szsunyuan:docs/gstack-gate-help-grammar
Open

szsunyuan wants to merge 1 commit into
garrytan:mainfrom
szsunyuan:docs/gstack-gate-help-grammar

Conversation

@szsunyuan

Copy link
Copy Markdown
Contributor

Why (in your own words)

gstack-gate --help still gives the reply grammar as it shipped in #3115: all · <id><option> tokens · all except <tokens>.

Since 1.91.107.0 (#3190) the parser leads with rec, keeps all as an alias and adds as-is. Everything else already says so:

  • the rendered gate list (lib/gate-list.ts:117)
  • the GATE_REPLY_UNPARSED fix text in RESULT_CODES (lib/result-codes.ts:117)
  • docs/unattended.md

A parent agent that learns the grammar from --help never sees rec or as-is, while the list it relays to the owner leads with rec. Nothing parses differently (all except d1b and rec except d1b resolve to the same choices); the help text was left behind.

The same old grammar also sat in the Fix. paragraph of docs/troubleshooting.md#gate-reply-unparsed. That copy now matches the result-code row.

Fixes #3282.

Why this shape

  • The help line is the reporter's expected text, word for word: "Reply grammar: rec (alias all) · rec except <tokens> · <id><option> tokens (d3b uc1a) · as-is. Bare yes/no is rejected."
  • The troubleshooting copy isn't in the issue. The docs rule (fix stale copies of the same sentence in the same commit) brings it in, in the order the RESULT_CODES row uses.
  • The test doesn't pin the new wording.
    • It reads the reply forms from the rendered list's "Reply with exactly one of:" line, and requires each one in --help's "Reply grammar:" line.
    • The next grammar change then fails the test until --help catches up, and the test never needs the words. That keeps the file's rule: "Prose in the rendering is not pinned."
    • It is red on upstream/main (no `rec`) and green here.
  • CONTRIBUTING's wave rule: if two PRs fix the same thing, keep the smaller one. This is 1 commit in 3 files (+12/−4), on current main, and fine to absorb into a wave.

What it does

  • bin/gstack-gate: the Reply grammar: line of --help.
  • docs/troubleshooting.md: the GATE_REPLY_UNPARSED Fix. paragraph.
  • test/gate-list.test.ts: one test in describe('bin/gstack-gate').

What it deliberately does not do

  • No parser or render change. all, approve all and the other aliases keep working, and the rendered Reply with line is untouched.
  • No single-source refactor (building --help from the render's grammar). The test guards the drift instead. Happy to do the refactor if you'd rather have it.
  • Historical copies left alone: docs/designs/* and test/fixtures/multi-agent-wave/* keep the original B9 grammar, as records of the plan.
  • Release files and docs: VERSION / CHANGELOG / README / ETHOS untouched, and no generated files. /ship not run (the wave stamps the version).

AI was used for assistance.

Live evidence

Setup. A synthetic one-item gate list in a temp dir. gstack-gate writes nothing.

Before (upstream/main at afac8dfd8): --help and the rendered list disagree.

$ gstack-gate --help | grep "Reply grammar"
Reply grammar: `all` · `<id><option>` tokens (`d3b uc1a`) · `all except <tokens>`. Bare yes/no is rejected.
$ gstack-gate render gate.json | grep "Reply with"
Reply with exactly one of: `rec` (default: take every recommendation, plan changes included) · `rec except <tokens>` · `<id><option>` tokens, e.g. `d1b` · `as-is` (the plan as written).

After (this branch, afff2b927): they agree, and the all alias still parses the same as rec.

$ gstack-gate --help | grep "Reply grammar"
Reply grammar: `rec` (alias `all`) · `rec except <tokens>` · `<id><option>` tokens (`d3b uc1a`) · `as-is`. Bare yes/no is rejected.
$ gstack-gate render gate.json | grep "Reply with"
Reply with exactly one of: `rec` (default: take every recommendation, plan changes included) · `rec except <tokens>` · `<id><option>` tokens, e.g. `d1b` · `as-is` (the plan as written).
$ gstack-gate parse gate.json --reply "all except d1b" --gate-rev 1 --json
{"valid":true,"gate_rev":1,"reply":"all except d1b","choices":[{"id":"d1","chosen":"b","kind":"auto","how":"override"}],"pending":[],"unparsed":[],"mode":"rec"}
$ gstack-gate parse gate.json --reply "rec except d1b" --gate-rev 1 --json
{"valid":true,"gate_rev":1,"reply":"rec except d1b","choices":[{"id":"d1","chosen":"b","kind":"auto","how":"override"}],"pending":[],"unparsed":[],"mode":"rec"}

Scope

  • Changed: bin/gstack-gate (+1/−1), docs/troubleshooting.md (+3/−3), test/gate-list.test.ts (+8). No VERSION, no CHANGELOG, no generated files.
  • Verified live by:
    • The new test is red on upstream/main, green here.
      • On afac8dfd8 it fails at toContain('`rec`'), receiving the old Reply grammar: line.
      • Here, all 15 tests in test/gate-list.test.ts pass.
    • Every file pregate selects for this diff. origin is my fork, so I pointed a temporary origin/pregate-base ref at upstream/main (afac8dfd8):
      • pregate selects 17 files, and I ran each alone with the runner's --timeout=30000.
      • 16 pass.
      • autoplan-gate-artifacts fails 3 tests here and the same 3 on upstream/main: gstack-autoplan next refuses with "bun 1.4.0 is below the supported minimum 1.4.2". This box has Bun 1.4.0; CI pins 1.4.2.
    • Typecheck: bun run typecheck exits 0.
    • Open PRs on the same files: it merges cleanly with main and with the four open PRs that touch docs/troubleshooting.md (fix(pregate): Dart import graph and test lanes #3285, feat(pregate): user-owned policy file and local lanes #3286, v1.91.153.0 fix(outside-review): no-findings counts only as the review's conclusion; add regressions (#3294) #3304, v1.91.161.0 fix(pregate): Django, Dart, asset and tool-config lanes; init drafts from the repo (#3266-#3269) #3306).
    • Full bun run test: not green on this Linux box, on upstream/main either.
      • This run on afff2b927 failed 365 tests in 69 files.
      • The main causes:
        • Bun 1.4.0 here is below gstack's 1.4.2 floor.
        • Chromium can't launch here (no Xvfb).
        • The /cso suites need bun run build:cso and Docker.
      • pregate's import graph links one of the 69 files to this diff: autoplan-gate-artifacts, above.
      • Against my previous full run on this box (another branch, on 2d42e4ece), no file fails now that didn't fail then, and every common file has the same count.
      • The serial shard 17 (bootstrap-retention) passed its 36 tests but was marked failed by the home-containment check: ~/.claude/sessions/<id>.json changed while it ran, and that file belongs to a live Claude Code session on this machine. No new ~/.gstack/projects entries.
      • CI's Linux free suite is the gate.
    • slop-scan: 706 findings on both trees, none in the changed files.
    • Paid evals: bun run eval:select --base upstream/main picks the whole PR gate (108 behaviors, 24 judges), because every gate case reaches bin/gstack-gate. Fork PRs get no eval secrets, so I couldn't run it. The change is the --help text only: render, parse and decisions output is byte-identical (the two Reply with lines above), so a case that relays or answers a gate is unaffected.
    • Redaction: bin/gstack-redact --repo-visibility public on the diff reports no findings. git diff --check is clean.
  • Did NOT test: Windows. CI's Windows Free Tests covers it.

Liveness proof (required for external contributors)

image

Checklist

Test plan

  • The new test is red on upstream/main and green here
  • Every file pregate selects for this diff (above)
  • Before/After evidence for --help, the rendered list and the alias
  • Full bun run test: the same environment failures as upstream/main; none comes from the changed files
  • CI free tests on this PR (Free Tests and Windows Free Tests)

Fork PRs do not get eval secrets; the free files above are the gate.

Fixes #3282

… / as-is grammar (garrytan#3282)

gstack-gate --help still gave the reply grammar as it shipped in garrytan#3115
(`all`, `all except <tokens>`), and so did the GATE_REPLY_UNPARSED fix
in docs/troubleshooting.md. Since 1.91.107.0 the parser leads with
`rec` (alias `all`) and adds `as-is`, and the rendered list, the
result-code fix text and docs/unattended.md say so. A parent that
learned the grammar from --help never saw `rec` or `as-is`.

Both now match the render. A test requires every reply form the
rendered list offers to appear in --help's grammar line, so the next
grammar change cannot leave the help behind again.

Fixes garrytan#3282

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trunk-io

trunk-io Bot commented Oct 19, 2026

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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.

gstack-gate --help still documents the pre-1.91.107.0 reply grammar (all), without rec and as-is

1 participant