<purpose>
Create executable phase prompts (PLAN.md files) for a roadmap phase with integrated research and verification. Default flow: Research (if needed) -> Plan -> Verify -> Done. Orchestrates gmd-phase-researcher, gmd-planner, and gmd-plan-checker agents with a revision loop (max 3 iterations).
</purpose>

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

@C:/Users/Christopher/.claude/get-magic-done/references/ui-brand.md
</required_reading>

<process>

## 0. Mode-Aware Path Resolution (v1.5.9 Parallel Milestone Organization)

Resolve organizational mode + active milestone slug ONCE; all subsequent path lookups route through `resolveMilestonePaths(mode, slug, artifact)`. Workflow consumes `active_milestone_slug` from init JSON — it does NOT parse `--milestone` itself (P3 thin-wrapper; flag parsed once at gmd-tools.cjs init dispatch entry per Plan 66-01).

```bash
INIT=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" init plan-phase "$PHASE" --raw)
MODE=$(echo "$INIT" | jq -r '.organizational_mode')
SLUG=$(echo "$INIT" | jq -r '.active_milestone_slug // empty')
NEEDS_PROMPT=$(echo "$INIT" | jq -r '.active_milestone_needs_prompt')
```

**Tier 4 prompt (parallel mode, no flag, no pointer, multiple/zero In Progress milestones):**

If `$NEEDS_PROMPT == "true"`:
- Read `.active_milestone_candidates` array from init JSON
- Invoke AskUserQuestion with the candidate list
- Persist selection: `node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" state set-current-milestone "<chosen-slug>"`
- Re-run init to pick up the now-set slug (re-execute the INIT=$(...) block above)

**Path lookups (used throughout this workflow):**

```bash
REQS_PATH=$(node -e "const {resolveMilestonePaths}=require('$HOME/.claude/get-magic-done/bin/lib/path-resolve.js'); console.log(resolveMilestonePaths('$MODE', '$SLUG' || null, 'REQUIREMENTS'))")
ROADMAP_PATH=$(node -e "const {resolveMilestonePaths}=require('$HOME/.claude/get-magic-done/bin/lib/path-resolve.js'); console.log(resolveMilestonePaths('$MODE', '$SLUG' || null, 'ROADMAP'))")
STATE_PATH=$(node -e "const {resolveMilestonePaths}=require('$HOME/.claude/get-magic-done/bin/lib/path-resolve.js'); console.log(resolveMilestonePaths('$MODE', '$SLUG' || null, 'STATE'))")
PHASES_DIR=$(node -e "const {resolveMilestonePaths}=require('$HOME/.claude/get-magic-done/bin/lib/path-resolve.js'); console.log(resolveMilestonePaths('$MODE', '$SLUG' || null, 'phases-dir'))")

# GROUND-03 (v1.8.2.5): active-milestone SPEC path for the critic grounding bundle.
# path-resolve.js has NO 'SPEC' artifact key (D2: the library does no SPEC resolution),
# so the CALLER composes it here per the milestone-SPEC layout convention:
#   sequential: .planning/milestones/<active>-SPEC.md   (flat, slug-prefixed)
#   parallel:   .planning/milestones/<slug>/<slug>-SPEC.md
# SLUG is the active-milestone slug from Step 0 init JSON. Both branches stay
# caller-resolved — no new library I/O is introduced (D2 held).
if [[ "$MODE" == "parallel" ]]; then
  SPEC_PATH=".planning/milestones/$SLUG/$SLUG-SPEC.md"
else
  SPEC_PATH=".planning/milestones/$SLUG-SPEC.md"
fi
```

**Sequential mode:** `MODE=sequential, SLUG=null` → paths resolve to root `.planning/` (byte-identical to pre-v1.5.9 behavior per P1). No Tier 4 prompt fires.

**Parallel mode:** `MODE=parallel, SLUG=<active>` → paths route to `.planning/milestones/<slug>/`. If `--milestone <slug>` flag was passed at `/gmd:plan-phase` invocation, it overrides the pointer (Tier 1; init.cjs handled this at flag-parse entry).

**Project-level paths stay literal** (root in BOTH modes per Phase 65 Decision O6-lean PROJECT_LEVEL_PATHS table): `.planning/PROJECT.md`, `.planning/MILESTONES.md`, `.planning/config.json`.

## 1. Initialize

Load all context in one call (paths only to minimize orchestrator context):

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

Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_enabled`, `plan_checker_enabled`, `nyquist_validation_enabled`, `commit_docs`, `phase_found`, `phase_dir`, `phase_number`, `phase_name`, `phase_slug`, `padded_phase`, `has_research`, `has_context`, `has_plans`, `plan_count`, `planning_exists`, `roadmap_exists`, `phase_req_ids`, `organizational_mode`, `active_milestone_slug`, `active_milestone_needs_prompt`, `active_milestone_candidates`.

**File paths (for <files_to_read> blocks):** `state_path`, `roadmap_path`, `requirements_path`, `context_path`, `research_path`, `verification_path`, `uat_path`. These are null if files don't exist.

**If `planning_exists` is false:** Error — run `/gmd:new-project` first.

## 1.5. Vault Pre-flight (D9b)

Run `vault-orient` to pre-warm the 5-min query cache and build a compressed `<vault_context>` block for injection into every downstream Task() prompt. This is the D9b orchestrator-side default: vault-use as the default code path, not an opt-in. Component-gate-aware: skips silently when `components.obsidian.enabled: false`.

```bash
VAULT_ORIENT_RAW=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" vault-orient \
  --agent orchestrator-plan-phase 2>/dev/null || echo '{"skipped":"vault unavailable"}')
