fix: enforce mandatory verification before phase/milestone completion routing

- Rewrite offer_next step in execute-phase.md as mandatory verification gate
- Rewrite offer_next_phase step in transition.md with explicit verification
- Rewrite route step in progress.md with numbered verification steps
- Replace broken regex [0-9] (only matched single digits) with ROADMAP.md reading
- Add decision tables mapping conditions to explicit routes (A, B, C, D)
- Require Claude to "State the counts" before any routing decision
- Add "Do NOT skip this verification" instruction to prevent premature completion claims

Fixes issue where Claude would declare "phase complete" or "milestone complete"
without verifying remaining plans actually exist.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Lex Christopherson
2026-01-07 15:19:22 -06:00
parent 6a1db4f420
commit da884ea7f0
3 changed files with 259 additions and 131 deletions

View File

@@ -90,84 +90,164 @@ CONTEXT: [✓ if CONTEXT.md exists | - if not]
</step>
<step name="route">
**Determine next action:**
**Determine next action based on verified counts.**
Find the next plan number that needs work.
Check if `{phase}-{plan}-PLAN.md` exists for that number.
**Step 1: Count plans and summaries in current phase**
**If PLAN.md exists (unexecuted):**
List files in the current phase directory:
- Read its `<objective>` section
- Show: "Ready to execute: [path] - [objective summary]"
- Display (see ~/.claude/get-shit-done/references/continuation-format.md):
```
---
```bash
ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null | wc -l
```
## ▶ Next Up
State: "This phase has {X} plans and {Y} summaries."
**{phase}-{plan}: [Plan Name]** — [objective summary from PLAN.md]
**Step 2: Route based on counts**
`/gsd:execute-plan [full-path-to-PLAN.md]`
| Condition | Meaning | Action |
|-----------|---------|--------|
| summaries < plans | Unexecuted plans exist | Go to **Route A** |
| summaries = plans AND plans > 0 | Phase complete | Go to Step 3 |
| plans = 0 | Phase not yet planned | Go to **Route B** |
<sub>`/clear` first → fresh context window</sub>
---
---
```
**Route A: Unexecuted plan exists**
**If PLAN.md does NOT exist:**
Find the first PLAN.md without matching SUMMARY.md.
Read its `<objective>` section.
- Check if `{phase}-CONTEXT.md` exists in phase directory
- Show: "Next plan not yet created: [expected path]"
- Show phase objective from ROADMAP
```
---
## ▶ Next Up
**{phase}-{plan}: [Plan Name]** — [objective summary from PLAN.md]
`/gsd:execute-plan [full-path-to-PLAN.md]`
<sub>`/clear` first → fresh context window</sub>
---
```
---
**Route B: Phase needs planning**
Check if `{phase}-CONTEXT.md` exists in phase directory.
**If CONTEXT.md exists:**
- Display: "✓ Context gathered, ready to plan"
- Display:
```
---
```
---
## ▶ Next Up
## ▶ Next Up
**Phase [N]: [Name]** — [Goal from ROADMAP.md]
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
<sub>✓ Context gathered, ready to plan</sub>
`/gsd:plan-phase [phase-number]`
`/gsd:plan-phase {phase-number}`
<sub>`/clear` first → fresh context window</sub>
<sub>`/clear` first → fresh context window</sub>
---
```
---
```
**If CONTEXT.md does NOT exist:**
- Display:
```
---
```
---
## ▶ Next Up
## ▶ Next Up
**Phase [N]: [Name]** — [Goal from ROADMAP.md]
**Phase {N}: {Name}** — {Goal from ROADMAP.md}
`/gsd:plan-phase [phase]`
`/gsd:plan-phase {phase}`
<sub>`/clear` first → fresh context window</sub>
<sub>`/clear` first → fresh context window</sub>
---
---
**Also available:**
- `/gsd:discuss-phase [phase]` — gather context first
- `/gsd:research-phase [phase]` — investigate unknowns
- `/gsd:list-phase-assumptions [phase]` — see Claude's assumptions
**Also available:**
- `/gsd:discuss-phase {phase}` — gather context first
- `/gsd:research-phase {phase}` — investigate unknowns
- `/gsd:list-phase-assumptions {phase}` — see Claude's assumptions
---
```
---
```
**If all plans complete for current phase:**
---
- Check if more phases exist in ROADMAP
- If yes: Show `/gsd:plan-phase [next-phase]` command to paste
- If no (milestone 100% complete): Show `/gsd:complete-milestone` command to paste
</step>
**Step 3: Check milestone status (only when phase complete)**
Read ROADMAP.md and identify:
1. Current phase number
2. All phase numbers in the current milestone section
Count total phases and identify the highest phase number.
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
**Route based on milestone status:**
| Condition | Meaning | Action |
|-----------|---------|--------|
| current phase < highest phase | More phases remain | Go to **Route C** |
| current phase = highest phase | Milestone complete | Go to **Route D** |
---
**Route C: Phase complete, more phases remain**
Read ROADMAP.md to get the next phase's name and goal.
```
---
## ✓ Phase {Z} Complete
## ▶ Next Up
**Phase {Z+1}: {Name}** — {Goal from ROADMAP.md}
`/gsd:plan-phase {Z+1}`
<sub>`/clear` first → fresh context window</sub>
---
**Also available:**
- `/gsd:discuss-phase {Z+1}` — gather context first
- `/gsd:research-phase {Z+1}` — investigate unknowns
---
```
---
**Route D: Milestone complete**
```
---
## 🎉 Milestone Complete
All {N} phases finished!
## ▶ Next Up
**Complete Milestone** — archive and prepare for next
`/gsd:complete-milestone`
<sub>`/clear` first → fresh context window</sub>
---
```
</step>
<step name="edge_cases">
**Handle edge cases:**

