From f1cbdbb48313957613bafb2d05346afc876fed89 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Mon, 2 Nov 2026 15:15:57 -0800 Subject: [PATCH] v1.93.24.0 GSTA-253 ship judge flake: one owner for the release commit, defined skipped/kept result (#3881) * fix(ship): one owner for the release commit and a defined result for a skipped or kept version (ship judge flake, GSTA-253) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (Step 12 names the no-write kept line exactly) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship): Step 15 states the no-tag rule outright (ship-workflow-clarity) 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> --- CHANGELOG.md | 7 +++++++ VERSION | 2 +- agents-digest/gstack-AGENTS.md | 2 +- package.json | 2 +- ship/SKILL.md | 18 +++++------------- ship/SKILL.md.tmpl | 18 +++++------------- test/fixtures/golden/agy-ship-SKILL.md | 18 +++++------------- test/fixtures/golden/claude-ship-SKILL.md | 18 +++++------------- test/fixtures/golden/codex-ship-SKILL.md | 18 +++++------------- test/fixtures/golden/factory-ship-SKILL.md | 18 +++++------------- test/ship-plan-completion-invariants.test.ts | 16 ++++++++++++++++ .../ship/capy-gsta253-ship-judge.json | 4 ++++ 12 files changed, 60 insertions(+), 81 deletions(-) create mode 100644 test/size-ledger/ship/capy-gsta253-ship-judge.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d0b33e8..574a8987b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.93.24.0] - 2026-11-02 + +**The /ship workflow judge loses the contradiction it cited in every recorded red sample.** + +### Fixed +- **`ship/SKILL.md` Steps 12 and 15**: Step 15 no longer tells the agent to make the VERSION/CHANGELOG commit by hand while Step 16's `gstack-ship-release finish` makes the same commit. Feature work is committed in Step 15, and `finish` commits the release files last with the co-author trailer. Step 12 now says what a `VERSION: skipped` (stamp-at-merge or changelog fragments) or `VERSION: kept` result leaves for Steps 13, 18 and 20. All six judge samples in the two recorded reds (E2E Evals 41429095451, 41445571955) named the commit conflict, and three named the undefined skipped/kept result. Three focused judge runs on the fix passed (actionability median 4 each), and none of their nine samples cited either one. + ## [1.93.23.0] - 2026-11-02 **Four tests from the 2026-11-02 flaky pass stop failing correct runs, and one more names its cause when it fails.** diff --git a/VERSION b/VERSION index f6f8c5632..8eae0b3f6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.93.23.0 +1.93.24.0 diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md index 068816677..1e6f2ef3d 100644 --- a/agents-digest/gstack-AGENTS.md +++ b/agents-digest/gstack-AGENTS.md @@ -1,4 +1,4 @@ -# gstack digest v1.93.23.0 — regenerate/re-copy after upgrading gstack +# gstack digest v1.93.24.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/package.json b/package.json index 13d24a6c0..0863537e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.93.23", + "version": "1.93.24", "description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.", "license": "MIT", "type": "module", diff --git a/ship/SKILL.md b/ship/SKILL.md index 43ec62eab..4970033c0 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -520,7 +520,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -641,19 +642,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -Co-Authored-By: Claude -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer 'Co-Authored-By: Claude '`. Do not add a Git tag. --- diff --git a/ship/SKILL.md.tmpl b/ship/SKILL.md.tmpl index 68483a085..1dc0ce129 100644 --- a/ship/SKILL.md.tmpl +++ b/ship/SKILL.md.tmpl @@ -243,7 +243,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -362,19 +363,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -{{CO_AUTHOR_TRAILER}} -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer '{{CO_AUTHOR_TRAILER}}'`. Do not add a Git tag. --- diff --git a/test/fixtures/golden/agy-ship-SKILL.md b/test/fixtures/golden/agy-ship-SKILL.md index 3b8907a44..19c18da44 100644 --- a/test/fixtures/golden/agy-ship-SKILL.md +++ b/test/fixtures/golden/agy-ship-SKILL.md @@ -521,7 +521,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -642,19 +643,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -Co-Authored-By: Claude -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer 'Co-Authored-By: Claude '`. Do not add a Git tag. --- diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index 43ec62eab..4970033c0 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -520,7 +520,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -641,19 +642,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -Co-Authored-By: Claude -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer 'Co-Authored-By: Claude '`. Do not add a Git tag. --- diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 093381d4f..db764395a 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -520,7 +520,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -644,19 +645,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -Co-Authored-By: OpenAI Codex -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer 'Co-Authored-By: OpenAI Codex '`. Do not add a Git tag. --- diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 4e89c2bf5..6057b83c8 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -522,7 +522,8 @@ chooses it in item 2 and ALREADY_BUMPED derives it in item 1. runs items 1 and 3–5; each decision left to you is a `STOP:` naming its rerun flag (`--bump`, `--accept-incomplete`, `--version `, `--keep-current`, `--answer`). -`ship: queue_mode stamp-at-merge` replaces items 1–4. +`VERSION: skipped` or `VERSION: kept (…; no write)` ends Step 12 with +`NEW_VERSION` unset: Step 13 follows its `NEXT:`; Steps 18 and 20 take NO_VERSION's branch. 1. **Classify state** — pure reader, never writes: ```bash @@ -646,19 +647,10 @@ Make bisectable commits; if already committed, continue to Step 16. Never create migrations may stand alone. Under 50 lines across fewer than 4 files may be one commit. 2. Order dependencies first: infrastructure → models/services → controllers/views. Each commit works alone (no broken imports or missing code). - Group VERSION + CHANGELOG + TODOS.md after the feature commits. 3. Use `: ` (feat/fix/chore/refactor/docs) and a brief body; fixing a - user-named issue adds a `Fixes: #` trailer. Only the final - VERSION/CHANGELOG commit gets the release version and co-author trailer. No Git tag: - -```bash -git commit -m "$(cat <<'EOF' -chore: bump version and changelog (vX.Y.Z.W) - -Co-Authored-By: Factory Droid -EOF -)" -``` + user-named issue adds a `Fixes: #` trailer. Leave VERSION, CHANGELOG/fragment, TODOS.md + and the digest uncommitted: Step 16's `finish` commits them last with + `--trailer 'Co-Authored-By: Factory Droid '`. Do not add a Git tag. --- diff --git a/test/ship-plan-completion-invariants.test.ts b/test/ship-plan-completion-invariants.test.ts index be3191b0d..4a292edd4 100644 --- a/test/ship-plan-completion-invariants.test.ts +++ b/test/ship-plan-completion-invariants.test.ts @@ -185,6 +185,22 @@ describe('ship/SKILL.md — Plan Completion gate invariants', () => { expect(entry).not.toMatch(/Step 15\.[012]/); }); + test('one owner per release commit and a defined result for a version Step 12 does not write', () => { + // Value: protects=the ship workflow judge's 6/6 cited conflict (Step 15 committed release metadata by hand while Step 16 finish also commits it) and its 3/6 undefined stamp-at-merge/kept result; fails_when=Step 15 regains a manual release commit or Step 12 drops the skipped/kept route; why_new=no pin covered commit ownership; seam=none; no_claim=judge scores + const entry = fs.readFileSync(path.join(SHIP_DIR, 'SKILL.md'), 'utf8'); + const commit = entry.slice(entry.indexOf('## Step 15:'), entry.indexOf('## Step 16:')); + expect(commit).not.toContain('git commit'); + expect(commit.replace(/\s+/g, ' ')).toMatch(/TODOS\.md and the digest uncommitted: Step 16's `finish` commits them last/); + const finish = entry.slice(entry.indexOf('## Step 16:'), entry.indexOf('### 1. Finish writers')); + expect(finish).toContain("makes Step 15's item-3 commit"); + const version = entry.slice(entry.indexOf('## Step 12:'), entry.indexOf('1. **Classify state**')).replace(/\s+/g, ' '); + expect(version).not.toContain('replaces items 1–4'); + expect(version).toContain('`VERSION: skipped`'); + expect(version).toContain('`VERSION: kept (…; no write)` ends Step 12 with `NEW_VERSION` unset'); + expect(version).toContain('ALREADY_BUMPED derives it in item 1'); + expect(version).toContain("Steps 18 and 20 take NO_VERSION's branch"); + }); + test('a rejected push stops publication and routes changed content back through verification', () => { const entry = fs.readFileSync(path.join(SHIP_DIR, 'SKILL.md'), 'utf8'); const push = entry.slice(entry.indexOf('## Step 17:'), entry.indexOf('## Step 20:')); diff --git a/test/size-ledger/ship/capy-gsta253-ship-judge.json b/test/size-ledger/ship/capy-gsta253-ship-judge.json new file mode 100644 index 000000000..9158b7122 --- /dev/null +++ b/test/size-ledger/ship/capy-gsta253-ship-judge.json @@ -0,0 +1,4 @@ +{ + "bytes": 4, + "why": "Steps 12 and 15 name who makes the release commit and what a skipped or kept version leaves for Steps 13, 18 and 20 (ship workflow judge flake, GSTA-253)" +}