<purpose>
Validate `.planning/` directory integrity and report actionable issues. Checks for missing files, invalid configurations, inconsistent state, and orphaned plans. Optionally repairs auto-fixable issues.
</purpose>

<required_reading>
Read all files referenced by the invoking prompt's execution_context before starting.
</required_reading>

<process>

<step name="step_0_mode_aware_init">
**Phase 67-02 STATUS-03 + STATE-03: load mode-aware init context.**

Run init health to retrieve organizational mode, milestones index, parallel-mode aggregation, and stale-pointer detection result:

```bash
INIT=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" init health)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
```

Extract from init JSON:
- `organizational_mode` — `'sequential'` | `'parallel'`
- `active_milestone_slug` — string | null
- `milestones_index` — `{ in_progress[], planned[], shipped[], on_disk[], rows{} }`
- `milestones_aggregation` — array of `{ slug, phases_complete, phases_total, plans_complete, plans_total, last_activity, is_active, drift_warnings[] }` (parallel mode only; empty in sequential)
- `stale_pointer` — `{ stale, case, slug, warn_text }` (3-case enumeration per CONTEXT.md Area 2; critic Gate 1 R1)
</step>

<step name="parse_args">
**Parse arguments:**

Check if `--repair` flag is present in the command arguments.

```
REPAIR_FLAG=""
if arguments contain "--repair"; then
  REPAIR_FLAG="--repair"
fi
```
</step>

<step name="run_health_check">
**Run health validation:**

```bash
node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" validate health $REPAIR_FLAG
```

Parse JSON output:
- `status`: "healthy" | "degraded" | "broken"
- `errors[]`: Critical issues (code, message, fix, repairable)
- `warnings[]`: Non-critical issues
- `info[]`: Informational notes
- `repairable_count`: Number of auto-fixable issues
- `repairs_performed[]`: Actions taken if --repair was used
</step>

<step name="format_output">
**Format and display results:**

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD Health Check
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Status: HEALTHY | DEGRADED | BROKEN
Errors: N | Warnings: N | Info: N
```

**If repairs were performed:**
```
## Repairs Performed

- ✓ config.json: Created with defaults
- ✓ STATE.md: Regenerated from roadmap
```

**If errors exist:**
```
## Errors

- [E001] config.json: JSON parse error at line 5
  Fix: Run /gmd:health --repair to reset to defaults

- [E002] PROJECT.md not found
  Fix: Run /gmd:new-project to create
```

**If warnings exist:**
```
## Warnings

- [W001] STATE.md references phase 5, but only phases 1-3 exist
  Fix: Run /gmd:health --repair to regenerate

- [W005] Phase directory "1-setup" doesn't follow NN-name format
  Fix: Rename to match pattern (e.g., 01-setup)
```

**If info exists:**
```
## Info

- [I001] 02-implementation/02-01-PLAN.md has no SUMMARY.md
  Note: May be in progress
```

**Footer (if repairable issues exist and --repair was NOT used):**
```
---
N issues can be auto-repaired. Run: /gmd:health --repair
```
</step>

<step name="parallel_aggregation">
**Phase 67-02 STATUS-03: parallel-mode cross-milestone aggregation.**

Runs ONLY when `organizational_mode === 'parallel'`. Sequential mode skips this step entirely — `/gmd:health` body remains P1 byte-identical to v1.5.8 ship anchor `a9e6cd4`.

If `organizational_mode !== 'parallel'`:
- Skip this step. Proceed to `<step name="render_stale_warning">` (which is also gated on parallel mode).

If `organizational_mode === 'parallel'` AND `milestones_aggregation.length > 0`:

Render one health row per in-progress milestone. Active milestone (pointer match — `is_active === true`) is flagged with `▶` glyph. Output format:

```
## In-Progress Milestones (parallel mode)

| slug | phases_complete/total | plans_complete/total | last_activity | drift_warnings |
| ---- | --------------------- | -------------------- | ------------- | -------------- |
| ▶ v1.5.9 | 3/5 | 12/25 | 2026-05-24 | — |
| v1.6 | 0/0 | 0/0 | — | — |
```

Columns:
- `slug` — kebab-case milestone slug; prefixed with `▶` (U+25B6) when `is_active === true` (active-milestone pointer match)
- `phases_complete/total` — counts derived from per-milestone ROADMAP.md (em-dash `—` when ROADMAP.md missing or unparseable)
- `plans_complete/total` — counts derived from per-milestone ROADMAP.md (em-dash `—` when missing)
- `last_activity` — from per-milestone STATE.md frontmatter (em-dash `—` when absent)
- `drift_warnings` — reserved for future drift detection; em-dash `—` in v1.5.9

If `milestones_aggregation.length === 0` (parallel mode with no in-progress milestones), render:

```
## In-Progress Milestones (parallel mode)