View File

@@ -1437,33 +1437,44 @@ Use AskUserQuestion:
</step>
<step name="offer_next">
**First, determine if more plans exist in this phase:**
**MANDATORY: Verify remaining work before presenting next steps.**
Do NOT skip this verification. Do NOT assume phase or milestone completion without checking.
**Step 1: Count plans and summaries in current phase**
List files in the phase directory:
```bash
# Get current phase directory from the plan we just executed
PHASE_DIR=$(dirname "$PLAN_PATH")
# Count PLAN files vs SUMMARY files
PLAN_COUNT=$(ls "$PHASE_DIR"/*-PLAN.md 2>/dev/null | wc -l | tr -d ' ')
SUMMARY_COUNT=$(ls "$PHASE_DIR"/*-SUMMARY.md 2>/dev/null | wc -l | tr -d ' ')
echo "Plans: $PLAN_COUNT, Summaries: $SUMMARY_COUNT"
if [[ $SUMMARY_COUNT -lt $PLAN_COUNT ]]; then
echo "MORE_PLANS_EXIST"
else
echo "PHASE_COMPLETE"
fi
ls -1 .planning/phases/[current-phase-dir]/*-PLAN.md 2>/dev/null | wc -l
ls -1 .planning/phases/[current-phase-dir]/*-SUMMARY.md 2>/dev/null | wc -l
```
**If MORE_PLANS_EXIST (more plans in this phase):**
State the counts: "This phase has [X] plans and [Y] summaries."
**Step 2: Route based on plan completion**
Compare the counts from Step 1:
| Condition | Meaning | Action |
|-----------|---------|--------|
| summaries < plans | More plans remain | Go to **Route A** |
| summaries = plans | Phase complete | Go to Step 3 |
---
**Route A: More plans remain in this phase**
Identify the next unexecuted plan:
- Find the first PLAN.md file that has no matching SUMMARY.md
- Read its `<objective>` section
<if mode="yolo">
```
Plan {phase}-{plan} complete.
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
[X] of [Y] plans complete for Phase Z.
{Y} of {X} plans complete for Phase {Z}.
⚡ Auto-continuing: Execute next plan ({phase}-{next-plan})
```
@@ -1474,9 +1485,9 @@ Loop back to identify_plan step automatically.
<if mode="interactive" OR="custom with gates.execute_next_plan true">
```
Plan {phase}-{plan} complete.
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
[X] of [Y] plans complete for Phase Z.
{Y} of {X} plans complete for Phase {Z}.
---
@@ -1484,7 +1495,7 @@ Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
**{phase}-{next-plan}: [Plan Name]** — [objective from next PLAN.md]
`/gsd:execute-plan .planning/phases/XX-name/{phase}-{next-plan}-PLAN.md`
`/gsd:execute-plan .planning/phases/{phase-dir}/{phase}-{next-plan}-PLAN.md`
<sub>`/clear` first → fresh context window</sub>
@@ -1499,37 +1510,82 @@ Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
Wait for user to clear and run next command.
</if>
**If phase complete (last plan done):**
**STOP here if Route A applies. Do not continue to Step 3.**
First, check if this is also the last phase in the milestone (milestone complete):
---
```bash
# Count total phases in ROADMAP.md
TOTAL_PHASES=$(grep -c "^### Phase [0-9]" .planning/ROADMAP.md)
**Step 3: Check milestone status (only when all plans in phase are complete)**
# Get current phase number from the just-completed plan
CURRENT_PHASE=$(echo "{phase}" | grep -oE '^[0-9]+')
Read ROADMAP.md and extract:
1. Current phase number (from the plan just completed)
2. All phase numbers listed in the current milestone section
# Check if current phase == total phases
if [[ "$CURRENT_PHASE" -eq "$TOTAL_PHASES" ]]; then
# Milestone complete
MILESTONE_COMPLETE=true
fi
To find phases in the current milestone, look for:
- Phase headers: lines starting with `### Phase` or `#### Phase`
- Phase list items: lines like `- [ ] **Phase X:` or `- [x] **Phase X:`
Count total phases in the current milestone and identify the highest phase number.
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
**Step 4: Route based on milestone status**
| Condition | Meaning | Action |
|-----------|---------|--------|
| current phase < highest phase | More phases remain | Go to **Route B** |
| current phase = highest phase | Milestone complete | Go to **Route C** |
---
**Route B: Phase complete, more phases remain in milestone**
Read ROADMAP.md to get the next phase's name and goal.
```
Plan {phase}-{plan} complete.
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
## ✓ Phase {Z}: {Phase Name} Complete
All {Y} plans finished.
---
## ▶ Next Up
**Phase {Z+1}: {Next Phase Name}** — {Goal from ROADMAP.md}
`/gsd:plan-phase {Z+1}`
<sub>`/clear` first → fresh context window</sub>
---
**Also available:**
- `/gsd:discuss-phase {Z+1}` — gather context first
- `/gsd:research-phase {Z+1}` — investigate unknowns
- Review phase accomplishments before continuing
---
```
**If milestone complete (final phase of roadmap done):**
---
**Route C: Milestone complete (all phases done)**
```
🎉 MILESTONE COMPLETE!
Plan {phase}-{plan} complete.
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
Summary: .planning/phases/{phase-dir}/{phase}-{plan}-SUMMARY.md
Phase [Z]: [Name] COMPLETE - all [Y] plans finished.
## ✓ Phase {Z}: {Phase Name} Complete
All {Y} plans finished.
════════════════════════════════════════
All [N] phases complete!
This milestone is 100% done.
All {N} phases complete!
Milestone is 100% done.
════════════════════════════════════════
---
@@ -1545,42 +1601,12 @@ This milestone is 100% done.
---
**Also available:**
- `/gsd:add-phase <description>` — add another phase
- `/gsd:add-phase <description>` — add another phase before completing
- Review accomplishments before archiving
---
```
**If phase complete but more phases remain:**
```
Plan {phase}-{plan} complete.
Summary: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md
## ✓ Phase [Z] Complete
All [Y] plans finished.
---
## ▶ Next Up
**Phase [X+1]: [Name]** — [Goal from ROADMAP.md]
`/gsd:plan-phase [X+1]`
<sub>`/clear` first → fresh context window</sub>
---
**Also available:**
- `/gsd:discuss-phase [X+1]` — gather context first
- `/gsd:research-phase [X+1]` — investigate unknowns
- Review phase accomplishments before continuing
---
```
</step>
</process>

