From 19e699ab9b69de9e1bf10d4b7c2682703b56f984 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 5 May 2026 21:18:35 -0700 Subject: [PATCH] v1.26.4.0 fix: GSTACK REVIEW REPORT delete-then-append (no more mid-file leftovers) (#1335) * fix: GSTACK REVIEW REPORT delete-then-append flow Replaces contradictory "replace it entirely" + "always last section / move if mid-file" bullets in scripts/resolvers/review.ts with a single delete-then-append rule. Adds Read-tool verification step so the agent self-checks before continuing. Affected SKILL.md files (regenerated): plan-ceo-review, plan-design-review, plan-devex-review, plan-eng-review, codex, devex-review. * test: static template assertions for delete-then-append + revert autoplan E2E shape 5 new static tests in test/gen-skill-docs.test.ts (4 plan-review SKILL.md files + 1 source resolver) verify the new prompt language is present and the old contradictory bullets are absent. Synthetic regression check confirmed all 5 fail when the prompt fix is reverted. The autoplan E2E (skill-e2e-autoplan-auto-mode.test.ts) reverts to its original AUQ-blocked-gate-surface shape. The mid-file regression scenario the plan briefly proposed isn't reachable in the current PTY harness because --disallowedTools AskUserQuestion makes autoplan bail at the Phase 1 premise gate before any review-write code path runs. Static prompt-text verification covers the load-bearing change. * chore: bump version and changelog (v1.26.4.0) Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 26 +++++++++++++ VERSION | 2 +- codex/SKILL.md | 32 +++++++++++----- devex-review/SKILL.md | 32 +++++++++++----- package.json | 2 +- plan-ceo-review/SKILL.md | 32 +++++++++++----- plan-design-review/SKILL.md | 32 +++++++++++----- plan-devex-review/SKILL.md | 32 +++++++++++----- plan-eng-review/SKILL.md | 32 +++++++++++----- scripts/resolvers/review.ts | 32 +++++++++++----- test/gen-skill-docs.test.ts | 45 +++++++++++++++++++++++ test/skill-e2e-autoplan-auto-mode.test.ts | 10 +++++ 12 files changed, 244 insertions(+), 65 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 176bb55f..fc49d3cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## [1.26.4.0] - 2026-05-05 + +## **`/autoplan` review reports now reliably land at the bottom of the plan, even when an older copy lives mid-file.** + +The `## GSTACK REVIEW REPORT` section had a write rule that contradicted itself: one bullet said "replace it entirely (in place)" while another said "always last section, move if mid-file." When the agent inherited a plan whose prior `/autoplan` run had landed before user-added sections, the in-place replace path won and the new report stayed mid-file. The user opened ExitPlanMode, saw their plan with no review at the bottom, and had to ask twice. Single delete-then-append rule now, with a Read-tool verification step before the next instruction runs. + +### What you can now do + +- **Run `/autoplan` against a plan that already has a stale `## GSTACK REVIEW REPORT` mid-file and trust the new report ends up at the bottom.** The instruction in `scripts/resolvers/review.ts` (which feeds `/plan-ceo-review`, `/plan-eng-review`, `/plan-design-review`, `/plan-devex-review`, `/codex`, `/devex-review`) now reads as one rule: search for any existing report section, delete it wherever it lives, append a fresh report at end of file, verify with the Read tool that the report is the last `##` heading. No more contradiction for the agent to reconcile. + +### What gets safer + +- **Five static template assertions in `test/gen-skill-docs.test.ts` lock the prompt change against drift.** Each plan-review SKILL.md (4 of them) plus the source resolver are checked for the new "delete-then-append flow" / "never mid-file" / "Do NOT replace the section in place" markers AND the absence of the old "replace it** entirely using the Edit tool" / "If it was found mid-file, move it" bullets. Synthetic regression check confirmed: all 5 fail when the prompt is reverted, all 5 pass when restored. The tests are bound to the change, not to incidentally green output. + +### Itemized changes + +#### Changed +- `scripts/resolvers/review.ts` — "Write to the plan file" subsection rewritten. Old contradictory pair ("replace it entirely" vs "always last / move if mid-file") collapsed into a single 4-step delete-then-append flow with explicit verification. +- All 6 generated SKILL.md files refreshed to carry the new instruction: `plan-ceo-review`, `plan-design-review`, `plan-devex-review`, `plan-eng-review`, `codex`, `devex-review`. + +#### Added +- `test/gen-skill-docs.test.ts` — new `GSTACK REVIEW REPORT delete-then-append flow` describe block: 4 SKILL.md target tests + 1 source resolver test. Static, deterministic, free. + +#### For contributors +- The `/autoplan` E2E approach attempted in the plan was dropped after a paid run revealed that `--disallowedTools AskUserQuestion` makes autoplan bail at the Phase 1 premise gate via the plan-file fallback. The PTY harness can't drive autoplan through its review phases without auto-progression of AskUserQuestions. The static prompt-text test catches the load-bearing change without needing that infrastructure. + ## [1.26.3.0] - 2026-05-03 ## **`/sync-gbrain` keeps your brain current and teaches the agent when to use it.** diff --git a/VERSION b/VERSION index 068ff0d4..1dbe2689 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.26.3.0 +1.26.4.0 diff --git a/codex/SKILL.md b/codex/SKILL.md index 44b5f0ed..e7cb13c3 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -1047,15 +1047,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. --- diff --git a/devex-review/SKILL.md b/devex-review/SKILL.md index 53030027..3e00c49e 100644 --- a/devex-review/SKILL.md +++ b/devex-review/SKILL.md @@ -1153,15 +1153,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. ## Capture Learnings diff --git a/package.json b/package.json index 380239b5..6ca9c412 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gstack", - "version": "1.26.3.0", + "version": "1.26.4.0", "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/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index 42344be3..7e04c143 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -1958,15 +1958,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. ## Next Steps — Review Chaining diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index d6ae7013..7cac8695 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -1722,15 +1722,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. ## Capture Learnings diff --git a/plan-devex-review/SKILL.md b/plan-devex-review/SKILL.md index 22c508b3..d61828ed 100644 --- a/plan-devex-review/SKILL.md +++ b/plan-devex-review/SKILL.md @@ -1926,15 +1926,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. ## Capture Learnings diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index 9d9e623f..bed2b2ee 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -1537,15 +1537,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \`## GSTACK REVIEW REPORT\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \`## GSTACK REVIEW REPORT\` - through either the next \`## \` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end. +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \`## GSTACK REVIEW REPORT\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \`## GSTACK REVIEW REPORT\` through either the next \`## \` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \`## GSTACK REVIEW REPORT\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \`## GSTACK REVIEW REPORT\` is the last + \`## \` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it. ## Capture Learnings diff --git a/scripts/resolvers/review.ts b/scripts/resolvers/review.ts index 53c7b08d..e9a8d3e5 100644 --- a/scripts/resolvers/review.ts +++ b/scripts/resolvers/review.ts @@ -133,15 +133,29 @@ Below the table, add these lines (omit any that are empty/not applicable): file you are allowed to edit in plan mode. The plan file review report is part of the plan's living status. -- Search the plan file for a \\\`## GSTACK REVIEW REPORT\\\` section **anywhere** in the file - (not just at the end — content may have been added after it). -- If found, **replace it** entirely using the Edit tool. Match from \\\`## GSTACK REVIEW REPORT\\\` - through either the next \\\`## \\\` heading or end of file, whichever comes first. This ensures - content added after the report section is preserved, not eaten. If the Edit fails - (e.g., concurrent edit changed the content), re-read the plan file and retry once. -- If no such section exists, **append it** to the end of the plan file. -- Always place it as the very last section in the plan file. If it was found mid-file, - move it: delete the old location and append at the end.`; +The report must always be the LAST section of the plan file — never mid-file. +Use a single delete-then-append flow: + +1. Read the plan file (Read tool) to see its full current content. Search the read + output for a \\\`## GSTACK REVIEW REPORT\\\` heading anywhere in the file. +2. If found, use the Edit tool to DELETE the entire existing section. Match from + \\\`## GSTACK REVIEW REPORT\\\` through either the next \\\`## \\\` heading or end of + file, whichever comes first. Replace with the empty string. This applies + regardless of where the section currently lives — mid-file deletion is + intentional, not a special case. If the Edit fails (e.g., concurrent edit + changed the content), re-read the plan file and retry once. +3. After the delete (or skipped, if no section existed), append the new + \\\`## GSTACK REVIEW REPORT\\\` section at the END of the file. Use the Edit + tool to match the file's current last paragraph and add the section after it, + or use Write to re-emit the whole file with the section at the end. +4. Verify with the Read tool that \\\`## GSTACK REVIEW REPORT\\\` is the last + \\\`## \\\` heading in the file before continuing. If it isn't, repeat steps + 2-3 once. + +Do NOT replace the section in place. The "replace mid-file" path is what allowed +prior versions to leave the report mid-file when an older report already lived +there — the user then sees a plan whose review report is not at the bottom and +(correctly) rejects it.`; } export function generateSpecReviewLoop(_ctx: TemplateContext): string { diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index aa2e2d9f..7249a448 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -2977,3 +2977,48 @@ describe('plan-mode-info resolver (handshake-replacement)', () => { expect(between).toContain('Do NOT proceed to Step 0D or 0F until the user responds to 0C-bis'); }); }); + +// GSTACK REVIEW REPORT report-at-bottom contract — verifies the prompt-text +// fix in scripts/resolvers/review.ts (the load-bearing change for the +// "report not at bottom of plan in plan mode" bug). The bug is in the +// prompt's contradictory write-flow instructions, not in observable +// runtime behavior we can cheaply gate in CI. Verifying the prompt text +// directly is the deterministic equivalent of the regression test the +// PTY harness can't reliably drive (autoplan needs auto-progression of +// AskUserQuestions to reach the report-write step, which the harness +// doesn't support today). +describe('GSTACK REVIEW REPORT delete-then-append flow', () => { + const PLAN_REVIEW_SKILLS = [ + 'plan-ceo-review', + 'plan-design-review', + 'plan-devex-review', + 'plan-eng-review', + ]; + + for (const skill of PLAN_REVIEW_SKILLS) { + test(`${skill}/SKILL.md prescribes delete-then-append, not in-place replace`, () => { + const content = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8'); + + // The new (correct) instruction must be present. + expect(content).toContain('delete-then-append flow'); + expect(content).toContain('never mid-file'); + expect(content).toContain('Do NOT replace the section in place'); + + // The old contradictory bullets must be gone. The signature phrase + // from the buggy prompt was 'replace it entirely using the Edit tool' + // which is what allowed mid-file reports to stay mid-file. + expect(content).not.toContain('replace it** entirely using the Edit tool'); + expect(content).not.toContain('If it was found mid-file, move it'); + }); + } + + test('scripts/resolvers/review.ts source has the rewritten flow', () => { + const src = fs.readFileSync(path.join(ROOT, 'scripts', 'resolvers', 'review.ts'), 'utf-8'); + expect(src).toContain('delete-then-append flow'); + expect(src).toContain('never mid-file'); + expect(src).toContain('Do NOT replace the section in place'); + // Old contradictory bullets are gone from the source resolver. + expect(src).not.toContain('replace it** entirely using the Edit tool'); + expect(src).not.toContain('If it was found mid-file, move it'); + }); +}); diff --git a/test/skill-e2e-autoplan-auto-mode.test.ts b/test/skill-e2e-autoplan-auto-mode.test.ts index f5fe84db..0677917b 100644 --- a/test/skill-e2e-autoplan-auto-mode.test.ts +++ b/test/skill-e2e-autoplan-auto-mode.test.ts @@ -18,6 +18,16 @@ * Filename keeps `auto-mode` for branch-history continuity. Auto-mode (the * AUTO_DECIDE preamble path when QUESTION_TUNING=true) is a related but * distinct silencing mechanism; both share the same fix surface. + * + * Note on report-at-bottom contract: the GSTACK REVIEW REPORT delete-then- + * append flow lives in `scripts/resolvers/review.ts` and is exercised when + * reviews actually run. The PTY harness can't drive autoplan through its + * review phases without auto-progression of AUQs (see runPlanSkillCounting), + * and `--disallowedTools AskUserQuestion` makes autoplan bail at the + * premise gate via the plan-file fallback before any review runs. The + * report-at-bottom prompt change is verified statically in + * `test/gen-skill-docs.test.ts` instead — that's the load-bearing + * verification for the contradictory-prompt fix. */ import { describe, test, expect } from 'bun:test';