(No in-progress milestones.)
```

This block is APPENDED to the existing format_output report (does not replace sequential-mode body).
</step>

<step name="render_stale_warning">
**Phase 67-02 STATE-03: stale-pointer detection rendering.**

Runs ONLY when `organizational_mode === 'parallel'`. Sequential mode skips entirely (P1 byte-identical preservation).

Consume `stale_pointer` field from INIT JSON. Three cases (CONTEXT.md Area 2 decision_id `a825b9c0-e0a3-0e65-c000-000000000004`; critic Gate 1 R1):

- **(a) pointer at shipped milestone:** `stale_pointer.case === 'a'` — emit `stale_pointer.warn_text` to **stderr** and continue with exit 0. Documented warn text: `current_milestone points at shipped milestone <slug>; run /gmd:switch-milestone to advance`.

- **(b) pointer at nonexistent milestone:** `stale_pointer.case === 'b'` — emit `stale_pointer.warn_text` to **stderr** and continue with exit 0. Documented warn text: `current_milestone points at nonexistent milestone <slug>; possibly typo or post-rename leftover`.

- **(c) transient race-case:** shape-matches case (a); same warn text. By definition transient (CMD-05 atomicity contract from Phase 66-04 guarantees the race window is short).

If `stale_pointer.stale === false`: no-op. No stderr text, no exit-code change.

**Exit-code contract (critic Gate 3 MC-2 lock):** stale-pointer warnings = stderr text + exit 0 (warnings are NOT failures). Only catastrophic state corruption (root STATE.md missing, MILESTONES.md unparseable) — handled by the existing `validate health` exit path — produces exit-non-zero. The new stale-pointer block does NOT shadow or escalate the catastrophic path.

**Bash implementation pattern (one-shot):**

```bash
if [ "$ORG_MODE" = "parallel" ] && [ "$(echo "$INIT" | jq -r '.stale_pointer.stale')" = "true" ]; then
  WARN_TEXT=$(echo "$INIT" | jq -r '.stale_pointer.warn_text')
  echo "$WARN_TEXT" >&2
fi
```

Continue to `<step name="offer_repair">` regardless of stale-pointer state. Catastrophic-corruption exit-non-zero path (existing `validate health`) is preserved upstream of this block.
</step>

<step name="offer_repair">
**If repairable issues exist and --repair was NOT used:**

Ask user if they want to run repairs:

```
Would you like to run /gmd:health --repair to fix N issues automatically?
```

If yes, re-run with --repair flag and display results.
</step>

<step name="verify_repairs">
**If repairs were performed:**

Re-run health check without --repair to confirm issues are resolved:

```bash
node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" validate health
```

Report final status.
</step>

</process>

<error_codes>

| Code | Severity | Description | Repairable |
|------|----------|-------------|------------|
| E001 | error | .planning/ directory not found | No |
| E002 | error | PROJECT.md not found | No |
| E003 | error | ROADMAP.md not found | No |
| E004 | error | STATE.md not found | Yes |
| E005 | error | config.json parse error | Yes |
| W001 | warning | PROJECT.md missing required section | No |
| W002 | warning | STATE.md references invalid phase | Yes |
| W003 | warning | config.json not found | Yes |
| W004 | warning | config.json invalid field value | No |
| W005 | warning | Phase directory naming mismatch | No |
| W006 | warning | Phase in ROADMAP but no directory | No |
| W007 | warning | Phase on disk but not in ROADMAP | No |
| W008 | warning | config.json: workflow.nyquist_validation absent (defaults to enabled but agents may skip) | Yes |
| W009 | warning | Phase has Validation Architecture in RESEARCH.md but no VALIDATION.md | No |
| I001 | info | Plan without SUMMARY (may be in progress) | No |

</error_codes>

<repair_actions>

| Action | Effect | Risk |
|--------|--------|------|
| createConfig | Create config.json with defaults | None |
| resetConfig | Delete + recreate config.json | Loses custom settings |
| regenerateState | Create STATE.md from ROADMAP structure | Loses session history |
| addNyquistKey | Add workflow.nyquist_validation: true to config.json | None — matches existing default |

**Not repairable (too risky):**
- PROJECT.md, ROADMAP.md content
- Phase directory renaming
- Orphaned plan cleanup

</repair_actions>