View File

@@ -408,14 +408,34 @@ Resume file: None
<step name="offer_next_phase">
**Check if there's a next phase in the current milestone:**
**MANDATORY: Verify milestone status before presenting next steps.**
Re-read the ROADMAP file:
**Step 1: Read ROADMAP.md and identify phases in current milestone**
- Parse current milestone version (e.g., "v1.0" from "## Current Milestone: v1.0 Foundation")
- Look for phases after the current one in the current milestone section
- If next phase exists: offer to plan it
- If no next phase (milestone 100% complete): offer to complete milestone with parsed version
Read the ROADMAP.md file and extract:
1. Current phase number (the phase just transitioned from)
2. All phase numbers in the current milestone section
To find phases, look for:
- Phase headers: lines starting with `### Phase` or `#### Phase`
- Phase list items: lines like `- [ ] **Phase X:` or `- [x] **Phase X:`
Count total phases and identify the highest phase number in the milestone.
State: "Current phase is {X}. Milestone has {N} phases (highest: {Y})."
**Step 2: Route based on milestone status**
| Condition | Meaning | Action |
|-----------|---------|--------|
| current phase < highest phase | More phases remain | Go to **Route A** |
| current phase = highest phase | Milestone complete | Go to **Route B** |
---
**Route A: More phases remain in milestone**
Read ROADMAP.md to get the next phase's name and goal.
**If next phase exists:**
@@ -460,36 +480,38 @@ Exit skill and invoke SlashCommand("/gsd:plan-phase [X+1]")
</if>
**If no next phase (milestone 100% complete):**
---
**Route B: Milestone complete (all phases done)**
<if mode="yolo">
```
Phase [X] marked complete.
Phase {X} marked complete.
🎉 Milestone [version] is 100% complete — all phases finished!
🎉 Milestone {version} is 100% complete — all {N} phases finished!
⚡ Auto-continuing: Complete milestone and archive
```
Exit skill and invoke SlashCommand("/gsd:complete-milestone [version]")
Exit skill and invoke SlashCommand("/gsd:complete-milestone {version}")
</if>
<if mode="interactive" OR="custom with gates.confirm_transition true">
```
## ✓ Phase [X] Complete
## ✓ Phase {X}: {Phase Name} Complete
🎉 Milestone [version] is 100% complete — all phases finished!
🎉 Milestone {version} is 100% complete — all {N} phases finished!
---
## ▶ Next Up
**Complete Milestone [version]** — archive and prepare for next
**Complete Milestone {version}** — archive and prepare for next
`/gsd:complete-milestone [version]`
`/gsd:complete-milestone {version}`
<sub>`/clear` first → fresh context window</sub>