```

**Compress orient JSON to a ~300-tok `<vault_context>` block:**

1. Parse the orient JSON. If `.skipped` is set OR the JSON contains an error field, set `VAULT_CONTEXT_BLOCK=""` (empty) and skip to step 3.
2. Otherwise, extract:
   - `index_summary` — cap at 1200 chars (append `…[truncated]` if longer)
   - `in_scope_notes[0..4]` — top 5 notes, emit `path + summary` only (no bodies)
   - `directives[*].summary` (or first-line fallback) — directive summaries only, no bodies
3. Build the block in this exact shape (omit entirely if compression produced nothing):

   ```
   <vault_context>
   ## Index Summary
   {index_summary}

   ## In-Scope Notes (top 5)
   - {path}: {summary}
   - ...

   ## Directives (summary only; re-read via vault-read if needed)
   - {path}: {summary}
   - ...

   vault_status: {ok | empty | error}
   </vault_context>
   ```

**Injection contract:** The `VAULT_CONTEXT_BLOCK` must be injected into every downstream Task() prompt immediately before the existing `<files_to_read>` block. When empty (skipped/error/empty orient), omit the block entirely — never inject an empty `<vault_context></vault_context>`. Cached orient means subsequent subagent `vault-query` calls hit the warm 5-min cache (~116ms cached vs ~1700ms uncached on Windows).

**Code-map slice (Tier-1 push — WIRE-01):** after building `VAULT_CONTEXT_BLOCK`, obtain the scoped code-map slice. Plan-phase performs TWO builds because `files_modified` is the planner's OUTPUT — it does not exist at preflight time:

**(a) Preflight build (here) — feeds the researcher + planner spawns.** Source: when `has_context` is true, extract the file paths mentioned in CONTEXT.md's `<code_context>` section → `--files <csv>`, plus key terms from the roadmap phase description → `--symbols <csv>`. When neither yields anything, skip the invocation entirely (empty → omit). Never fabricate scope.

```bash
CODE_MAP_CONTEXT_BLOCK=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" code-slice --files "<csv from CONTEXT.md code seams>" --symbols "<csv of roadmap phase-description terms>" --format block 2>/dev/null || true)
```

**(b) Post-planning rebuild (Step 10) — feeds the checker + revision spawns** as `CODE_MAP_CONTEXT_BLOCK_V2`, built from the union of the just-written plans' `files_modified` frontmatter (see Step 10).

**Injection contract for `<code_map_context>`:** inject the block immediately AFTER `<vault_context>`, BEFORE `<files_to_read>`, in the downstream Task() prompts named here (researcher + planner receive `CODE_MAP_CONTEXT_BLOCK`; checker + revision receive `CODE_MAP_CONTEXT_BLOCK_V2`). When empty, omit entirely — never inject an empty `<code_map_context></code_map_context>`. The block already embeds the Tier-2 pull commands + the freshness verdict (launch point, not payload — D-V184-05); the orchestrator never widens it.

## 2. Parse and Normalize Arguments

Extract from $ARGUMENTS: phase number (integer or decimal like `2.1`), flags (`--research`, `--skip-research`, `--high-research`, `--gaps`, `--skip-verify`, `--prd <filepath>`).

Extract `--prd <filepath>` from $ARGUMENTS. If present, set PRD_FILE to the filepath.

**If no phase number:** Detect next unplanned phase from roadmap.

**If `phase_found` is false:** Validate phase exists in ROADMAP.md. If valid, create the directory using `phase_slug` and `padded_phase` from init (mode-aware: routes to `${PHASES_DIR}` resolved at Step 0):
```bash
mkdir -p "${PHASES_DIR}/${padded_phase}-${phase_slug}"
```

**Existing artifacts from init:** `has_research`, `has_plans`, `plan_count`.

## 3. Validate Phase

```bash
PHASE_INFO=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" roadmap get-phase "${PHASE}")
```

**If `found` is false:** Error with available phases. **If `found` is true:** Extract `phase_number`, `phase_name`, `goal` from JSON.

## 3.5. Handle PRD Express Path

**Skip if:** No `--prd` flag in arguments.

**If `--prd <filepath>` provided:**

1. Read the PRD file:
```bash
PRD_CONTENT=$(cat "$PRD_FILE" 2>/dev/null)
if [ -z "$PRD_CONTENT" ]; then
  echo "Error: PRD file not found: $PRD_FILE"
  exit 1
fi
```

2. Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► PRD EXPRESS PATH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Using PRD: {PRD_FILE}
Generating CONTEXT.md from requirements...
```

3. Parse the PRD content and generate CONTEXT.md. The orchestrator should:
   - Extract all requirements, user stories, acceptance criteria, and constraints from the PRD
   - Map each to a locked decision (everything in the PRD is treated as a locked decision)
   - Identify any areas the PRD doesn't cover and mark as "Claude's Discretion"
   - Create CONTEXT.md in the phase directory

4. Write CONTEXT.md:
```markdown
# Phase [X]: [Name] - Context

**Gathered:** [date]
**Status:** Ready for planning
**Source:** PRD Express Path ({PRD_FILE})

<domain>
## Phase Boundary

[Extracted from PRD — what this phase delivers]

</domain>

<decisions>
## Implementation Decisions

{For each requirement/story/criterion in the PRD:}
### [Category derived from content]
- [Requirement as locked decision]

### Claude's Discretion
[Areas not covered by PRD — implementation details, technical choices]

</decisions>

<specifics>
## Specific Ideas

[Any specific references, examples, or concrete requirements from PRD]

</specifics>

<deferred>
## Deferred Ideas

[Items in PRD explicitly marked as future/v2/out-of-scope]
[If none: "None — PRD covers phase scope"]

</deferred>

---

*Phase: XX-name*
*Context gathered: [date] via PRD Express Path*
```

5. Commit:
```bash
node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" commit "docs(${padded_phase}): generate context from PRD" --files "${phase_dir}/${padded_phase}-CONTEXT.md"
```

6. Set `context_content` to the generated CONTEXT.md content and continue to step 5 (Handle Research).

