From 848973007c0d0942fb97096499f26f1486c1355e Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 28 Aug 2026 01:41:29 +0000 Subject: [PATCH] =?UTF-8?q?feat(autoplan):=20eng=20review=20always=20runs?= =?UTF-8?q?=20last=20=E2=80=94=20the=20gate=20reviews=20the=20final=20amen?= =?UTF-8?q?ded=20plan?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorder the pipeline to CEO -> Design (if UI scope) -> DX (if developer-facing scope) -> Eng. The old order (CEO -> Design -> Eng -> DX) let DX findings land AFTER the required gate signed off, so eng validated a stale plan. Accept-all semantics made explicit: every AskUserQuestion resolves to the recommended option; premises no longer pause the pipeline mid-run (clearly-wrong ones queue as User-Challenge items at the single Final Approval Gate). Eng's Codex voice now sees the DX consensus summary. New free static test pins the order; the chain E2E gains DX-between and Eng-terminal assertions. Co-Authored-By: Claude Fable 5 --- autoplan/SKILL.md | 88 +++++++++++++++------------ autoplan/SKILL.md.tmpl | 84 ++++++++++++++----------- autoplan/sections/ceo-phase.md | 13 ++-- autoplan/sections/ceo-phase.md.tmpl | 13 ++-- autoplan/sections/dx-phase.md | 8 +-- autoplan/sections/dx-phase.md.tmpl | 8 +-- autoplan/sections/eng-phase.md | 5 +- autoplan/sections/eng-phase.md.tmpl | 5 +- autoplan/sections/manifest.json | 6 +- test/autoplan-phase-order.test.ts | 70 +++++++++++++++++++++ test/skill-e2e-autoplan-chain.test.ts | 20 ++++-- 11 files changed, 216 insertions(+), 104 deletions(-) create mode 100644 test/autoplan-phase-order.test.ts diff --git a/autoplan/SKILL.md b/autoplan/SKILL.md index 0cc6c8dca..b84089926 100644 --- a/autoplan/SKILL.md +++ b/autoplan/SKILL.md @@ -544,7 +544,7 @@ sections. Read a section in full before doing its step; do not work from memory. | starting Phase 1 (CEO review — always runs, after the Phase 0.5 preflight) | `sections/ceo-phase.md` | | starting Phase 2 (design review — ONLY if UI scope was detected in Phase 0; skip the read entirely otherwise) | `sections/design-phase.md` | | starting Phase 3 (eng review — always runs, after the Pre-Phase 3 checklist) | `sections/eng-phase.md` | -| starting Phase 3.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise) | `sections/dx-phase.md` | +| starting Phase 2.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise) | `sections/dx-phase.md` | | presenting the Final Approval Gate (Phase 4) — the aggregator computes $AGGREGATED_TASKS that the gate message substitutes | `sections/tasks-aggregator.md` | --- @@ -605,9 +605,11 @@ preference." The user still decides, but the framing is appropriately urgent. ## Sequential Execution — MANDATORY -Phases MUST execute in strict order: CEO → Design → Eng → DX. -Each phase MUST complete fully before the next begins. -NEVER run phases in parallel — each builds on the previous. +Phases MUST execute in strict order: CEO → Design (if UI scope) → DX (if +developer-facing scope) → Eng. Eng runs LAST, always: it is the required +shipping gate, so it must review the FINAL amended plan — every other phase's +amendments land before it. Each phase MUST complete fully before the next +begins. NEVER run phases in parallel — each builds on the previous. Between each phase, emit a phase-transition summary and verify that all required outputs from the prior phase are written before starting the next. @@ -619,13 +621,20 @@ outputs from the prior phase are written before starting the next. Auto-decide replaces the USER'S judgment with the 6 principles. It does NOT replace the ANALYSIS. Every section in the loaded skill files must still be executed at the same depth as the interactive version. The only thing that changes is who answers the -AskUserQuestion: you do, using the 6 principles, instead of the user. +AskUserQuestion: you do, instead of the user. -**Two exceptions — never auto-decided:** -1. Premises (Phase 1) — require human judgment about what problem to solve. -2. User Challenges — when both models agree the user's stated direction should change - (merge, split, add, remove features/workflows). The user always has context models - lack. See Decision Classification above. +**Default resolution: the recommended option.** Every AskUserQuestion in the loaded +skills resolves to its `(recommended)` option; mode selections take the skill's +context-dependent default. The 6 principles guide cases with no recommendation and +break ties; when a principle argues AGAINST the recommended option, that is a Taste +decision — take the recommendation and surface the disagreement at the final gate. + +**One exception class — never auto-decided:** User Challenges — when both models +agree the user's stated direction should change (merge, split, add, remove +features/workflows; reinterpret a settled decision), or a premise looks clearly +wrong. These queue and surface at the Final Approval Gate — never as mid-run +stops. The user is interrupted exactly once, at the gate. The user always has +context models lack. See Decision Classification above. **You MUST still:** - READ the actual code, diffs, and files each section references @@ -775,7 +784,7 @@ else fi ``` -If `_CODEX_AVAILABLE=false`, all Phase 1-3.5 Codex voices below degrade to +If `_CODEX_AVAILABLE=false`, all Phase 1-3 Codex voices below degrade to `[codex-unavailable]` in the degradation matrix. /autoplan completes with Claude subagent only — saves token spend on Codex prompts we can't use. @@ -792,7 +801,7 @@ Claude subagent only — saves token spend on Codex prompts we can't use. - [ ] CEO completion summary written to plan file - [ ] CEO dual voices ran (Codex + Claude subagent, or noted unavailable) - [ ] CEO consensus table produced -- [ ] Premise gate passed (user confirmed) +- [ ] Premises assessed (clearly-wrong ones queued as Final Gate items — no mid-run stop) - [ ] Phase-transition summary emitted ## Phase 2: Design Review (conditional — skip if no UI scope) @@ -805,30 +814,33 @@ entirely — do NOT read its section. Log: "Phase 2 skipped — no UI scope dete --- +## Phase 2.5: DX Review (conditional — skip if no developer-facing scope) + +**Skip condition:** If DX scope was NOT detected in Phase 0, skip this phase +entirely — do NOT read its section. Log: "Phase 2.5 skipped — no developer-facing scope detected." + +> **STOP.** Before starting Phase 2.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise), Read `~/.claude/skills/gstack/autoplan/sections/dx-phase.md` and execute it +> in full. Do not work from memory — that section is the source of truth for this step. + +--- + **Pre-Phase 3 checklist (verify before starting):** - [ ] All Phase 1 items above confirmed - [ ] Design completion summary written (or "skipped, no UI scope") - [ ] Design dual voices ran (if Phase 2 ran) - [ ] Design consensus table produced (if Phase 2 ran) +- [ ] DX completion summary written (or "skipped, no developer-facing scope") +- [ ] DX dual voices ran (if Phase 2.5 ran) +- [ ] DX consensus table produced (if Phase 2.5 ran) - [ ] Phase-transition summary emitted -## Phase 3: Eng Review + Dual Voices +## Phase 3: Eng Review + Dual Voices (always runs, always LAST — the required gate reviews the final amended plan) > **STOP.** Before starting Phase 3 (eng review — always runs, after the Pre-Phase 3 checklist), Read `~/.claude/skills/gstack/autoplan/sections/eng-phase.md` and execute it > in full. Do not work from memory — that section is the source of truth for this step. --- -## Phase 3.5: DX Review (conditional — skip if no developer-facing scope) - -**Skip condition:** If DX scope was NOT detected in Phase 0, skip this phase -entirely — do NOT read its section. Log: "Phase 3.5 skipped — no developer-facing scope detected." - -> **STOP.** Before starting Phase 3.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise), Read `~/.claude/skills/gstack/autoplan/sections/dx-phase.md` and execute it -> in full. Do not work from memory — that section is the source of truth for this step. - ---- - ## Decision Audit Trail After each auto-decision, append a row to the plan file using Edit: @@ -869,7 +881,16 @@ produced. Check the plan file and conversation for each item. - [ ] Dual voices ran (or noted unavailable/skipped with phase) - [ ] Design litmus scorecard produced -**Phase 3 (Eng) outputs:** +**Phase 2.5 (DX) outputs — only if DX scope detected:** +- [ ] All 8 DX dimensions evaluated with scores +- [ ] Developer journey map produced +- [ ] Developer empathy narrative written +- [ ] TTHW assessment with target +- [ ] DX Implementation Checklist produced +- [ ] Dual voices ran (or noted unavailable/skipped with phase) +- [ ] DX consensus table produced + +**Phase 3 (Eng — final phase) outputs:** - [ ] Scope challenge with actual code analysis (not just "scope is fine") - [ ] Architecture ASCII diagram produced - [ ] Test diagram mapping codepaths to test coverage @@ -881,15 +902,6 @@ produced. Check the plan file and conversation for each item. - [ ] Dual voices ran (Codex + Claude subagent, or noted unavailable) - [ ] Eng consensus table produced -**Phase 3.5 (DX) outputs — only if DX scope detected:** -- [ ] All 8 DX dimensions evaluated with scores -- [ ] Developer journey map produced -- [ ] Developer empathy narrative written -- [ ] TTHW assessment with target -- [ ] DX Implementation Checklist produced -- [ ] Dual voices ran (or noted unavailable/skipped with phase) -- [ ] DX consensus table produced - **Cross-phase:** - [ ] Cross-phase themes section written @@ -981,7 +993,7 @@ AskUserQuestion options: - A: mark APPROVED, write review logs, suggest /ship - B: ask which overrides, apply, re-present gate - C: answer freeform, re-present gate -- D: make changes, re-run affected phases (scope→1B, design→2, test plan→3, arch→3). Max 3 cycles. +- D: make changes, re-run affected phases (scope→1B, design→2, dx→2.5, test plan→3, arch→3; a re-run of any earlier phase re-runs Eng after it — the gate always reviews the final plan). Max 3 cycles. - E: start over --- @@ -1006,7 +1018,7 @@ If Phase 2 ran (UI scope): ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"plan-design-review","timestamp":"'"$TIMESTAMP"'","status":"STATUS","unresolved":N,"via":"autoplan","commit":"'"$COMMIT"'"}' ``` -If Phase 3.5 ran (DX scope): +If Phase 2.5 ran (DX scope): ```bash ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"plan-devex-review","timestamp":"'"$TIMESTAMP"'","status":"STATUS","initial_score":N,"overall_score":N,"product_type":"TYPE","tthw_current":"TTHW","tthw_target":"TARGET","unresolved":N,"via":"autoplan","commit":"'"$COMMIT"'"}' ``` @@ -1023,7 +1035,7 @@ If Phase 2 ran (UI scope), also log: ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"autoplan-voices","timestamp":"'"$TIMESTAMP"'","status":"STATUS","source":"SOURCE","phase":"design","via":"autoplan","consensus_confirmed":N,"consensus_disagree":N,"commit":"'"$COMMIT"'"}' ``` -If Phase 3.5 ran (DX scope), also log: +If Phase 2.5 ran (DX scope), also log: ```bash ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"autoplan-voices","timestamp":"'"$TIMESTAMP"'","status":"STATUS","source":"SOURCE","phase":"dx","via":"autoplan","consensus_confirmed":N,"consensus_disagree":N,"commit":"'"$COMMIT"'"}' ``` @@ -1038,8 +1050,8 @@ Suggest next step: `/ship` when ready to create the PR. ## Important Rules - **Never abort.** The user chose /autoplan. Respect that choice. Surface all taste decisions, never redirect to interactive review. -- **Two gates.** The non-auto-decided AskUserQuestions are: (1) premise confirmation in Phase 1, and (2) User Challenges — when both models agree the user's stated direction should change. Everything else is auto-decided using the 6 principles. +- **One gate.** The only non-auto-decided AskUserQuestions surface at the Final Approval Gate: User Challenges — including clearly-wrong premises queued from Phase 1. Everything else resolves to the recommended option (the 6 principles break ties), so the pipeline never stops mid-run. - **Log every decision.** No silent auto-decisions. Every choice gets a row in the audit trail. - **Full depth means full depth.** Do not compress or skip sections from the loaded skill files (except the skip list in Phase 0). "Full depth" means: read the code the section asks you to read, produce the outputs the section requires, identify every issue, and decide each one. A one-sentence summary of a section is not "full depth" — it is a skip. If you catch yourself writing fewer than 3 sentences for any review section, you are likely compressing. - **Artifacts are deliverables.** Test plan artifact, failure modes registry, error/rescue table, ASCII diagrams — these must exist on disk or in the plan file when the review completes. If they don't exist, the review is incomplete. -- **Sequential order.** CEO → Design → Eng → DX. Each phase builds on the last. +- **Sequential order.** CEO → Design (if UI scope) → DX (if developer-facing scope) → Eng, always last. Each phase builds on the last; the required gate reviews the final amended plan. diff --git a/autoplan/SKILL.md.tmpl b/autoplan/SKILL.md.tmpl index fdc65fda9..276297169 100644 --- a/autoplan/SKILL.md.tmpl +++ b/autoplan/SKILL.md.tmpl @@ -108,9 +108,11 @@ preference." The user still decides, but the framing is appropriately urgent. ## Sequential Execution — MANDATORY -Phases MUST execute in strict order: CEO → Design → Eng → DX. -Each phase MUST complete fully before the next begins. -NEVER run phases in parallel — each builds on the previous. +Phases MUST execute in strict order: CEO → Design (if UI scope) → DX (if +developer-facing scope) → Eng. Eng runs LAST, always: it is the required +shipping gate, so it must review the FINAL amended plan — every other phase's +amendments land before it. Each phase MUST complete fully before the next +begins. NEVER run phases in parallel — each builds on the previous. Between each phase, emit a phase-transition summary and verify that all required outputs from the prior phase are written before starting the next. @@ -122,13 +124,20 @@ outputs from the prior phase are written before starting the next. Auto-decide replaces the USER'S judgment with the 6 principles. It does NOT replace the ANALYSIS. Every section in the loaded skill files must still be executed at the same depth as the interactive version. The only thing that changes is who answers the -AskUserQuestion: you do, using the 6 principles, instead of the user. +AskUserQuestion: you do, instead of the user. -**Two exceptions — never auto-decided:** -1. Premises (Phase 1) — require human judgment about what problem to solve. -2. User Challenges — when both models agree the user's stated direction should change - (merge, split, add, remove features/workflows). The user always has context models - lack. See Decision Classification above. +**Default resolution: the recommended option.** Every AskUserQuestion in the loaded +skills resolves to its `(recommended)` option; mode selections take the skill's +context-dependent default. The 6 principles guide cases with no recommendation and +break ties; when a principle argues AGAINST the recommended option, that is a Taste +decision — take the recommendation and surface the disagreement at the final gate. + +**One exception class — never auto-decided:** User Challenges — when both models +agree the user's stated direction should change (merge, split, add, remove +features/workflows; reinterpret a settled decision), or a premise looks clearly +wrong. These queue and surface at the Final Approval Gate — never as mid-run +stops. The user is interrupted exactly once, at the gate. The user always has +context models lack. See Decision Classification above. **You MUST still:** - READ the actual code, diffs, and files each section references @@ -278,7 +287,7 @@ else fi ``` -If `_CODEX_AVAILABLE=false`, all Phase 1-3.5 Codex voices below degrade to +If `_CODEX_AVAILABLE=false`, all Phase 1-3 Codex voices below degrade to `[codex-unavailable]` in the degradation matrix. /autoplan completes with Claude subagent only — saves token spend on Codex prompts we can't use. @@ -294,7 +303,7 @@ Claude subagent only — saves token spend on Codex prompts we can't use. - [ ] CEO completion summary written to plan file - [ ] CEO dual voices ran (Codex + Claude subagent, or noted unavailable) - [ ] CEO consensus table produced -- [ ] Premise gate passed (user confirmed) +- [ ] Premises assessed (clearly-wrong ones queued as Final Gate items — no mid-run stop) - [ ] Phase-transition summary emitted ## Phase 2: Design Review (conditional — skip if no UI scope) @@ -306,28 +315,31 @@ entirely — do NOT read its section. Log: "Phase 2 skipped — no UI scope dete --- +## Phase 2.5: DX Review (conditional — skip if no developer-facing scope) + +**Skip condition:** If DX scope was NOT detected in Phase 0, skip this phase +entirely — do NOT read its section. Log: "Phase 2.5 skipped — no developer-facing scope detected." + +{{SECTION:dx-phase}} + +--- + **Pre-Phase 3 checklist (verify before starting):** - [ ] All Phase 1 items above confirmed - [ ] Design completion summary written (or "skipped, no UI scope") - [ ] Design dual voices ran (if Phase 2 ran) - [ ] Design consensus table produced (if Phase 2 ran) +- [ ] DX completion summary written (or "skipped, no developer-facing scope") +- [ ] DX dual voices ran (if Phase 2.5 ran) +- [ ] DX consensus table produced (if Phase 2.5 ran) - [ ] Phase-transition summary emitted -## Phase 3: Eng Review + Dual Voices +## Phase 3: Eng Review + Dual Voices (always runs, always LAST — the required gate reviews the final amended plan) {{SECTION:eng-phase}} --- -## Phase 3.5: DX Review (conditional — skip if no developer-facing scope) - -**Skip condition:** If DX scope was NOT detected in Phase 0, skip this phase -entirely — do NOT read its section. Log: "Phase 3.5 skipped — no developer-facing scope detected." - -{{SECTION:dx-phase}} - ---- - ## Decision Audit Trail After each auto-decision, append a row to the plan file using Edit: @@ -368,7 +380,16 @@ produced. Check the plan file and conversation for each item. - [ ] Dual voices ran (or noted unavailable/skipped with phase) - [ ] Design litmus scorecard produced -**Phase 3 (Eng) outputs:** +**Phase 2.5 (DX) outputs — only if DX scope detected:** +- [ ] All 8 DX dimensions evaluated with scores +- [ ] Developer journey map produced +- [ ] Developer empathy narrative written +- [ ] TTHW assessment with target +- [ ] DX Implementation Checklist produced +- [ ] Dual voices ran (or noted unavailable/skipped with phase) +- [ ] DX consensus table produced + +**Phase 3 (Eng — final phase) outputs:** - [ ] Scope challenge with actual code analysis (not just "scope is fine") - [ ] Architecture ASCII diagram produced - [ ] Test diagram mapping codepaths to test coverage @@ -380,15 +401,6 @@ produced. Check the plan file and conversation for each item. - [ ] Dual voices ran (Codex + Claude subagent, or noted unavailable) - [ ] Eng consensus table produced -**Phase 3.5 (DX) outputs — only if DX scope detected:** -- [ ] All 8 DX dimensions evaluated with scores -- [ ] Developer journey map produced -- [ ] Developer empathy narrative written -- [ ] TTHW assessment with target -- [ ] DX Implementation Checklist produced -- [ ] Dual voices ran (or noted unavailable/skipped with phase) -- [ ] DX consensus table produced - **Cross-phase:** - [ ] Cross-phase themes section written @@ -479,7 +491,7 @@ AskUserQuestion options: - A: mark APPROVED, write review logs, suggest /ship - B: ask which overrides, apply, re-present gate - C: answer freeform, re-present gate -- D: make changes, re-run affected phases (scope→1B, design→2, test plan→3, arch→3). Max 3 cycles. +- D: make changes, re-run affected phases (scope→1B, design→2, dx→2.5, test plan→3, arch→3; a re-run of any earlier phase re-runs Eng after it — the gate always reviews the final plan). Max 3 cycles. - E: start over --- @@ -504,7 +516,7 @@ If Phase 2 ran (UI scope): ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"plan-design-review","timestamp":"'"$TIMESTAMP"'","status":"STATUS","unresolved":N,"via":"autoplan","commit":"'"$COMMIT"'"}' ``` -If Phase 3.5 ran (DX scope): +If Phase 2.5 ran (DX scope): ```bash ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"plan-devex-review","timestamp":"'"$TIMESTAMP"'","status":"STATUS","initial_score":N,"overall_score":N,"product_type":"TYPE","tthw_current":"TTHW","tthw_target":"TARGET","unresolved":N,"via":"autoplan","commit":"'"$COMMIT"'"}' ``` @@ -521,7 +533,7 @@ If Phase 2 ran (UI scope), also log: ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"autoplan-voices","timestamp":"'"$TIMESTAMP"'","status":"STATUS","source":"SOURCE","phase":"design","via":"autoplan","consensus_confirmed":N,"consensus_disagree":N,"commit":"'"$COMMIT"'"}' ``` -If Phase 3.5 ran (DX scope), also log: +If Phase 2.5 ran (DX scope), also log: ```bash ~/.claude/skills/gstack/bin/gstack-review-log '{"skill":"autoplan-voices","timestamp":"'"$TIMESTAMP"'","status":"STATUS","source":"SOURCE","phase":"dx","via":"autoplan","consensus_confirmed":N,"consensus_disagree":N,"commit":"'"$COMMIT"'"}' ``` @@ -536,8 +548,8 @@ Suggest next step: `/ship` when ready to create the PR. ## Important Rules - **Never abort.** The user chose /autoplan. Respect that choice. Surface all taste decisions, never redirect to interactive review. -- **Two gates.** The non-auto-decided AskUserQuestions are: (1) premise confirmation in Phase 1, and (2) User Challenges — when both models agree the user's stated direction should change. Everything else is auto-decided using the 6 principles. +- **One gate.** The only non-auto-decided AskUserQuestions surface at the Final Approval Gate: User Challenges — including clearly-wrong premises queued from Phase 1. Everything else resolves to the recommended option (the 6 principles break ties), so the pipeline never stops mid-run. - **Log every decision.** No silent auto-decisions. Every choice gets a row in the audit trail. - **Full depth means full depth.** Do not compress or skip sections from the loaded skill files (except the skip list in Phase 0). "Full depth" means: read the code the section asks you to read, produce the outputs the section requires, identify every issue, and decide each one. A one-sentence summary of a section is not "full depth" — it is a skip. If you catch yourself writing fewer than 3 sentences for any review section, you are likely compressing. - **Artifacts are deliverables.** Test plan artifact, failure modes registry, error/rescue table, ASCII diagrams — these must exist on disk or in the plan file when the review completes. If they don't exist, the review is incomplete. -- **Sequential order.** CEO → Design → Eng → DX. Each phase builds on the last. +- **Sequential order.** CEO → Design (if UI scope) → DX (if developer-facing scope) → Eng, always last. Each phase builds on the last; the required gate reviews the final amended plan. diff --git a/autoplan/sections/ceo-phase.md b/autoplan/sections/ceo-phase.md index ff9e524b0..876c03fb9 100644 --- a/autoplan/sections/ceo-phase.md +++ b/autoplan/sections/ceo-phase.md @@ -5,9 +5,11 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. **Override rules:** - Mode selection: SELECTIVE EXPANSION -- Premises: accept reasonable ones (P6), challenge only clearly wrong ones -- **GATE: Present premises to user for confirmation** — this is the ONE AskUserQuestion - that is NOT auto-decided. Premises require human judgment. +- Premises: accept reasonable ones (P6). Clearly-wrong or challenged premises are + NOT a mid-run stop — queue each as a User-Challenge-shaped item for the Final + Approval Gate (Phase 4): what the plan assumes, why it looks wrong, and the cost + of proceeding anyway. Premises still require human judgment — the human exercises + it at the gate, exactly once, not mid-pipeline. - Alternatives: pick highest completeness (P1). If tied, pick simplest (P5). If top 2 are close → mark TASTE DECISION. - Scope expansion: in blast radius + <1d CC → approve (P2). Outside → defer to TODOS.md (P3). @@ -112,5 +114,6 @@ Sections 1-10 — for EACH section, run the evaluation criteria from the loaded > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. > Passing to Phase 2. -Do NOT begin Phase 2 until all Phase 1 outputs are written to the plan file -and the premise gate has been passed. +Do NOT begin Phase 2 until all Phase 1 outputs are written to the plan file, +including the premise assessment (queued premise challenges travel to the +Final Gate — they never pause the pipeline here). diff --git a/autoplan/sections/ceo-phase.md.tmpl b/autoplan/sections/ceo-phase.md.tmpl index d906682f1..52c8f1aa6 100644 --- a/autoplan/sections/ceo-phase.md.tmpl +++ b/autoplan/sections/ceo-phase.md.tmpl @@ -3,9 +3,11 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. **Override rules:** - Mode selection: SELECTIVE EXPANSION -- Premises: accept reasonable ones (P6), challenge only clearly wrong ones -- **GATE: Present premises to user for confirmation** — this is the ONE AskUserQuestion - that is NOT auto-decided. Premises require human judgment. +- Premises: accept reasonable ones (P6). Clearly-wrong or challenged premises are + NOT a mid-run stop — queue each as a User-Challenge-shaped item for the Final + Approval Gate (Phase 4): what the plan assumes, why it looks wrong, and the cost + of proceeding anyway. Premises still require human judgment — the human exercises + it at the gate, exactly once, not mid-pipeline. - Alternatives: pick highest completeness (P1). If tied, pick simplest (P5). If top 2 are close → mark TASTE DECISION. - Scope expansion: in blast radius + <1d CC → approve (P2). Outside → defer to TODOS.md (P3). @@ -110,5 +112,6 @@ Sections 1-10 — for EACH section, run the evaluation criteria from the loaded > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. > Passing to Phase 2. -Do NOT begin Phase 2 until all Phase 1 outputs are written to the plan file -and the premise gate has been passed. +Do NOT begin Phase 2 until all Phase 1 outputs are written to the plan file, +including the premise assessment (queued premise challenges travel to the +Final Gate — they never pause the pipeline here). diff --git a/autoplan/sections/dx-phase.md b/autoplan/sections/dx-phase.md index 79f5109af..c2d755c57 100644 --- a/autoplan/sections/dx-phase.md +++ b/autoplan/sections/dx-phase.md @@ -87,15 +87,15 @@ Missing voice = N/A (not CONFIRMED). Single critical finding from one voice = fl 4. DX Scorecard: Produce the full scorecard with all 8 dimensions scored. -**Mandatory outputs from Phase 3.5:** +**Mandatory outputs from Phase 2.5:** - Developer journey map (9-stage table) - Developer empathy narrative (first-person perspective) - DX Scorecard with all 8 dimension scores - DX Implementation Checklist - TTHW assessment with target -**PHASE 3.5 COMPLETE.** Emit phase-transition summary: -> **Phase 3.5 complete.** DX overall: [N]/10. TTHW: [N] min → [target] min. +**PHASE 2.5 COMPLETE.** Emit phase-transition summary: +> **Phase 2.5 complete.** DX overall: [N]/10. TTHW: [N] min → [target] min. > Codex: [N concerns]. Claude subagent: [N issues]. > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. -> Passing to Phase 4 (Final Gate). +> Passing to Phase 3 (Eng Review — the required gate reviews the final amended plan). diff --git a/autoplan/sections/dx-phase.md.tmpl b/autoplan/sections/dx-phase.md.tmpl index 8fde659c0..e9255c7b8 100644 --- a/autoplan/sections/dx-phase.md.tmpl +++ b/autoplan/sections/dx-phase.md.tmpl @@ -85,15 +85,15 @@ Missing voice = N/A (not CONFIRMED). Single critical finding from one voice = fl 4. DX Scorecard: Produce the full scorecard with all 8 dimensions scored. -**Mandatory outputs from Phase 3.5:** +**Mandatory outputs from Phase 2.5:** - Developer journey map (9-stage table) - Developer empathy narrative (first-person perspective) - DX Scorecard with all 8 dimension scores - DX Implementation Checklist - TTHW assessment with target -**PHASE 3.5 COMPLETE.** Emit phase-transition summary: -> **Phase 3.5 complete.** DX overall: [N]/10. TTHW: [N] min → [target] min. +**PHASE 2.5 COMPLETE.** Emit phase-transition summary: +> **Phase 2.5 complete.** DX overall: [N]/10. TTHW: [N] min → [target] min. > Codex: [N concerns]. Claude subagent: [N issues]. > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. -> Passing to Phase 4 (Final Gate). +> Passing to Phase 3 (Eng Review — the required gate reviews the final amended plan). diff --git a/autoplan/sections/eng-phase.md b/autoplan/sections/eng-phase.md index bb9954cfe..bd60553a2 100644 --- a/autoplan/sections/eng-phase.md +++ b/autoplan/sections/eng-phase.md @@ -18,6 +18,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. Also consider these findings from prior review phases: CEO: Design: + DX: File: " -C "$_REPO_ROOT" -s read-only -c 'web_search="cached"' < /dev/null _CODEX_EXIT=$? @@ -45,7 +46,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. - Architecture choices: explicit over clever (P5). If codex disagrees with valid reason → TASTE DECISION. Scope changes both models agree on → USER CHALLENGE. - Evals: always include all relevant suites (P1) - Test plan: generate artifact at `~/.gstack/projects/$SLUG/{user}-{branch}-test-plan-{datetime}.md` -- TODOS.md: collect all deferred scope expansions from Phase 1, auto-write +- TODOS.md: collect all deferred scope expansions from every prior phase (Eng runs last), auto-write **Required execution checklist (Eng):** @@ -105,4 +106,4 @@ Missing voice = N/A (not CONFIRMED). Single critical finding from one voice = fl **PHASE 3 COMPLETE.** Emit phase-transition summary: > **Phase 3 complete.** Codex: [N concerns]. Claude subagent: [N issues]. > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. -> Passing to Phase 3.5 (DX Review) or Phase 4 (Final Gate). +> Passing to Phase 4 (Final Gate). diff --git a/autoplan/sections/eng-phase.md.tmpl b/autoplan/sections/eng-phase.md.tmpl index 59a04d69b..a7cd8e5da 100644 --- a/autoplan/sections/eng-phase.md.tmpl +++ b/autoplan/sections/eng-phase.md.tmpl @@ -16,6 +16,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. Also consider these findings from prior review phases: CEO: Design: + DX: File: " -C "$_REPO_ROOT" -s read-only {{CODEX_WEB_SEARCH_FLAG}} < /dev/null _CODEX_EXIT=$? @@ -43,7 +44,7 @@ Override: every AskUserQuestion → auto-decide using the 6 principles. - Architecture choices: explicit over clever (P5). If codex disagrees with valid reason → TASTE DECISION. Scope changes both models agree on → USER CHALLENGE. - Evals: always include all relevant suites (P1) - Test plan: generate artifact at `~/.gstack/projects/$SLUG/{user}-{branch}-test-plan-{datetime}.md` -- TODOS.md: collect all deferred scope expansions from Phase 1, auto-write +- TODOS.md: collect all deferred scope expansions from every prior phase (Eng runs last), auto-write **Required execution checklist (Eng):** @@ -103,4 +104,4 @@ Missing voice = N/A (not CONFIRMED). Single critical finding from one voice = fl **PHASE 3 COMPLETE.** Emit phase-transition summary: > **Phase 3 complete.** Codex: [N concerns]. Claude subagent: [N issues]. > Consensus: [X/6 confirmed, Y disagreements → surfaced at gate]. -> Passing to Phase 3.5 (DX Review) or Phase 4 (Final Gate). +> Passing to Phase 4 (Final Gate). diff --git a/autoplan/sections/manifest.json b/autoplan/sections/manifest.json index c51c27698..85940b4c2 100644 --- a/autoplan/sections/manifest.json +++ b/autoplan/sections/manifest.json @@ -2,7 +2,7 @@ "$schema": "https://gstack.dev/schemas/section-manifest.json", "skill": "autoplan", "version": 1, - "note": "PASSIVE registry (v2 plan T9 / CM2). Fields are IDs, file paths, human titles, and human-readable trigger text ONLY. The skeleton's phase sequencing (Sequential Execution + the Phase 0 UI/DX scope detection) is the ONLY place that decides WHEN to read a section — Phase 2 and Phase 3.5 are conditional and their sections must NOT be read when their scope is absent; required-reads live in the E2E fixtures. No machine predicate here — see docs/designs/v2_PLAN.md:663.", + "note": "PASSIVE registry (v2 plan T9 / CM2). Fields are IDs, file paths, human titles, and human-readable trigger text ONLY. The skeleton's phase sequencing (Sequential Execution + the Phase 0 UI/DX scope detection) is the ONLY place that decides WHEN to read a section — Phase 2 and Phase 2.5 are conditional and their sections must NOT be read when their scope is absent; required-reads live in the E2E fixtures. No machine predicate here — see docs/designs/v2_PLAN.md:663.", "sections": [ { "id": "ceo-phase", @@ -25,8 +25,8 @@ { "id": "dx-phase", "file": "dx-phase.md", - "title": "Phase 3.5: DX review — override rules, dual voices, 8-dimension scorecard", - "trigger": "starting Phase 3.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise)" + "title": "Phase 2.5: DX review — override rules, dual voices, 8-dimension scorecard", + "trigger": "starting Phase 2.5 (DX review — ONLY if developer-facing scope was detected in Phase 0; skip the read entirely otherwise)" }, { "id": "tasks-aggregator", diff --git a/test/autoplan-phase-order.test.ts b/test/autoplan-phase-order.test.ts new file mode 100644 index 000000000..c7c3b2eea --- /dev/null +++ b/test/autoplan-phase-order.test.ts @@ -0,0 +1,70 @@ +/** + * /autoplan phase-order pin (free, static). + * + * The pipeline order is a deliberate design decision (2026-08-25, user-directed): + * CEO → Design (if UI scope) → DX (if developer-facing scope) → Eng, ALWAYS LAST. + * Eng is the required shipping gate — it must review the FINAL amended plan, so + * every other phase's amendments land before it. The original order buried Eng + * mid-pipeline (CEO → Design → Eng → DX), which let DX findings land AFTER the + * gate had signed off — the gate validated a stale plan. + * + * These assertions pin the template so a refactor can't silently restore the + * old order. The paid chain E2E (skill-e2e-autoplan-chain.test.ts) verifies the + * runtime behavior; this pins the source of truth for free on every PR. + */ +import { describe, test, expect } from 'bun:test'; +import * as fs from 'fs'; +import * as path from 'path'; + +const ROOT = path.join(import.meta.dir, '..'); +const read = (p: string) => fs.readFileSync(path.join(ROOT, p), 'utf-8'); + +describe('autoplan phase order (Eng always last)', () => { + const tmpl = read('autoplan/SKILL.md.tmpl'); + + test('Sequential Execution block names Eng as the terminal phase', () => { + const block = tmpl.split('## Sequential Execution')[1]?.split('---')[0] ?? ''; + expect(block).toContain('Eng runs LAST, always'); + expect(block).toMatch(/CEO → Design.*→ DX.*→ Eng/s); + // The old order must not resurface anywhere in the template. + expect(tmpl).not.toContain('CEO → Design → Eng → DX'); + }); + + test('phase headings appear in the new order: 1, 2, 2.5, 3', () => { + const idx = (h: string) => { + const i = tmpl.indexOf(h); + expect(i).toBeGreaterThan(-1); + return i; + }; + const p1 = idx('## Phase 1: CEO Review'); + const p2 = idx('## Phase 2: Design Review'); + const p25 = idx('## Phase 2.5: DX Review'); + const p3 = idx('## Phase 3: Eng Review'); + expect(p1).toBeLessThan(p2); + expect(p2).toBeLessThan(p25); + expect(p25).toBeLessThan(p3); + // No stale Phase 3.5 heading or transition marker survives. + expect(tmpl).not.toContain('Phase 3.5'); + }); + + test('phase sections hand off in the new order', () => { + expect(read('autoplan/sections/dx-phase.md.tmpl')).toContain( + 'Passing to Phase 3 (Eng Review', + ); + expect(read('autoplan/sections/eng-phase.md.tmpl')).toContain( + 'Passing to Phase 4 (Final Gate)', + ); + // Eng's Codex voice sees every prior phase's consensus, DX included. + expect(read('autoplan/sections/eng-phase.md.tmpl')).toContain( + 'DX: { + expect(tmpl).toContain('One exception class — never auto-decided'); + expect(tmpl).not.toContain('Premise gate passed (user confirmed)'); + const ceo = read('autoplan/sections/ceo-phase.md.tmpl'); + expect(ceo).not.toContain('GATE: Present premises to user for confirmation'); + expect(ceo).toContain('Final'); + }); +}); diff --git a/test/skill-e2e-autoplan-chain.test.ts b/test/skill-e2e-autoplan-chain.test.ts index 7f6fbea6d..96f09febe 100644 --- a/test/skill-e2e-autoplan-chain.test.ts +++ b/test/skill-e2e-autoplan-chain.test.ts @@ -6,8 +6,9 @@ * * "**Phase 1 complete." (CEO) → * "**Phase 2 complete." (Design — only if UI scope detected) → - * "**Phase 3 complete." (Eng) → - * "**Phase 3.5 complete." (DX — optional, skipped if no DX scope) + * "**Phase 2.5 complete." (DX — optional, skipped if no DX scope) → + * "**Phase 3 complete." (Eng — always runs, always LAST: the required + * gate reviews the final amended plan) * * Why this exists: each individual phase has its own plan-mode smoke * test. Nothing verifies the SEQUENCING — that phases don't run in @@ -88,7 +89,7 @@ describeE2E('/autoplan chain ordering (periodic)', () => { // Phase markers live in autoplan's carved phase sections // (autoplan/sections/{ceo,design,eng,dx}-phase.md — the skeleton // STOP-Reads each one at its phase boundary): - // "**Phase 1 complete." / "**Phase 2 complete." / "**Phase 3 complete." / "**Phase 3.5 complete." + // "**Phase 1 complete." / "**Phase 2 complete." / "**Phase 2.5 complete." / "**Phase 3 complete." const phasePattern = /\*\*Phase\s+(\d+(?:\.\d+)?)\s+complete\.?\*\*/g; let lastPermSig = ''; @@ -163,13 +164,22 @@ describeE2E('/autoplan chain ordering (periodic)', () => { ); } - // Sequencing: CEO must end before Eng ends. Design (if observed) - // must end after CEO and before Eng. + // Sequencing: CEO must end before Eng ends — and Eng is the terminal + // phase (the required gate reviews the final amended plan). Design and + // DX (if observed) must end after CEO and before Eng. expect(ceo.ts).toBeLessThan(eng.ts); if (design) { expect(design.ts).toBeGreaterThan(ceo.ts); expect(design.ts).toBeLessThan(eng.ts); } + const dx = hits.find(h => h.phase === 2.5); + if (dx) { + expect(dx.ts).toBeGreaterThan(ceo.ts); + expect(dx.ts).toBeLessThan(eng.ts); + } + // No phase marker may appear after Eng's (Eng-last invariant). + const maxTs = Math.max(...hits.map(h => h.ts)); + expect(eng.ts).toBe(maxTs); } finally { try { fs.rmSync(tempDir, { recursive: true, force: true }); } catch { /* ignore */ } }