diff --git a/get-shit-done/bin/lib/phase.cjs b/get-shit-done/bin/lib/phase.cjs
index 6bf2e5cf..5cb5eac4 100644
--- a/get-shit-done/bin/lib/phase.cjs
+++ b/get-shit-done/bin/lib/phase.cjs
@@ -880,6 +880,34 @@ function cmdPhaseComplete(cwd, phaseNum, raw) {
`$1Phase ${phaseNum} complete${nextPhaseNum ? `, transitioned to Phase ${nextPhaseNum}` : ''}`
);
+ // Increment Completed Phases counter (#956)
+ const completedMatch = stateContent.match(/\*\*Completed Phases:\*\*\s*(\d+)/);
+ if (completedMatch) {
+ const newCompleted = parseInt(completedMatch[1], 10) + 1;
+ stateContent = stateContent.replace(
+ /(\*\*Completed Phases:\*\*\s*)\d+/,
+ `$1${newCompleted}`
+ );
+
+ // Recalculate percent based on completed / total (#956)
+ const totalMatch = stateContent.match(/\*\*Total Phases:\*\*\s*(\d+)/);
+ if (totalMatch) {
+ const totalPhases = parseInt(totalMatch[1], 10);
+ if (totalPhases > 0) {
+ const newPercent = Math.round((newCompleted / totalPhases) * 100);
+ stateContent = stateContent.replace(
+ /(\*\*Progress:\*\*\s*)\d+%/,
+ `$1${newPercent}%`
+ );
+ // Also update percent field if it exists separately
+ stateContent = stateContent.replace(
+ /(percent:\s*)\d+/,
+ `$1${newPercent}`
+ );
+ }
+ }
+ }
+
writeStateMd(statePath, stateContent, cwd);
}
diff --git a/get-shit-done/workflows/execute-phase.md b/get-shit-done/workflows/execute-phase.md
index 243103b9..d7096616 100644
--- a/get-shit-done/workflows/execute-phase.md
+++ b/get-shit-done/workflows/execute-phase.md
@@ -499,6 +499,28 @@ node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-{X}): co
```
+
+**Evolve PROJECT.md to reflect phase completion (prevents planning document drift — #956):**
+
+PROJECT.md tracks validated requirements, decisions, and current state. Without this step,
+PROJECT.md falls behind silently over multiple phases.
+
+1. Read `.planning/PROJECT.md`
+2. If the file exists and has a `## Validated Requirements` or `## Requirements` section:
+ - Move any requirements validated by this phase from Active → Validated
+ - Add a brief note: `Validated in Phase {X}: {Name}`
+3. If the file has a `## Current State` or similar section:
+ - Update it to reflect this phase's completion (e.g., "Phase {X} complete — {one-liner}")
+4. Update the `Last updated:` footer to today's date
+5. Commit the change:
+
+```bash
+node "$HOME/.claude/get-shit-done/bin/gsd-tools.cjs" commit "docs(phase-{X}): evolve PROJECT.md after phase completion" --files .planning/PROJECT.md
+```
+
+**Skip this step if** `.planning/PROJECT.md` does not exist.
+
+
**Exception:** If `gaps_found`, the `verify_phase_goal` step already presents the gap-closure path (`/gsd:plan-phase {X} --gaps`). No additional routing needed — skip auto-advance.