**Effect:** This completely bypasses step 4 (Load CONTEXT.md) since we just created it. The rest of the workflow (research, planning, verification) proceeds normally with the PRD-derived context.

## 4. Load CONTEXT.md

**Skip if:** PRD express path was used (CONTEXT.md already created in step 3.5).

Check `context_path` from init JSON.

If `context_path` is not null, display: `Using phase context from: ${context_path}`

**If `context_path` is null (no CONTEXT.md exists):**

Use AskUserQuestion:
- header: "No context"
- question: "No CONTEXT.md found for Phase {X}. Plans will use research and requirements only — your design preferences won't be included. Continue or capture context first?"
- options:
  - "Continue without context" — Plan using research + requirements only
  - "Run discuss-phase first" — Capture design decisions before planning

If "Continue without context": Proceed to step 5.
If "Run discuss-phase first": Display `/gmd:discuss-phase {X}` and exit workflow.

## 5. Handle Research

**Skip if:** `--gaps` flag, `--skip-research` flag, or `research_enabled` is false (from init) without `--research` override.

**If `has_research` is true (from init) AND no `--research` flag:** Use existing, skip to step 6.

**High-research tier:** If `--high-research` flag is present, pass it to the researcher spawn. If `--high-research` is not explicitly set, the researcher uses auto-escalation heuristics (novelty, 3+ dependencies, competing approaches) to determine whether to escalate to high research.

**Profile check:** If model profile is 'budget' (from config.json), high research falls back to normal research even if the flag is set. Budget profiles prioritize speed over depth.

**If RESEARCH.md missing OR `--research` flag:**

Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► RESEARCHING PHASE {X}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

◆ Spawning researcher...
```

### Spawn gmd-phase-researcher

```bash
PHASE_DESC=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" roadmap get-phase "${PHASE}" | jq -r '.section')
```

Research prompt (inject `VAULT_CONTEXT_BLOCK` then `CODE_MAP_CONTEXT_BLOCK` immediately before `<files_to_read>`; omit each entirely when empty):

```markdown
<objective>
Research how to implement Phase {phase_number}: {phase_name}
Answer: "What do I need to know to PLAN this phase well?"
</objective>

{VAULT_CONTEXT_BLOCK}

{CODE_MAP_CONTEXT_BLOCK}

<files_to_read>
- {context_path} (USER DECISIONS from /gmd:discuss-phase)
- {requirements_path} (Project requirements)
- {state_path} (Project decisions and history)
</files_to_read>

<additional_context>
**Phase description:** {phase_description}
**Phase requirement IDs (MUST address):** {phase_req_ids}

**Project instructions:** Read ./CLAUDE.md if exists — follow project-specific guidelines
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — read SKILL.md files, research should account for project skill patterns

**Research tier:** {normal | high-research}
If high-research: Use NotebookLM integration for deep synthesis (see gmd-phase-researcher high-research tier)
</additional_context>

<output>
Write to: {phase_dir}/{phase_num}-RESEARCH.md
</output>
```

```
Task(
  prompt=research_prompt,
  subagent_type="gmd-phase-researcher",
  model="{researcher_model}",
  description="Research Phase {phase}"
)
```

### Handle Researcher Return

- **`## RESEARCH COMPLETE`:** Display confirmation, continue to step 6
- **`## RESEARCH BLOCKED`:** Display blocker, offer: 1) Provide context, 2) Skip research, 3) Abort

## 5.5. Create Validation Strategy

MANDATORY unless `nyquist_validation_enabled` is false.

```bash
grep -l "## Validation Architecture" "${PHASE_DIR}"/*-RESEARCH.md 2>/dev/null
```

**If found:**
1. Read template: `C:/Users/Christopher/.claude/get-magic-done/templates/VALIDATION.md`
2. Write to `${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md` (use Write tool)
3. Fill frontmatter: `{N}` → phase number, `{phase-slug}` → slug, `{date}` → current date
4. Verify:
```bash
test -f "${PHASE_DIR}/${PADDED_PHASE}-VALIDATION.md" && echo "VALIDATION_CREATED=true" || echo "VALIDATION_CREATED=false"
```
5. If `VALIDATION_CREATED=false`: STOP — do not proceed to Step 6
6. If `commit_docs`: `commit-docs "docs(phase-${PHASE}): add validation strategy"`

**If not found:** Warn and continue — plans may fail Dimension 8.

## Post-Workflow Vault Extraction (J4)

After RESEARCH.md is produced by the researcher agent, extract knowledge candidates to `.vault/Knowledge/_inbox/`.

```bash
# Only runs if RESEARCH.md was actually created (research is optional at Level 0)
# Mode-aware: ${PHASES_DIR} resolved at Step 0 to .planning/phases (sequential) or .planning/milestones/<slug>/phases (parallel).
if [[ -f "${PHASES_DIR}/${PHASE}/${PHASE}-RESEARCH.md" ]]; then
  # Locate config (Phase 17 idiom)
  HAS_CFG=""
  if [[ -f get-magic-done/config.json ]]; then HAS_CFG="get-magic-done/config.json"
  elif [[ -f config.json ]]; then HAS_CFG="config.json"
  fi

  # Gate on components.obsidian.enabled
  if [[ -z "$HAS_CFG" ]] || [[ "$(jq -r '.components.obsidian.enabled // false' "$HAS_CFG" 2>/dev/null)" != "true" ]]; then
    echo "[J4] vault-extract-knowledge skipped: obsidian component disabled" >&2
  else
    node bin/gmd-tools.cjs vault-extract-knowledge \
      --trigger J4 \
      --source-files "${PHASES_DIR}/${PHASE}/${PHASE}-RESEARCH.md" \
      --caller plan-phase \
      --phase "${PHASE}" \
    || echo "[J4] extraction returned non-zero — continuing; check .vault/_logs/" >&2
  fi
fi
```

