diff --git a/SKILL.md b/SKILL.md index 1a61ac96f..c6441014c 100644 --- a/SKILL.md +++ b/SKILL.md @@ -473,9 +473,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. If `PROACTIVE` is `false`: do NOT proactively invoke or suggest other gstack skills during this session. Only run skills the user explicitly invokes. This preference persists across diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index c64e6e8bd..5394c16bc 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -766,9 +766,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/benchmark-models/SKILL.md b/benchmark-models/SKILL.md index 5e5e6bd66..47050855b 100644 --- a/benchmark-models/SKILL.md +++ b/benchmark-models/SKILL.md @@ -475,9 +475,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /benchmark-models — Cross-Model Skill Benchmark diff --git a/benchmark/SKILL.md b/benchmark/SKILL.md index 46934ba3d..b6dc81373 100644 --- a/benchmark/SKILL.md +++ b/benchmark/SKILL.md @@ -475,9 +475,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## SETUP (run this check BEFORE any browse command) diff --git a/browse/SKILL.md b/browse/SKILL.md index 1d544756c..6a4f5c269 100644 --- a/browse/SKILL.md +++ b/browse/SKILL.md @@ -474,9 +474,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # browse: QA Testing & Dogfooding diff --git a/canary/SKILL.md b/canary/SKILL.md index a211c386a..1ba6ecec7 100644 --- a/canary/SKILL.md +++ b/canary/SKILL.md @@ -740,9 +740,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## SETUP (run this check BEFORE any browse command) diff --git a/codex/SKILL.md b/codex/SKILL.md index f6b507697..edf4075f2 100644 --- a/codex/SKILL.md +++ b/codex/SKILL.md @@ -760,9 +760,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch @@ -1153,6 +1151,31 @@ 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. +## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST `## ` heading in the file is `## GSTACK REVIEW REPORT`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured `## GSTACK REVIEW REPORT` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + `gstack-review-log` was called and `gstack-review-read` was run at least + once. If no plan file is in context (e.g. `/codex consult` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading. + --- ## Step 2B: Challenge (Adversarial) Mode diff --git a/codex/SKILL.md.tmpl b/codex/SKILL.md.tmpl index ab2a405f8..329e93c4f 100644 --- a/codex/SKILL.md.tmpl +++ b/codex/SKILL.md.tmpl @@ -295,6 +295,8 @@ rm -f "$TMPERR" {{PLAN_FILE_REVIEW_REPORT}} +{{EXIT_PLAN_MODE_GATE}} + --- ## Step 2B: Challenge (Adversarial) Mode diff --git a/context-restore/SKILL.md b/context-restore/SKILL.md index 4f0cd70eb..92eb1cdd1 100644 --- a/context-restore/SKILL.md +++ b/context-restore/SKILL.md @@ -744,9 +744,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /context-restore — Restore Saved Working Context diff --git a/context-save/SKILL.md b/context-save/SKILL.md index b083b039f..5a7b0d60e 100644 --- a/context-save/SKILL.md +++ b/context-save/SKILL.md @@ -744,9 +744,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /context-save — Save Working Context diff --git a/cso/SKILL.md b/cso/SKILL.md index fe12df74e..70d8105e7 100644 --- a/cso/SKILL.md +++ b/cso/SKILL.md @@ -745,9 +745,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. diff --git a/design-consultation/SKILL.md b/design-consultation/SKILL.md index ed4d3811b..00a5f0f2e 100644 --- a/design-consultation/SKILL.md +++ b/design-consultation/SKILL.md @@ -786,9 +786,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /design-consultation: Your Design System, Built Together diff --git a/design-html/SKILL.md b/design-html/SKILL.md index 2337af721..5c92f7703 100644 --- a/design-html/SKILL.md +++ b/design-html/SKILL.md @@ -747,9 +747,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /design-html: Pretext-Native HTML Engine diff --git a/design-review/SKILL.md b/design-review/SKILL.md index d17c07678..91603dd2e 100644 --- a/design-review/SKILL.md +++ b/design-review/SKILL.md @@ -763,9 +763,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. diff --git a/design-shotgun/SKILL.md b/design-shotgun/SKILL.md index 2f8ac7abb..178416ba2 100644 --- a/design-shotgun/SKILL.md +++ b/design-shotgun/SKILL.md @@ -762,9 +762,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /design-shotgun: Visual Design Exploration diff --git a/devex-review/SKILL.md b/devex-review/SKILL.md index fd8dbf908..49d5ae212 100644 --- a/devex-review/SKILL.md +++ b/devex-review/SKILL.md @@ -763,9 +763,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/document-generate/SKILL.md b/document-generate/SKILL.md index d9e0ddeb8..e6cf9965d 100644 --- a/document-generate/SKILL.md +++ b/document-generate/SKILL.md @@ -747,9 +747,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/document-release/SKILL.md b/document-release/SKILL.md index 24d48aaaa..b49f4e89b 100644 --- a/document-release/SKILL.md +++ b/document-release/SKILL.md @@ -744,9 +744,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/health/SKILL.md b/health/SKILL.md index b5471c0e8..396c980b2 100644 --- a/health/SKILL.md +++ b/health/SKILL.md @@ -742,9 +742,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /health -- Code Quality Dashboard diff --git a/investigate/SKILL.md b/investigate/SKILL.md index 9e2b23f0f..b7780c1c4 100644 --- a/investigate/SKILL.md +++ b/investigate/SKILL.md @@ -781,9 +781,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # Systematic Debugging diff --git a/land-and-deploy/SKILL.md b/land-and-deploy/SKILL.md index 1c19c98b0..b58ec2316 100644 --- a/land-and-deploy/SKILL.md +++ b/land-and-deploy/SKILL.md @@ -757,9 +757,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## SETUP (run this check BEFORE any browse command) diff --git a/landing-report/SKILL.md b/landing-report/SKILL.md index e14817cfa..be8aed5e1 100644 --- a/landing-report/SKILL.md +++ b/landing-report/SKILL.md @@ -758,9 +758,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. --- diff --git a/learn/SKILL.md b/learn/SKILL.md index 899ad42c1..3599115b8 100644 --- a/learn/SKILL.md +++ b/learn/SKILL.md @@ -742,9 +742,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # Project Learnings Manager diff --git a/make-pdf/SKILL.md b/make-pdf/SKILL.md index 927b637d9..045e31516 100644 --- a/make-pdf/SKILL.md +++ b/make-pdf/SKILL.md @@ -510,9 +510,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # make-pdf: publication-quality PDFs from markdown diff --git a/office-hours/SKILL.md b/office-hours/SKILL.md index 6170f0e5f..c4acb9ea8 100644 --- a/office-hours/SKILL.md +++ b/office-hours/SKILL.md @@ -795,9 +795,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## SETUP (run this check BEFORE any browse command) diff --git a/open-gstack-browser/SKILL.md b/open-gstack-browser/SKILL.md index b510d9d7b..8b4b0c493 100644 --- a/open-gstack-browser/SKILL.md +++ b/open-gstack-browser/SKILL.md @@ -757,9 +757,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /open-gstack-browser — Launch GStack Browser diff --git a/pair-agent/SKILL.md b/pair-agent/SKILL.md index 8ddaf5e1a..dd7a51ecd 100644 --- a/pair-agent/SKILL.md +++ b/pair-agent/SKILL.md @@ -758,9 +758,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /pair-agent — Share Your Browser With Another AI Agent diff --git a/plan-ceo-review/SKILL.md b/plan-ceo-review/SKILL.md index 0f1738aec..fedb75645 100644 --- a/plan-ceo-review/SKILL.md +++ b/plan-ceo-review/SKILL.md @@ -789,9 +789,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch @@ -2126,3 +2124,28 @@ already knows. A good test: would this insight save time in a future session? If │ (Sec 11) │ UI review │ detected │ detected │ │ └─────────────┴──────────────┴──────────────┴──────────────┴────────────────────┘ ``` + +## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST `## ` heading in the file is `## GSTACK REVIEW REPORT`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured `## GSTACK REVIEW REPORT` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + `gstack-review-log` was called and `gstack-review-read` was run at least + once. If no plan file is in context (e.g. `/codex consult` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading. diff --git a/plan-ceo-review/SKILL.md.tmpl b/plan-ceo-review/SKILL.md.tmpl index 7da8f5761..ef71e8c83 100644 --- a/plan-ceo-review/SKILL.md.tmpl +++ b/plan-ceo-review/SKILL.md.tmpl @@ -890,3 +890,5 @@ If promoted, copy the CEO plan content to `docs/designs/{FEATURE}.md` (create th │ (Sec 11) │ UI review │ detected │ detected │ │ └─────────────┴──────────────┴──────────────┴──────────────┴────────────────────┘ ``` + +{{EXIT_PLAN_MODE_GATE}} diff --git a/plan-design-review/SKILL.md b/plan-design-review/SKILL.md index 699bacf69..10c590215 100644 --- a/plan-design-review/SKILL.md +++ b/plan-design-review/SKILL.md @@ -762,9 +762,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch @@ -1846,3 +1844,28 @@ Use AskUserQuestion to present the next step. Include only applicable options: * One sentence max per option. * After each pass, pause and wait for feedback. * Rate before and after each pass for scannability. + +## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST `## ` heading in the file is `## GSTACK REVIEW REPORT`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured `## GSTACK REVIEW REPORT` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + `gstack-review-log` was called and `gstack-review-read` was run at least + once. If no plan file is in context (e.g. `/codex consult` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading. diff --git a/plan-design-review/SKILL.md.tmpl b/plan-design-review/SKILL.md.tmpl index 24e89a01e..a64e23150 100644 --- a/plan-design-review/SKILL.md.tmpl +++ b/plan-design-review/SKILL.md.tmpl @@ -475,3 +475,5 @@ Use AskUserQuestion to present the next step. Include only applicable options: * One sentence max per option. * After each pass, pause and wait for feedback. * Rate before and after each pass for scannability. + +{{EXIT_PLAN_MODE_GATE}} diff --git a/plan-devex-review/SKILL.md b/plan-devex-review/SKILL.md index 886964a58..0172df6bc 100644 --- a/plan-devex-review/SKILL.md +++ b/plan-devex-review/SKILL.md @@ -766,9 +766,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch @@ -2047,3 +2045,28 @@ Outside voice| Recommended | Recommended | Skip * One sentence max per option. * After each pass, pause and wait for feedback before moving on. * Rate before and after each pass for scannability. + +## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST `## ` heading in the file is `## GSTACK REVIEW REPORT`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured `## GSTACK REVIEW REPORT` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + `gstack-review-log` was called and `gstack-review-read` was run at least + once. If no plan file is in context (e.g. `/codex consult` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading. diff --git a/plan-devex-review/SKILL.md.tmpl b/plan-devex-review/SKILL.md.tmpl index 5b68c2ea5..88dd0038b 100644 --- a/plan-devex-review/SKILL.md.tmpl +++ b/plan-devex-review/SKILL.md.tmpl @@ -827,3 +827,5 @@ Outside voice| Recommended | Recommended | Skip * One sentence max per option. * After each pass, pause and wait for feedback before moving on. * Rate before and after each pass for scannability. + +{{EXIT_PLAN_MODE_GATE}} diff --git a/plan-eng-review/SKILL.md b/plan-eng-review/SKILL.md index 881455550..d47c39f5e 100644 --- a/plan-eng-review/SKILL.md +++ b/plan-eng-review/SKILL.md @@ -764,9 +764,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. @@ -1653,3 +1651,28 @@ Use AskUserQuestion with only the applicable options: ## Unresolved decisions If the user does not respond to an AskUserQuestion or interrupts to move on, note which decisions were left unresolved. At the end of the review, list these as "Unresolved decisions that may bite you later" — never silently default to an option. + +## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST `## ` heading in the file is `## GSTACK REVIEW REPORT`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured `## GSTACK REVIEW REPORT` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + `gstack-review-log` was called and `gstack-review-read` was run at least + once. If no plan file is in context (e.g. `/codex consult` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading. diff --git a/plan-eng-review/SKILL.md.tmpl b/plan-eng-review/SKILL.md.tmpl index a950c060d..8bdd3933e 100644 --- a/plan-eng-review/SKILL.md.tmpl +++ b/plan-eng-review/SKILL.md.tmpl @@ -338,3 +338,5 @@ Use AskUserQuestion with only the applicable options: ## Unresolved decisions If the user does not respond to an AskUserQuestion or interrupts to move on, note which decisions were left unresolved. At the end of the review, list these as "Unresolved decisions that may bite you later" — never silently default to an option. + +{{EXIT_PLAN_MODE_GATE}} diff --git a/plan-tune/SKILL.md b/plan-tune/SKILL.md index 471fbe517..c575ef4f4 100644 --- a/plan-tune/SKILL.md +++ b/plan-tune/SKILL.md @@ -753,9 +753,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /plan-tune — Question Tuning + Developer Profile (v1 observational) diff --git a/qa-only/SKILL.md b/qa-only/SKILL.md index 77dcc4d23..3e95cb032 100644 --- a/qa-only/SKILL.md +++ b/qa-only/SKILL.md @@ -759,9 +759,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /qa-only: Report-Only QA Testing diff --git a/qa/SKILL.md b/qa/SKILL.md index 0b56e53e2..aec716f95 100644 --- a/qa/SKILL.md +++ b/qa/SKILL.md @@ -765,9 +765,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/retro/SKILL.md b/retro/SKILL.md index 2d2684afe..92d58f7b8 100644 --- a/retro/SKILL.md +++ b/retro/SKILL.md @@ -759,9 +759,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/review/SKILL.md b/review/SKILL.md index 4d134d175..88378396a 100644 --- a/review/SKILL.md +++ b/review/SKILL.md @@ -762,9 +762,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/scrape/SKILL.md b/scrape/SKILL.md index b255abe08..7fb04d3f6 100644 --- a/scrape/SKILL.md +++ b/scrape/SKILL.md @@ -758,9 +758,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /scrape — pull data from a page diff --git a/scripts/resolvers/index.ts b/scripts/resolvers/index.ts index d96b729dc..40342f497 100644 --- a/scripts/resolvers/index.ts +++ b/scripts/resolvers/index.ts @@ -11,7 +11,7 @@ import { generateTestFailureTriage } from './preamble'; import { generateCommandReference, generateSnapshotFlags, generateBrowseSetup } from './browse'; import { generateDesignMethodology, generateDesignHardRules, generateDesignOutsideVoices, generateDesignReviewLite, generateDesignSketch, generateDesignSetup, generateDesignMockup, generateDesignShotgunLoop, generateTasteProfile, generateUXPrinciples } from './design'; import { generateTestBootstrap, generateTestCoverageAuditPlan, generateTestCoverageAuditShip, generateTestCoverageAuditReview } from './testing'; -import { generateReviewDashboard, generatePlanFileReviewReport, generateAntiShortcutClause, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec, generateScopeDrift, generateCrossReviewDedup } from './review'; +import { generateReviewDashboard, generatePlanFileReviewReport, generateExitPlanModeGate, generateAntiShortcutClause, generateSpecReviewLoop, generateBenefitsFrom, generateCodexSecondOpinion, generateAdversarialStep, generateCodexPlanReview, generatePlanCompletionAuditShip, generatePlanCompletionAuditReview, generatePlanVerificationExec, generateScopeDrift, generateCrossReviewDedup } from './review'; import { generateSlugEval, generateSlugSetup, generateBaseBranchDetect, generateDeployBootstrap, generateQAMethodology, generateCoAuthorTrailer, generateChangelogWorkflow } from './utility'; import { generateLearningsSearch, generateLearningsLog } from './learnings'; import { generateConfidenceCalibration } from './confidence'; @@ -39,6 +39,7 @@ export const RESOLVERS: Record = { DESIGN_REVIEW_LITE: generateDesignReviewLite, REVIEW_DASHBOARD: generateReviewDashboard, PLAN_FILE_REVIEW_REPORT: generatePlanFileReviewReport, + EXIT_PLAN_MODE_GATE: generateExitPlanModeGate, ANTI_SHORTCUT_CLAUSE: generateAntiShortcutClause, TEST_BOOTSTRAP: generateTestBootstrap, TEST_COVERAGE_AUDIT_PLAN: generateTestCoverageAuditPlan, diff --git a/scripts/resolvers/preamble/generate-completion-status.ts b/scripts/resolvers/preamble/generate-completion-status.ts index 21c0bd5e7..0c50da1c7 100644 --- a/scripts/resolvers/preamble/generate-completion-status.ts +++ b/scripts/resolvers/preamble/generate-completion-status.ts @@ -81,7 +81,5 @@ Replace \`SKILL_NAME\`, \`OUTCOME\`, and \`USED_BROWSE\` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks \`## GSTACK REVIEW REPORT\`, run \`~/.claude/skills/gstack/bin/gstack-review-read\` and append the standard runs/status/findings table. With \`NO_REVIEWS\` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run \`/autoplan\`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file).`; +Skills that run plan reviews (\`/plan-*-review\`, \`/codex review\`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with \`## GSTACK REVIEW REPORT\` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like \`/ship\`, \`/qa\`, \`/review\`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode.`; } diff --git a/scripts/resolvers/review.ts b/scripts/resolvers/review.ts index 263767d69..3b9e2999d 100644 --- a/scripts/resolvers/review.ts +++ b/scripts/resolvers/review.ts @@ -158,6 +158,33 @@ there — the user then sees a plan whose review report is not at the bottom and (correctly) rejects it.`; } +export function generateExitPlanModeGate(_ctx: TemplateContext): string { + return `## EXIT PLAN MODE GATE (BLOCKING) + +Before calling ExitPlanMode, run this self-check. If any item fails, do the +missing work — do NOT call ExitPlanMode: + +1. Read the plan file with the Read tool (after your most recent write to it). +2. Confirm the LAST \`## \` heading in the file is \`## GSTACK REVIEW REPORT\`. + In-body prose that mentions "outside voice", "codex findings", or similar + does NOT count — only the structured \`## GSTACK REVIEW REPORT\` section + satisfies this check. +3. Confirm the report contains: a Runs / Status / Findings table, a VERDICT + line, and absorbs CODEX / CROSS-MODEL / UNRESOLVED lines if applicable. +4. If a plan file is in context for this skill invocation: confirm + \`gstack-review-log\` was called and \`gstack-review-read\` was run at least + once. If no plan file is in context (e.g. \`/codex consult\` against a + diff with no plan), this check short-circuits — checks 1-3 already + short-circuit when no plan file exists. + +Failing this gate and calling ExitPlanMode anyway is a contract violation — +the user will see a plan whose review report is missing or stale, and will +(correctly) reject it. Self-deception failure mode to watch for: feeling +"done" after writing review prose into the plan body. The body prose is not +the report. The report is a separate, structured, table-bearing section that +must be the file's terminal heading.`; +} + export function generateAntiShortcutClause(_ctx: TemplateContext): string { return `**Anti-shortcut clause:** The plan file is the OUTPUT of the interactive review, not a substitute for it. Writing every finding into one plan write and calling ExitPlanMode without firing AskUserQuestion is the precise failure mode of the May 2026 transcript bug — the model explored, found issues, and dumped them into a deliverable rather than walking the user through them. If you have ANY non-trivial finding in any review section, the path from finding to ExitPlanMode goes THROUGH AskUserQuestion. Zero findings in every section is the only path to ExitPlanMode that bypasses AskUserQuestion. If you find yourself wanting to write a plan with findings before asking, stop and call AskUserQuestion now — that's the bug, recognize it.`; } diff --git a/setup-browser-cookies/SKILL.md b/setup-browser-cookies/SKILL.md index 4e46c0b25..8b80fd58b 100644 --- a/setup-browser-cookies/SKILL.md +++ b/setup-browser-cookies/SKILL.md @@ -471,9 +471,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # Setup Browser Cookies diff --git a/setup-deploy/SKILL.md b/setup-deploy/SKILL.md index 2731365c5..0e09cc491 100644 --- a/setup-deploy/SKILL.md +++ b/setup-deploy/SKILL.md @@ -743,9 +743,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /setup-deploy — Configure Deployment for gstack diff --git a/setup-gbrain/SKILL.md b/setup-gbrain/SKILL.md index c1abd775c..a31b7de7a 100644 --- a/setup-gbrain/SKILL.md +++ b/setup-gbrain/SKILL.md @@ -744,9 +744,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /setup-gbrain — Coding-Agent Onboarding for gbrain diff --git a/ship/SKILL.md b/ship/SKILL.md index 25119fb39..dcab2bdda 100644 --- a/ship/SKILL.md +++ b/ship/SKILL.md @@ -763,9 +763,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/skillify/SKILL.md b/skillify/SKILL.md index 503f8262b..afef0e3a1 100644 --- a/skillify/SKILL.md +++ b/skillify/SKILL.md @@ -759,9 +759,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /skillify — codify the last scrape into a permanent skill diff --git a/sync-gbrain/SKILL.md b/sync-gbrain/SKILL.md index 8dba77386..f7b9b5230 100644 --- a/sync-gbrain/SKILL.md +++ b/sync-gbrain/SKILL.md @@ -744,9 +744,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. # /sync-gbrain — Keep gbrain current and teach the agent to use it diff --git a/test/fixtures/golden/claude-ship-SKILL.md b/test/fixtures/golden/claude-ship-SKILL.md index 25119fb39..dcab2bdda 100644 --- a/test/fixtures/golden/claude-ship-SKILL.md +++ b/test/fixtures/golden/claude-ship-SKILL.md @@ -763,9 +763,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `~/.claude/skills/gstack/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 7770a8906..58bf20a0d 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -752,9 +752,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `$GSTACK_ROOT/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index baae7421d..e71f38883 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -754,9 +754,7 @@ Replace `SKILL_NAME`, `OUTCOME`, and `USED_BROWSE` before running. ## Plan Status Footer -In plan mode before ExitPlanMode: if the plan file lacks `## GSTACK REVIEW REPORT`, run `$GSTACK_ROOT/bin/gstack-review-read` and append the standard runs/status/findings table. With `NO_REVIEWS` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run `/autoplan`". If a richer report exists, skip. - -PLAN MODE EXCEPTION — always allowed (it's the plan file). +Skills that run plan reviews (`/plan-*-review`, `/codex review`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like `/ship`, `/qa`, `/review`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. Writing the plan file is the one edit allowed in plan mode. ## Step 0: Detect platform and base branch diff --git a/test/gen-skill-docs.test.ts b/test/gen-skill-docs.test.ts index 4bf8abeee..a270b3eb4 100644 --- a/test/gen-skill-docs.test.ts +++ b/test/gen-skill-docs.test.ts @@ -1090,14 +1090,16 @@ describe('Retro plan completion section', () => { // --- Plan status footer in preamble --- describe('Plan status footer in preamble', () => { - test('preamble contains plan status footer', () => { + test('preamble contains plan status footer as neutral forward reference to EXIT PLAN MODE GATE', () => { // Read any skill that uses PREAMBLE const content = fs.readFileSync(path.join(ROOT, 'office-hours', 'SKILL.md'), 'utf-8'); expect(content).toContain('Plan Status Footer'); expect(content).toContain('GSTACK REVIEW REPORT'); - expect(content).toContain('gstack-review-read'); expect(content).toContain('ExitPlanMode'); - expect(content).toContain('NO REVIEWS YET'); + expect(content).toContain('EXIT PLAN MODE GATE'); + // The preamble must NOT impose review-report rules on operational skills + // that have no review report. It's a forward reference, not enforcement. + expect(content).not.toContain('NO REVIEWS YET'); }); }); @@ -3095,3 +3097,30 @@ describe('LEARNINGS_SEARCH resolver: query parameter', () => { } }); }); + +describe('EXIT PLAN MODE GATE placement', () => { + // Fresh skill list — do NOT reuse REVIEW_SKILLS upstream (3 entries, missing plan-devex). + const planSkills = ['plan-eng-review', 'plan-ceo-review', 'plan-design-review', 'plan-devex-review']; + + // Strip fenced code blocks before matching headings — PLAN_FILE_REVIEW_REPORT + // already contains `## GSTACK REVIEW REPORT` inside a markdown example fence, + // and the gate text itself shows `## GSTACK REVIEW REPORT` inside a fence too. + const stripFences = (md: string) => md.replace(/```[\s\S]*?```/g, ''); + + test('gate is the terminal ## heading in every plan-* review SKILL.md', () => { + for (const skill of planSkills) { + const md = fs.readFileSync(path.join(ROOT, skill, 'SKILL.md'), 'utf-8'); + const stripped = stripFences(md); + const headings = [...stripped.matchAll(/^## .+$/gm)].map(m => m[0]); + const lastH2 = headings.at(-1); + expect(lastH2, `${skill}/SKILL.md last ## heading (fences stripped)`).toBe('## EXIT PLAN MODE GATE (BLOCKING)'); + expect(md, `${skill}/SKILL.md gate body`).toContain('Failing this gate and calling ExitPlanMode anyway is a contract violation'); + } + }); + + test('codex/SKILL.md contains gate (mid-file per D5; Step 2B/2C follow)', () => { + const codex = fs.readFileSync(path.join(ROOT, 'codex', 'SKILL.md'), 'utf-8'); + expect(codex).toContain('## EXIT PLAN MODE GATE (BLOCKING)'); + expect(codex).toContain('Failing this gate and calling ExitPlanMode anyway is a contract violation'); + }); +});