**Flag-form rule (load-bearing):** every flag uses space separator. `--trigger J4`, NOT `--trigger=J4`. `--source-files "<path>"`, NOT `--source=<path>`. The parseAllFlags tokenizer at bin/gmd-tools.cjs:182 silently drops equals-form tokens — hooks would appear to run but extract nothing.

**Failure is non-fatal.** Extraction is additive enrichment; if it fails, the planning workflow still succeeds.

## 6. Check Existing Plans

```bash
ls "${PHASE_DIR}"/*-PLAN.md 2>/dev/null
```

**If exists:** Offer: 1) Add more plans, 2) View existing, 3) Replan from scratch.

## 7. Use Context Paths from INIT

Extract from INIT JSON:

```bash
STATE_PATH=$(printf '%s\n' "$INIT" | jq -r '.state_path // empty')
ROADMAP_PATH=$(printf '%s\n' "$INIT" | jq -r '.roadmap_path // empty')
REQUIREMENTS_PATH=$(printf '%s\n' "$INIT" | jq -r '.requirements_path // empty')
RESEARCH_PATH=$(printf '%s\n' "$INIT" | jq -r '.research_path // empty')
VERIFICATION_PATH=$(printf '%s\n' "$INIT" | jq -r '.verification_path // empty')
UAT_PATH=$(printf '%s\n' "$INIT" | jq -r '.uat_path // empty')
CONTEXT_PATH=$(printf '%s\n' "$INIT" | jq -r '.context_path // empty')
```

## 7.5. Verify Nyquist Artifacts

Skip if `nyquist_validation_enabled` is false.

```bash
VALIDATION_EXISTS=$(ls "${PHASE_DIR}"/*-VALIDATION.md 2>/dev/null | head -1)
```

If missing and Nyquist enabled — ask user:
1. Re-run: `/gmd:plan-phase {PHASE} --research`
2. Disable Nyquist in config
3. Continue anyway (plans fail Dimension 8)

Proceed to Step 8 only if user selects 2 or 3.

## 7.7. Budget Check (D14)

<step name="budget_check">
Before spawning the planner subagent, estimate the vault token budget using the scope-sized heuristic wired in Plan 19-01.

**Inputs:**
- `PLAN_COUNT` — number of plans being created this phase. Default to `plan_count` from phase context. If planning a single plan directly (PRD express path or single-plan phase), this is 1.
- `CROSS_SCOPE_COUNT` — number of HIGH/MEDIUM overlap hits from the vault-orient output. Extract from `VAULT_ORIENT_RAW` by counting `in_scope_notes` entries whose `overlap` field is `high` or `medium`. Default to 0 when vault was skipped or returned empty.

**Run budget estimation:**

```bash
BUDGET_ESTIMATE=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" vault-budget estimate \
  --orchestrator planner \
  --plan-count "${PLAN_COUNT}" \
  --cross-scope-count "${CROSS_SCOPE_COUNT}" 2>/dev/null || echo '{"error":"budget estimation failed"}')
```

Budget formula (from D14): `5000 + 2000 × plan_count + 500 × cross_scope_hit_count`. Ceiling for planner: 30K.

**Branching:**

1. **If estimate exceeds 30K ceiling** (`partition: true` in output):
   - Auto-partition into subagents — one per plan (or one per PLAN group if `plan_count > 5`).
   - Each subagent receives the `<vault_context>` block + its specific plan scope.
   - Main session composes the final PLAN artifact from subagent synthesis only (AGENT-03 context discipline).
   - Log structured event:
     ```
     {"event":"budget_exceeded","orchestrator":"gmd-planner","estimated":<N>,"budget":30000,"partitioned_into":<K>}
     ```
   - Stamp final artifact frontmatter:
     ```yaml
     partitioned: true
     subagent_count: <K>
     ```

2. **If estimate is under ceiling** (`partition: false`):
   - Single planner agent runs normally (current behavior; continue to Step 8).

3. **If budget estimation fails** (vault-budget returned error, or `.error` field set):
   - Proceed with single-agent mode. Do NOT block the workflow.
   - Log: `{"event":"budget_estimation_failed","orchestrator":"gmd-planner","fallback":"single-agent"}`
</step>

## 7.8. Critic Review — Planning Context (CRIT-WIRE-02)

<!-- critic-gate: architectural-decision (CRIT-WIRE-02 / Phase 51-02) -->
<step name="critic_review_planning_context" priority="late">
This is a **high-signal architectural-decision gate** per CRIT-WIRE-02. Lead has just absorbed research + requirements + context + nyquist artifacts + budget check, and is about to instantiate the planner with the locked planning context. This is the moment where critic catches "wrong vehicle" / "schema-design foreclosure" / "dispatcher-coupling" defects — TD-07 publish-boundary catch was at exactly this gate shape.

**D6 contract:** dispatcher is called UNCONDITIONALLY (no `isEnabled('critic')` workflow-side wrapper); dispatcher honors gate internally and returns no-op envelope if disabled.

**D2 contract:** library SoT imported directly via `require()` — zero Claude Code Task-tool coupling in the workflow source.

**Construct caller-injected `spawnSubagent` wrapper** that uses the Claude Code `Task` tool to invoke `subagent_type='gmd-critic'` (caller-injected per D2; v1.5.7 Codex CLI adapter swaps in its own spawn primitive without changing this dispatcher call site):

```javascript
const { dispatchCritic } = require('${CLAUDE_PLUGIN_ROOT}/bin/lib/critic-dispatch.js');

const spawnSubagent = async ({ agent, prompt, cross_model }) => {
  // Inline a Task() invocation that spawns gmd-critic with the prompt object.
  // Returns { verdict, alternative_argument, missed_concerns, escalate_to_human,
  //           confidence, tokens_input, tokens_output, notes }.
  return await Task({
    subagent_type: agent,                    // 'gmd-critic'
    prompt: JSON.stringify(prompt),
    description: `gmd-critic review (${prompt.workflow})`,
  });
};

// CRIT-01/02/03 (Plan 66-05): milestone-scoped affects_paths in parallel mode.
// MODE + SLUG + PHASES_DIR + REQS_PATH + ROADMAP_PATH sourced from Step 0 init JSON.
// affects_reqs honors active-milestone-only scoping in parallel mode — PHASE_REQ_IDS
// already comes from milestone-scoped ROADMAP.md (Plan 66-02 made the path lookup
// mode-aware), so the value reaching dispatchCritic is automatically scoped.
const affects_paths = (MODE === 'parallel')
  ? [`${PHASE_DIR}/*-PLAN.md`, REQS_PATH, ROADMAP_PATH]
  : [`${PHASE_DIR}/*-PLAN.md`];

// GROUND-03 (v1.8.2.5): caller-resolved grounding bundle for the critic's unconditional read mandate.
// SPEC_PATH resolves the active milestone SPEC (parallel: milestones/<slug>/<slug>-SPEC.md;
// sequential: .planning/milestones/<active>-SPEC.md — composed in Step 0 path-lookups).
// Library does NO resolution (D2) — caller supplies. files_to_read is threaded into the
// prompt object by dispatchCritic (Plan 02 conditional spread); the spawnSubagent wrapper
// JSON.stringifies it, so the agent sees a files_to_read key per Plan 01's read mandate.
const files_to_read = [
  SPEC_PATH,                                  // active-milestone SPEC (caller-resolved <active>)
  '.planning/PROJECT.md',                     // project invariants
  '.planning/specs/gmd-critic-protocol.md',  // protocol anchor (envelope source-of-record)
  ...affects_paths,                           // the PLAN.md glob (+ REQS/ROADMAP in parallel)
];

// <!-- critic-gate: architectural-decision (CRIT-WIRE-02 / Phase 51-02; inline-proximity anchor) -->
const envelope = await dispatchCritic({
  spawnSubagent: spawnSubagent,
  decision_point: "Planning context shape — ready to spawn planner with current REQ list + research + nyquist + context?",
  lead_recommendation: "<one-line summary of planning_context shape: REQ IDs + research path + context path + validation path>",
  lead_rationale: "<why this shape — e.g., 'all REQs covered + research surfaced no novel architectural risk + context locks decisions + validation strategy ready'>",
  workflow: '/gmd:plan-phase',
  phase: PHASE,                              // e.g., '51-workflow-integration-...'
  affects_paths,
  affects_reqs: PHASE_REQ_IDS,               // array from init JSON phase_req_ids (active-milestone-scoped in parallel via Plan 66-02 mode-aware lookup)
  files_to_read,                              // GROUND-03: grounding bundle for the critic
});
```

**Surface critic output in user-visible menu copy** when `envelope.verdict !== 'noop'`. Include the literal text `decision_id: ${envelope.decision_id}` in the surfaced banner (per CRIT-DISP-02 — UUID is the join key for future CRIT-TELM-02 correlation):

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► CRITIC REVIEW — PLANNING CONTEXT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

verdict:           ${envelope.verdict}             (endorse | dissent | refine)
decision_id:       ${envelope.decision_id}
confidence:        ${envelope.confidence}
alternative:       ${envelope.alternative_argument}
missed concerns:   ${envelope.missed_concerns.join(', ')}
escalate_to_human: ${envelope.escalate_to_human}
```

**Reciprocal-marker emission** (CRIT-WIRE-05 / CRIT-SCHEMA-03): when `envelope.verdict !== 'noop'` AND lead modifies the planning_context per critic recommendation, the planner's spawned PLAN.md output MUST carry the reciprocal marker. The executing agent injects the marker as an HTML comment in the PLAN.md frontmatter (at the top of the file, immediately before the closing `---`) so the marker is preserved in the consuming artifact per CRIT-SCHEMA-03 and round-trip-joinable to the NDJSON `decision_id` for CRIT-TELM-02:

```markdown
---
phase: <phase>
plan: <NN>
type: execute
...
<!-- critic-decision: ${envelope.decision_id} -->
---
```

When `envelope.verdict === 'noop'` (dispatcher disabled per D6) OR lead does NOT integrate critic's alternative, NO marker is emitted — the marker only emits when the critic-influenced path is actually chosen.

**Continue to Step 8** regardless of verdict (critic informs, lead decides).
</step>

## 7.9. Critic Review — REQ Add/Remove Delta (CRIT-WIRE-02 / req-add-remove gate)

<!-- critic-gate: req-add-remove (CRIT-WIRE-02 / Phase 51-02; folded — see comment) -->
<step name="critic_review_req_delta" priority="late">
**REQ-add/remove gate decision: FOLDED into architectural-decision gate (Step 7.8) per planner judgment.**

Per CONTEXT.md "Claude's Discretion / Exact gate selection per workflow" + plan 51-02 Task 2 acceptance criterion: this gate is FOLDED unless research / nyquist / context surfaced a REQ delta vs roadmap. The folded-anchor pattern is permitted by Phase 51 Plan E (Wave 2 audit) — `critic-gate: req-add-remove` anchor presence (separate OR folded) satisfies the CRIT-AUDIT-01 anchor-presence assertion. The CRIT-WIRE-02 audit-criterion is gate-presence verified by the named anchor; if no REQ delta surfaces, the audit treats anchor presence as a documented negative finding rather than a missing gate.

**Runtime check (executing agent):** did research / nyquist / context surface a REQ delta vs roadmap?

1. **If NO (no REQ delta):** Folded into the architectural-decision gate above (Step 7.8). The `affects_reqs: PHASE_REQ_IDS` parameter on Step 7.8's `dispatchCritic` call already conveys the REQ scope to the critic. NO additional dispatch call is required. Proceed to Step 8.

2. **If YES (REQ delta detected — e.g., research recommends adding a REQ not in roadmap, or scope creep at plan-time forces removal):** Emit a SEPARATE `dispatchCritic` call here using the SAME `spawnSubagent` wrapper as Step 7.8:

   ```javascript
   // CRIT-01/02/03 (Plan 66-05): affects_paths already mode-aware via Step 0
   // (REQS_PATH + ROADMAP_PATH resolve to milestones/<slug>/ in parallel mode;
   // root .planning/ in sequential mode — byte-identical to v1.5.5 baseline by
   // composition). affects_reqs (REQ_DELTA_IDS) is the delta list for THIS
   // phase only — active-milestone-scoped by construction (parent REQS_PATH
   // is the active milestone's REQUIREMENTS.md in parallel mode).
   // GROUND-03 (v1.8.2.5): caller-resolved grounding bundle (same shape as Step 7.8).
   // SPEC_PATH composed in Step 0 path-lookups (caller-resolved <active>; library does
   // no resolution — D2). The affects_paths here is the REQ-delta array below.
   const files_to_read = [
     SPEC_PATH,                              // active-milestone SPEC (caller-resolved <active>)
     '.planning/PROJECT.md',                 // project invariants
     '.planning/specs/gmd-critic-protocol.md',  // protocol anchor
     `${PHASE_DIR}/*-PLAN.md`, REQS_PATH, ROADMAP_PATH,  // this branch's affects_paths
   ];

   // <!-- critic-gate: req-add-remove (CRIT-WIRE-02 / Phase 51-02; inline-proximity anchor for YES branch) -->
   const reqDeltaEnvelope = await dispatchCritic({
     spawnSubagent: spawnSubagent,
     decision_point: "REQ delta vs roadmap — add/remove REQs for this phase?",
     lead_recommendation: "<add: [REQ-X, REQ-Y] | remove: [REQ-Z] | rationale>",
     lead_rationale: "<one-line rationale — e.g., 'research surfaced architectural concern requiring new REQ-X scope per critic R-pattern'>",
     workflow: '/gmd:plan-phase',
     phase: PHASE,
     affects_paths: [`${PHASE_DIR}/*-PLAN.md`, REQS_PATH, ROADMAP_PATH],  // mode-aware via Step 0 (CRIT-01)
     affects_reqs: REQ_DELTA_IDS,            // delta list (added + removed REQ IDs) — active-milestone-scoped (CRIT-02)
     files_to_read,                          // GROUND-03: grounding bundle for the critic
   });

   // Surface verdict + decision_id in user-visible menu copy when verdict !== 'noop'
   // (same banner shape as Step 7.8). When critic-influenced path chosen, emit
   // reciprocal `<!-- critic-decision: ${reqDeltaEnvelope.decision_id} -->` marker
   // in REQUIREMENTS.md (next to the new/removed REQ entry) per CRIT-WIRE-05.
   ```

**D6 contract:** UNCONDITIONAL (no `isEnabled('critic')` wrapper).
</step>

## 8. Spawn gmd-planner Agent

Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► PLANNING PHASE {X}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

◆ Spawning planner...
```

Planner prompt (inject `VAULT_CONTEXT_BLOCK` then `CODE_MAP_CONTEXT_BLOCK` immediately before `<files_to_read>`; omit each entirely when empty):

```markdown
<planning_context>
**Phase:** {phase_number}
**Mode:** {standard | gap_closure}

{VAULT_CONTEXT_BLOCK}

{CODE_MAP_CONTEXT_BLOCK}

<files_to_read>
- {state_path} (Project State)
- {roadmap_path} (Roadmap)
- {requirements_path} (Requirements)
- {context_path} (USER DECISIONS from /gmd:discuss-phase)
- {research_path} (Technical Research)
- {verification_path} (Verification Gaps - if --gaps)
- {uat_path} (UAT Gaps - if --gaps)
</files_to_read>

**Phase requirement IDs (every ID MUST appear in a plan's `requirements` field):** {phase_req_ids}

**Project instructions:** Read ./CLAUDE.md if exists — follow project-specific guidelines
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — read SKILL.md files, plans should account for project skill rules
</planning_context>

<downstream_consumer>
Output consumed by /gmd:execute-phase. Plans need:
- Frontmatter (wave, depends_on, files_modified, autonomous)
- Tasks in XML format
- Verification criteria
- must_haves for goal-backward verification
</downstream_consumer>

<quality_gate>
- [ ] PLAN.md files created in phase directory
- [ ] Each plan has valid frontmatter
- [ ] Tasks are specific and actionable
- [ ] Dependencies correctly identified
- [ ] Waves assigned for parallel execution
- [ ] must_haves derived from phase goal
</quality_gate>
```

```
Task(
  prompt=filled_prompt,
  subagent_type="gmd-planner",
  model="{planner_model}",
  description="Plan Phase {phase}"
)
```

## 9. Handle Planner Return

- **`## PLANNING COMPLETE`:** Display plan count. If `--skip-verify` or `plan_checker_enabled` is false (from init): skip to step 13. Otherwise: step 10.
- **`## CHECKPOINT REACHED`:** Present to user, get response, spawn continuation (step 12)
- **`## PLANNING INCONCLUSIVE`:** Show attempts, offer: Add context / Retry / Manual

## 10. Spawn gmd-plan-checker Agent

Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► VERIFYING PLANS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

◆ Spawning plan checker...
```

**Post-planning code-map rebuild (WIRE-01 build (b)):** the plans now exist — rebuild the slice as `CODE_MAP_CONTEXT_BLOCK_V2` from the union of the just-written plans' `files_modified` frontmatter. This is a SECOND build because the preflight build (a) predates the plans (`files_modified` is the planner's OUTPUT — it did not exist at preflight):

```bash
FILES_CSV=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" phase-plan-index "${PHASE}" 2>/dev/null | jq -r '[.plans[].files_modified // [] | .[]] | unique | join(",")')
CODE_MAP_CONTEXT_BLOCK_V2=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" code-slice --files "${FILES_CSV}" --format block 2>/dev/null || true)
```

Inject `CODE_MAP_CONTEXT_BLOCK_V2` immediately AFTER `<vault_context>`, BEFORE `<files_to_read>`, in the checker prompt below AND the revision prompt (Step 12) — same empty-omit rule (never inject an empty `<code_map_context></code_map_context>`).

Checker prompt (inject `VAULT_CONTEXT_BLOCK` then `CODE_MAP_CONTEXT_BLOCK_V2` immediately before `<files_to_read>`; omit each entirely when empty):

```markdown
<verification_context>
**Phase:** {phase_number}
**Phase Goal:** {goal from ROADMAP}

{VAULT_CONTEXT_BLOCK}

{CODE_MAP_CONTEXT_BLOCK_V2}

<files_to_read>
- {PHASE_DIR}/*-PLAN.md (Plans to verify)
- {roadmap_path} (Roadmap)
- {requirements_path} (Requirements)
- {context_path} (USER DECISIONS from /gmd:discuss-phase)
- {research_path} (Technical Research — includes Validation Architecture)
</files_to_read>

**Phase requirement IDs (MUST ALL be covered):** {phase_req_ids}

**Project instructions:** Read ./CLAUDE.md if exists — verify plans honor project guidelines
**Project skills:** Check .claude/skills/ or .agents/skills/ directory (if either exists) — verify plans account for project skill rules
</verification_context>

<expected_output>
- ## VERIFICATION PASSED — all checks pass
- ## ISSUES FOUND — structured issue list
</expected_output>
```

```
Task(
  prompt=checker_prompt,
  subagent_type="gmd-plan-checker",
  model="{checker_model}",
  description="Verify Phase {phase} plans"
)
```

## 11. Handle Checker Return

- **`## VERIFICATION PASSED`:** Display confirmation, proceed to step 13.
- **`## ISSUES FOUND`:** Display issues, check iteration count, proceed to step 12.

## 12. Revision Loop (Max 3 Iterations)

Track `iteration_count` (starts at 1 after initial plan + check).

**If iteration_count < 3:**

Display: `Sending back to planner for revision... (iteration {N}/3)`

<!-- critic-gate: deviation-from-recommendation (CRIT-WIRE-02 / Phase 51-02) -->
<step name="critic_review_revision_decision" priority="late">
This is a **high-signal deviation-from-recommendation gate** per CRIT-WIRE-02. Checker has flagged issues AND lead is about to send revision context back to the planner. Critic catches "checker-recommended fix is wrong" or "fix-approach forecloses something downstream" defects. Distinct from the planner-spawn gate (Step 7.8) because the revision context is asymmetric (checker-driven, not lead-driven).

**D6 contract:** UNCONDITIONAL invocation (no `isEnabled('critic')` workflow-side wrapper).
**D2 contract:** library SoT imported via `require()` — same pattern as Step 7.8.

Reuse the same caller-injected `spawnSubagent` wrapper pattern documented in Step 7.8 (Task tool → `subagent_type='gmd-critic'`):

```javascript
const { dispatchCritic } = require('${CLAUDE_PLUGIN_ROOT}/bin/lib/critic-dispatch.js');

// CRIT-01/02/03 (Plan 66-05): milestone-scoped affects_paths in parallel mode.
// Same pattern as Step 7.8 architectural-decision gate — PHASE_DIR is already
// mode-aware (init JSON resolves it to milestones/<slug>/phases/... in parallel
// per Plan 66-02). Parallel mode additionally surfaces REQS_PATH + ROADMAP_PATH
// since revision may touch REQ scope. Sequential mode byte-identical to v1.5.5
// baseline. affects_reqs (REVISION_AFFECTED_REQ_IDS) is active-milestone-scoped
// by construction (delta is computed from this phase's REQ list only).
const affects_paths = (MODE === 'parallel')
  ? [`${PHASE_DIR}/*-PLAN.md`, REQS_PATH, ROADMAP_PATH]
  : [`${PHASE_DIR}/*-PLAN.md`];

// GROUND-03 (v1.8.2.5): caller-resolved grounding bundle (same shape as Step 7.8).
// SPEC_PATH composed in Step 0 path-lookups (caller-resolved <active>; library does
// no resolution — D2). affects_paths is the mode-aware array computed just above.
const files_to_read = [
  SPEC_PATH,                                  // active-milestone SPEC (caller-resolved <active>)
  '.planning/PROJECT.md',                     // project invariants
  '.planning/specs/gmd-critic-protocol.md',  // protocol anchor
  ...affects_paths,                           // this gate's affects_paths
];

// <!-- critic-gate: deviation-from-recommendation (CRIT-WIRE-02 / Phase 51-02; inline-proximity anchor) -->
const revisionEnvelope = await dispatchCritic({
  spawnSubagent: spawnSubagent,
  decision_point: "Checker flagged issues — accept checker's recommended fix or override?",
  lead_recommendation: "<issue summary + accept|override decision>",
  lead_rationale: "<one-line rationale — e.g., 'checker-recommended fix aligns with REQ-X intent' OR 'override: checker fix forecloses downstream Plan-Y dependency'>",
  workflow: '/gmd:plan-phase',
  phase: PHASE,
  affects_paths,
  affects_reqs: REVISION_AFFECTED_REQ_IDS,    // REQ IDs touched by the revision (active-milestone-scoped)
  files_to_read,                              // GROUND-03: grounding bundle for the critic
});
```

**Surface verdict + decision_id in user-visible menu copy when `revisionEnvelope.verdict !== 'noop'`** (same banner shape as Step 7.8 — include literal `decision_id: ${revisionEnvelope.decision_id}`).

**Reciprocal-marker emission** (CRIT-WIRE-05): when critic dissents AND lead accepts critic's alternative (overrides checker per critic recommendation), the revision Task() prompt MUST be augmented to instruct the planner to insert `<!-- critic-decision: ${revisionEnvelope.decision_id} -->` in the revised PLAN.md task block (next to the affected task or in PLAN.md frontmatter — same shape as Step 7.8's reciprocal marker):

```markdown
<!-- critic-decision: ${revisionEnvelope.decision_id} -->
<task type="auto">
  <name>Revised task addressing critic-recommended override</name>
  ...
</task>
```

When `revisionEnvelope.verdict === 'noop'` (dispatcher disabled) OR lead accepts checker's recommendation as-is (no critic-influenced override), NO marker is emitted.

**Continue to revision Task() invocation below regardless of verdict** (critic informs, lead decides; revision still proceeds).
</step>

Revision prompt (inject `VAULT_CONTEXT_BLOCK` then `CODE_MAP_CONTEXT_BLOCK_V2` immediately before `<files_to_read>`; omit each entirely when empty — `CODE_MAP_CONTEXT_BLOCK_V2` is the Step-10 post-planning rebuild from the plans' `files_modified` union):

```markdown
<revision_context>
**Phase:** {phase_number}
**Mode:** revision

{VAULT_CONTEXT_BLOCK}

{CODE_MAP_CONTEXT_BLOCK_V2}

<files_to_read>
- {PHASE_DIR}/*-PLAN.md (Existing plans)
- {context_path} (USER DECISIONS from /gmd:discuss-phase)
</files_to_read>

**Checker issues:** {structured_issues_from_checker}
</revision_context>

<instructions>
Make targeted updates to address checker issues.
Do NOT replan from scratch unless issues are fundamental.
Return what changed.
</instructions>
```

```
Task(
  prompt=revision_prompt,
  subagent_type="gmd-planner",
  model="{planner_model}",
  description="Revise Phase {phase} plans"
)
```

After planner returns -> spawn checker again (step 10), increment iteration_count.

**If iteration_count >= 3:**

Display: `Max iterations reached. {N} issues remain:` + issue list

Offer: 1) Force proceed, 2) Provide guidance and retry, 3) Abandon

## 13. Present Final Status

Route to `<offer_next>` OR `auto_advance` depending on flags/config.

## 14. Auto-Advance Check

Check for auto-advance trigger:

1. Parse `--auto` flag from $ARGUMENTS
2. **Sync chain flag with intent** — if user invoked manually (no `--auto`), clear the ephemeral chain flag from any previous interrupted `--auto` chain. This does NOT touch `workflow.auto_advance` (the user's persistent settings preference):
   ```bash
   if [[ ! "$ARGUMENTS" =~ --auto ]]; then
     node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" config-set workflow._auto_chain_active false 2>/dev/null
   fi
   ```
3. Read both the chain flag and user preference:
   ```bash
   AUTO_CHAIN=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" config-get workflow._auto_chain_active 2>/dev/null || echo "false")
   AUTO_CFG=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" config-get workflow.auto_advance 2>/dev/null || echo "false")
   ```

**If `--auto` flag present OR `AUTO_CHAIN` is true OR `AUTO_CFG` is true:**

Display banner:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► AUTO-ADVANCING TO EXECUTE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Plans ready. Launching execute-phase...
```

Launch execute-phase using the Skill tool to avoid nested Task sessions (which cause runtime freezes due to deep agent nesting):
```
Skill(skill="gmd:execute-phase", args="${PHASE} --auto --no-transition")
```

The `--no-transition` flag tells execute-phase to return status after verification instead of chaining further. This keeps the auto-advance chain flat — each phase runs at the same nesting level rather than spawning deeper Task agents.

**Handle execute-phase return:**
- **PHASE COMPLETE** → Display final summary:
  ```
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
   GMD ► PHASE ${PHASE} COMPLETE ✓
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  Auto-advance pipeline finished.

  Next: /gmd:discuss-phase ${NEXT_PHASE} --auto
  ```
- **GAPS FOUND / VERIFICATION FAILED** → Display result, stop chain:
  ```
  Auto-advance stopped: Execution needs review.

  Review the output above and continue manually:
  /gmd:execute-phase ${PHASE}
  ```

**If neither `--auto` nor config enabled:**
Route to `<offer_next>` (existing behavior).

</process>

<offer_next>
Output this markdown directly (not as a code block):

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 GMD ► PHASE {X} PLANNED ✓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

**Phase {X}: {Name}** — {N} plan(s) in {M} wave(s)

| Wave | Plans | What it builds |
|------|-------|----------------|
| 1    | 01, 02 | [objectives] |
| 2    | 03     | [objective]  |

Research: {Completed | Used existing | Skipped}
Verification: {Passed | Passed with override | Skipped}

───────────────────────────────────────────────────────────────

## ▶ Next Up

**Execute Phase {X}** — run all {N} plans

/gmd:execute-phase {X}

<sub>/clear first → fresh context window</sub>

───────────────────────────────────────────────────────────────

**Also available:**
- cat .planning/phases/{phase-dir}/*-PLAN.md — review plans (sequential mode; parallel: cat .planning/milestones/<slug>/phases/{phase-dir}/*-PLAN.md)
- /gmd:plan-phase {X} --research — re-research first

───────────────────────────────────────────────────────────────
</offer_next>

<success_criteria>
- [ ] .planning/ directory validated
- [ ] Phase validated against roadmap
- [ ] Phase directory created if needed
- [ ] CONTEXT.md loaded early (step 4) and passed to ALL agents
- [ ] Research completed (unless --skip-research or --gaps or exists)
- [ ] gmd-phase-researcher spawned with CONTEXT.md
- [ ] Existing plans checked
- [ ] gmd-planner spawned with CONTEXT.md + RESEARCH.md
- [ ] Plans created (PLANNING COMPLETE or CHECKPOINT handled)
- [ ] gmd-plan-checker spawned with CONTEXT.md
- [ ] Verification passed OR user override OR max iterations with user decision
- [ ] User sees status between agent spawns
- [ ] User knows next steps
</success_criteria>
