<purpose>
Orchestrate team-lead agents to perform team-scaled parallel codebase analysis and produce structured documents in .planning/codebase/

Each team lead receives a persona assignment, dynamically decides sub-agent count based on codebase size, dispatches gmd-codebase-mapper sub-agents for directory shards, and synthesizes an INDEX file with Obsidian wikilinks.

Output: .planning/codebase/ folder with sharded analysis files, 4 persona INDEX files, and a CODEBASE.base root view.
</purpose>

<philosophy>
**Why team-lead architecture:**
- Team leads dynamically decide sub-agent count (no fixed tiers)
- Directory-sharded work avoids context contamination between sub-agents
- Each team lead synthesizes findings into a navigable INDEX with wikilinks
- Root CODEBASE.base provides filterable cross-persona queries via Obsidian
- Scales from small repos (1-2 sub-agents per persona) to monorepos (6-10 per persona)

**Graceful degradation:**
- Very small codebases or --simple flag falls back to single-agent-per-persona pattern
- Team-lead failures retry once, then fall back to questioning-only flow
- No dead ends -- brownfield flag preserved for manual re-invocation

**Document quality over length:**
Include enough detail to be useful as reference. Prioritize practical examples (especially code patterns) over arbitrary brevity.

**Always include file paths:**
Documents are reference material for Claude when planning/executing. Always include actual file paths formatted with backticks: `src/services/user.ts`.
</philosophy>

<process>

<step name="init_context" priority="first">
Load codebase mapping context:

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

Extract from init JSON: `mapper_model`, `commit_docs`, `codebase_dir`, `existing_maps`, `has_maps`, `codebase_dir_exists`.
</step>

<step name="check_existing">
Check if .planning/codebase/ already exists using `has_maps` from init context.

If `codebase_dir_exists` is true:
```bash
ls -la .planning/codebase/
```

**If exists:**

```
.planning/codebase/ already exists with these documents:
[List files found]

What's next?
1. Refresh - Delete existing and remap codebase
2. Update - Keep existing, only update specific documents
3. Skip - Use existing codebase map as-is
```

Wait for user response.

If "Refresh": Delete .planning/codebase/ contents EXCEPT `_notes/` (judgment notes are committed durable content anchored to entity ids — the wiki is regenerable, notes are not; note staleness is handled by serve-time derivation, never by deletion), continue to create_structure
If "Update": Ask which documents to update, continue to determine_mode (filtered)
If "Skip": Exit workflow

**If doesn't exist:**
Continue to create_structure.
</step>

<step name="create_structure">
Create .planning/codebase/ directory:

```bash
mkdir -p .planning/codebase
```

Continue to determine_mode.
</step>

<step name="determine_mode">
Determine whether to use team-lead architecture or simple single-agent mode.

**Check for --simple flag or codebase size:**

```bash
# Count total code files (quick sizing)
TOTAL_FILES=$(find . -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.java" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/build/*" 2>/dev/null | wc -l)
echo "Total code files: $TOTAL_FILES"
```

**Decision:**
- If `--simple` flag passed explicitly: use simple mode (single agent per persona)
- If total code files < 50: use simple mode (team-lead overhead not worthwhile)
- Otherwise: use team-lead mode (default for brownfield)

**Simple mode:** Fall back to the original single-agent-per-persona pattern -- dispatch 4 gmd-codebase-mapper agents directly (one per persona: tech, arch, quality, concerns). Each agent writes documents directly to `.planning/codebase/`. No INDEX files, no sharding.

**Team-lead mode:** Continue to structural_pass.
</step>

<step name="structural_pass">
## The Two-Pass Boundary (structural → semantic)

The map is produced by **two passes** with an explicit boundary (Phase 81 / PASS):

1. **The structural pass (deterministic, LLM-token-FREE).** A pure Tree-sitter + filesystem walk that extracts the entity graph — file / function / class / export entities + their `{type, target_id}` edges — and emits a **byte-deterministic** `.planning/codebase/.structural.json`. This is the **extraction** leg. The LLM does NOT do extraction; the deterministic pass owns it.

2. **The semantic pass (LLM, synthesis-only).** The team-lead + gmd-codebase-mapper agents **CONSUME** `.planning/codebase/.structural.json` as their **entity index** and synthesize the human-facing Deep-Dive docs (invariants / responsibilities / change-rationale + the Phase-80 C4-doc frontmatter family). The semantic pass does NOT re-run Tree-sitter extraction — the structural pass already produced the entity index.

**Run the structural step (this step) BEFORE the semantic pass (`spawn_team_leads`).** The `.structural.json` it emits is the entity index the semantic pass reads.

```bash
# THE deterministic extraction leg — LLM-token-FREE. Emits
# .planning/codebase/.structural.json (Phase 81 / PASS contract; SC1 byte-deterministic).
node bin/gmd-tools.cjs map-structural
STRUCTURAL_RC=$?
```

- Exit 0 → `.planning/codebase/.structural.json` is written (the entity index).
- Exit 2 (`ESTRUCT_IO`) → a HARD engine error (broken pinned grammar/ABI). Surface it; do NOT proceed to the semantic pass with a missing/empty index.

### Flag gating — `--structural-only` / `--semantic-only` / full run (SC3)

The two passes are **independently invocable** (SC3 separability), and a full run **sequences** them:

| Invocation                | Structural step (this step)                          | Semantic pass (`spawn_team_leads`)                          |
| ------------------------- | ---------------------------------------------------- | ---------------------------------------------------------- |
| `--structural-only`       | **RUN** `map-structural`, then print minimal output and **STOP** | **SKIPPED** — no team-lead / LLM dispatch (free of LLM tokens) |
| `--semantic-only`         | **SKIP** — do NOT run `map-structural`; **ASSERT** `.planning/codebase/.structural.json` exists | **RUN** — dispatch team-leads with the existing `.structural.json` index |
| full run (no flag)        | **RUN** `map-structural` (this step)                 | **RUN** `spawn_team_leads` (SEQUENCED after the structural step) |

**`--structural-only` leg** — run the structural step above, print a minimal confirmation, and STOP. Do NOT spawn team-leads. This leg is **free of LLM tokens** (the structural pass is pure Tree-sitter + filesystem; no model call).

```bash
# --structural-only: deterministic extraction ONLY. No team-lead / semantic dispatch.
echo "structural-only: wrote .planning/codebase/.structural.json (no semantic pass dispatched)"
# STOP — do NOT continue to spawn_team_leads.
```

**`--semantic-only` leg** — SKIP the structural step (do NOT re-run `map-structural` — that would re-extract; SC2 forbids it). ASSERT the entity index already exists; fail fast with a clear message if absent, then proceed to `spawn_team_leads` consuming the existing index.

```bash
# --semantic-only: consume the EXISTING .structural.json — do NOT re-extract (SC2).
# This leg NEVER re-runs the structural extractor; it only asserts the index exists.
if [ ! -f .planning/codebase/.structural.json ]; then
  echo "ERROR: .planning/codebase/.structural.json not found." >&2
  echo "       Run \`/gmd:map-codebase --structural-only\` first (or a full run) to produce the structural entity index, then re-run --semantic-only." >&2
  exit 1
fi
# .structural.json present — proceed to spawn_team_leads, consuming the existing index.
```

**Full run (no flag)** — run the structural step (above), THEN continue to `spawn_team_leads` (the structural → semantic SEQUENCING). The structural pass is idempotent + byte-deterministic, so producing the index immediately before the semantic pass is safe.

Continue to spawn_team_leads (unless `--structural-only`, which STOPS here).
</step>

<step name="spawn_team_leads">
This is **the semantic pass** — the LLM synthesis leg. It runs AFTER the structural step (`structural_pass`) has produced `.planning/codebase/.structural.json` (the full run sequences both; `--semantic-only` asserts the index already exists). Each team-lead **consumes** that structural entity index rather than re-extracting — it is passed into each team-lead's `<files_to_read>` below.

Resolve model and spawn 4 team-lead agents (one per persona).

```bash
TEAM_LEAD_MODEL=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" resolve-model --complexity complex 2>/dev/null || echo "opus")
```

Use `--complexity complex` for team leads because they orchestrate sub-agents (higher blast radius).

**Team Lead 1: Tech Persona**

```
Task(
  subagent_type="gmd-mapper-team-lead",
  model="{TEAM_LEAD_MODEL}",
  run_in_background=true,
  description="Team lead: tech persona codebase analysis",
  prompt="Analyze codebase at {cwd} as the tech team lead.
  Persona: tech
  Codebase root: {cwd}
  Output directory: .planning/codebase/

  Your persona analyzes: technology stack, external integrations, dependency health.
  Sub-agent output files: TECH-{shard-slug}.md (or STACK.md + INTEGRATIONS.md for single-shard)
  INDEX file: TECH-INDEX.md

  <files_to_read>
  - .planning/codebase/.structural.json (the structural entity index — file/function/class/export entities + their {type,target_id} edges, emitted by the deterministic structural pass; CONSUME this as your entity index, do NOT re-extract)
  - agents/gmd-codebase-mapper.md (your sub-agent template)
  </files_to_read>"
)
```

**Team Lead 2: Architecture Persona**

```
Task(
  subagent_type="gmd-mapper-team-lead",
  model="{TEAM_LEAD_MODEL}",
  run_in_background=true,
  description="Team lead: arch persona codebase analysis",
  prompt="Analyze codebase at {cwd} as the arch team lead.
  Persona: arch
  Codebase root: {cwd}
  Output directory: .planning/codebase/

  Your persona analyzes: architecture patterns, layers, data flow, directory structure.
  Sub-agent output files: ARCHITECTURE-{shard-slug}.md (or ARCHITECTURE.md + STRUCTURE.md for single-shard)
  INDEX file: ARCHITECTURE-INDEX.md

  <files_to_read>
  - .planning/codebase/.structural.json (the structural entity index — file/function/class/export entities + their {type,target_id} edges, emitted by the deterministic structural pass; CONSUME this as your entity index, do NOT re-extract)
  - agents/gmd-codebase-mapper.md (your sub-agent template)
  </files_to_read>"
)
```

**Team Lead 3: Quality Persona**

```
Task(
  subagent_type="gmd-mapper-team-lead",
  model="{TEAM_LEAD_MODEL}",
  run_in_background=true,
  description="Team lead: quality persona codebase analysis",
  prompt="Analyze codebase at {cwd} as the quality team lead.
  Persona: quality
  Codebase root: {cwd}
  Output directory: .planning/codebase/

  Your persona analyzes: coding conventions, testing patterns, observability.
  Sub-agent output files: QUALITY-{shard-slug}.md (or CONVENTIONS.md + TESTING.md for single-shard)
  INDEX file: QUALITY-INDEX.md

  <files_to_read>
  - .planning/codebase/.structural.json (the structural entity index — file/function/class/export entities + their {type,target_id} edges, emitted by the deterministic structural pass; CONSUME this as your entity index, do NOT re-extract)
  - agents/gmd-codebase-mapper.md (your sub-agent template)
  </files_to_read>"
)
```

**Team Lead 4: Concerns Persona**

```
Task(
  subagent_type="gmd-mapper-team-lead",
  model="{TEAM_LEAD_MODEL}",
  run_in_background=true,
  description="Team lead: concerns persona codebase analysis",
  prompt="Analyze codebase at {cwd} as the concerns team lead.
  Persona: concerns
  Codebase root: {cwd}
  Output directory: .planning/codebase/

  Your persona analyzes: technical debt, known bugs, security, performance, fragile areas.
  Sub-agent output files: CONCERNS-{shard-slug}.md (or CONCERNS.md for single-shard)
  INDEX file: CONCERNS-INDEX.md

  <files_to_read>
  - .planning/codebase/.structural.json (the structural entity index — file/function/class/export entities + their {type,target_id} edges, emitted by the deterministic structural pass; CONSUME this as your entity index, do NOT re-extract)
  - agents/gmd-codebase-mapper.md (your sub-agent template)
  </files_to_read>"
)
```

Continue to collect_results.
</step>

<step name="collect_results">
Wait for all 4 team leads to complete.

Read each team lead's output to collect confirmations.

**Expected confirmation format from each team lead:**
```
## Team Lead Complete

**Persona:** {persona}
**Sub-agents dispatched:** {N}
**Sub-agents succeeded:** {N}
**Sub-agents failed:** {N}
**Files written:**
- `.planning/codebase/{PERSONA}-INDEX.md`
- `.planning/codebase/{PERSONA}-{slug1}.md`
- ...

Ready for orchestrator synthesis.
```

**Failure handling:**

Track team-lead results:
```
TEAM_LEAD_RESULTS=()
TEAM_LEAD_FAILURES=()
```

For each team lead:
- If it succeeded: record in TEAM_LEAD_RESULTS
- If it failed on first attempt: **retry ONCE**
  ```
  # Retry the failed team lead
  Task(
    subagent_type="gmd-mapper-team-lead",
    model="{TEAM_LEAD_MODEL}",
    description="RETRY: Team lead: {persona} persona codebase analysis",
    prompt="... same prompt as original ..."
  )
  ```
- If it fails on second attempt: record in TEAM_LEAD_FAILURES, continue with remaining personas

**If ALL team leads fail (both attempts):**

Fall back to questioning-only flow:
```
Codebase mapping failed. Likely causes: file permissions, unreadable paths, extremely large directories.

The brownfield flag has been preserved -- you can retry mapping later with `/gmd:map-codebase`.

Continuing with questioning-only flow for project initialization.
```

Preserve the brownfield flag in init state so user can re-invoke mapping manually.
Exit workflow (do not proceed to CODEBASE.base creation).

**If at least one team lead succeeded:**
Continue to generate_trails.
</step>

<step name="generate_trails">
## Code-trail generation (Phase 85 CTRAIL — ADDITIVE, fail-open)

After the semantic pass has authored the C4 wiki (`collect_results`) and BEFORE the Graph Reviewer (`lint_code_edges`), generate the auto **code-trails** over the structural call graph. A code-trail is a v1.6-TRAIL-conformant ordered walk through the wiki's Deep-Dive components — request-lifecycle (calls-reachability from the entry point), startup-sequence (a `depends-on` topo-sort), and integration-flow-per-seam (one per `Boundary-Interfaces/` seam, degrading to none when absent). Each trail carries a `see-also` CEDGE edge to its Deep-Dive targets, so running the trail pass HERE (ahead of the reviewer) means the reviewer sees the trail see-also links as part of the wiki under review.

This step runs ONLY when a real Deep-Dive tree exists (`[ -d .planning/codebase/Deep-Dive ]`, matching the reviewer-hook guard) — on a bare repo with no wiki it is a clean no-op. It is **fail-open**: the trail pass is purely ADDITIVE and NEVER blocks the mapper. The `map-trails` CLI itself catches every throw and exits 0; the workflow wraps the invocation in a `|| echo` swallow as a belt-and-suspenders guard, so a non-zero exit / throw is absorbed and the run continues.

**The governing invariant (SPEC §4, verbatim):** trail generation is ADDITIVE — it writes ONLY `.planning/codebase/Trails/<trail-slug>.md` + a `Trails/_index.md` surface, and NEVER rewrites a non-trail file. A generation failure SKIPS trails (records them in the engine's `skipped[]`, prints a `[TRAILS]` tally to stderr) and the mapper run continues. The trail generator is deterministic: re-running over an unchanged `.structural.json` produces byte-identical trail bodies (the only churn is the `last_regenerated_at` stamp).

```bash
# Code-trail pass — ADDITIVE + FAIL-OPEN. `map-trails` dispatches the 85-01 pure engine
# (bin/lib/map-trails.js): generateCodeTrails(root) -> writeTrails(root, result), writing
# ONLY .planning/codebase/Trails/<slug>.md + Trails/_index.md. The CLI catches every throw
# and exits 0; the `|| echo` swallow is a belt-and-suspenders guard so the mapper run
# continues regardless. Deep-Dive-guarded so a bare repo no-ops cleanly.
if [ -d .planning/codebase/Deep-Dive ]; then
  node bin/gmd-tools.cjs map-trails || echo "[TRAILS] continuing (fail-open)"
fi
```

Continue to lint_code_edges.
</step>

<step name="lint_code_edges">
## The Graph Reviewer surface (SC3 — fail-open end-of-run review)

After the semantic pass has authored the C4 wiki (`collect_results`), run the **Graph Reviewer** over the freshly generated code wiki. The reviewer is the ROADMAP SC3 verification surface: it surfaces the 7 charter violation classes — **dangling wikilinks, stale `file:line` pointers, claim/evidence mismatch, orphan Deep-Dive components, missing Boundary-Interfaces, unknown typed edges, malformed provenance** — ranked **critical / warning / info** in `.planning/codebase/.review-report.md`. The unknown-edge check (and the object-form edge handling) still rides `lintCodeWikiEdges` (Phase 82) underneath. Findings are **surfaced for review, never silently rewritten**, and the review **never blocks the mapper** (fail-open is the governing invariant).

This step runs ONLY when a C4 wiki was actually produced (a `Deep-Dive` or `Boundary-Interfaces` tree exists under `.planning/codebase`), and it is **fail-open** — any non-zero exit / throw is swallowed and the run continues.

**Two-layer drive (the load-bearing contract is the same for both):** when a wiki exists, `.planning/codebase/.review-report.md` is produced/refreshed, and a reviewer failure NEVER blocks the run.

**(a) Deterministic baseline layer — ALWAYS runs (cheapest, mechanical-only, always fail-open).** A `node -e` idiom calls `reviewCodeWiki(".planning/codebase")` from `bin/lib/map-review.js` (Plan 84-01 — the 6 mechanical checks: dangling / stale / orphan / missing-boundary / unknown-edge / malformed-provenance) and writes a baseline `.review-report.md` with the severity-ranked findings + a load-bearing `## Checks Skipped` section. The whole thing is wrapped in try/catch + `|| echo "[REVIEW] continuing (fail-open)"` — the SAME idiom the 84-03 F3 arm validated yields shell exit 0:

```bash
# Graph Reviewer baseline — FAIL-OPEN. reviewCodeWiki runs the 6 mechanical checks
# and refreshes .review-report.md. A throw / non-zero exit is SWALLOWED; the mapper
# run continues. The reviewer NEVER rewrites a code-wiki doc — its ONLY write is the
# advisory .review-report.md.
if [ -d .planning/codebase/Deep-Dive ] || [ -d .planning/codebase/Boundary-Interfaces ]; then
  node -e '
    const fs = require("fs");
    const path = require("path");
    try {
      const { reviewCodeWiki } = require("./bin/lib/map-review.js");
      const root = ".planning/codebase";
      const { findings = [], skipped = [] } = reviewCodeWiki(root) || {};
      const bySev = { critical: [], warning: [], info: [] };
      for (const f of findings) (bySev[f.severity] || bySev.info).push(f);
      const sec = (title, arr) =>
        "## " + title + "\n\n" +
        (arr.length
          ? arr.map(f => "- [" + f.check + "] " + (f.source_note || "?") +
              ": " + (f.detail || f.target || "")).join("\n")
          : "_None_") + "\n";
      const skippedSec =
        "## Checks Skipped\n\n" +
        (skipped.length
          ? skipped.map(s => "- " + s.check + ": " + s.reason).join("\n")
          : "_None_") + "\n";
      const body =
        "---\n" +
        "generated_by: gmd-map-codebase (reviewCodeWiki baseline)\n" +
        "last_reviewed_at: " + new Date().toISOString() + "\n" +
        "wiki_root: " + root + "\n" +
        "findings:\n" +
        "  critical: " + bySev.critical.length + "\n" +
        "  warning: " + bySev.warning.length + "\n" +
        "  info: " + bySev.info.length + "\n" +
        "checks_skipped: " + skipped.length + "\n" +
        "---\n\n" +
        "# Code-Wiki Review Report\n\n" +
        "**" + bySev.critical.length + " critical / " + bySev.warning.length +
          " warning / " + bySev.info.length + " info / " + skipped.length + " skipped**\n\n" +
        "_Mechanical baseline (the 6 deterministic checks). For the full 7-check pass " +
          "(incl. claim/evidence judgment), run `/gmd:map-review`._\n\n" +
        sec("Critical", bySev.critical) + "\n" +
        sec("Warning", bySev.warning) + "\n" +
        sec("Info", bySev.info) + "\n" +
        skippedSec;
      fs.writeFileSync(path.join(root, ".review-report.md"), body);
      process.stderr.write("[REVIEW] " + bySev.critical.length + " critical / " +
        bySev.warning.length + " warning / " + bySev.info.length + " info / " +
        skipped.length + " skipped → .review-report.md\n");
    } catch (e) {
      // Fail-open: a reviewer hiccup must never abort the mapper.
      process.stderr.write("[REVIEW] review error (continuing fail-open): " + e.message + "\n");
    }
  ' || echo "[REVIEW] reviewCodeWiki returned non-zero — continuing (fail-open)"
fi
```

**(b) Full 7-check layer — the LLM claim/evidence pass.** The deterministic baseline above covers 6 of the 7 charter checks. The seventh — **claim/evidence mismatch** (a cited `file:line` that EXISTS and is non-blank but does NOT support the prose claim) — is irreducibly semantic and needs the LLM `gmd-map-reviewer` agent. Drive it one of two ways:

- **On-demand (the standalone surface):** the `/gmd:map-review` slash command (Plan 84-04) dispatches `gmd-map-reviewer` against the wiki, refreshing `.planning/codebase/.review-report.md` with the full 7-check, severity-ranked pass + the claim/evidence judgment. Run it after a map-codebase run to upgrade the baseline report.
- **Inline under the team-lead orchestrator (OPTIONAL):** when this workflow runs under the team-lead orchestrator (which has the `Task` tool), it MAY dispatch `gmd-map-reviewer` directly here for the full pass instead of leaving the mechanical baseline. If the orchestrator lacks `Task` (or the dispatch fails), it falls back to the deterministic baseline above. The agent is fail-open by construction — it exits 0 regardless of critical count and NEVER rewrites a wiki doc.

```
# OPTIONAL — only when this workflow runs under an orchestrator with the Task tool.
# A reviewer failure here is swallowed; the deterministic baseline report already exists.
Task(
  subagent_type="gmd-map-reviewer",
  description="End-of-run Graph Review of .planning/codebase",
  prompt="Review the code wiki at .planning/codebase and (re)emit .planning/codebase/.review-report.md.
          <files_to_read>
          - .planning/codebase/SCHEMA.md
          - .planning/codebase/STRUCTURAL-SCHEMA.md
          - .planning/codebase/.structural.json
          - bin/lib/map-review.js
          </files_to_read>
          Advisory-only, fail-open — do NOT block the mapper."
)
```

**The governing invariant (fail-open, verbatim):** the Graph Reviewer NEVER blocks the mapper, NEVER aborts the run, and NEVER rewrites a code-wiki doc — its ONLY write is the advisory `.planning/codebase/.review-report.md`. `reviewCodeWiki` never throws (each check is wrapped in try/catch → a `skipped[]` entry); the `gmd-map-reviewer` agent exits 0 regardless of how many critical findings it logs; and the end-of-run hook swallows any non-zero exit (`|| echo … continuing`). A reviewer crash, timeout, or empty wiki leaves the mapper run intact.

**Object-form edges are SUPPORTED** (Phase 83 CPROV resolved the v1.7-F deferral). A well-formed object-form `edges:` entry (`{target, provenance, confidence}`) is accepted; the reviewer's unknown-edge check (riding `lintCodeWikiEdges`) flags only a verb OUTSIDE the closed-10 CEDGE vocabulary (`unknown_edge`), and the malformed-provenance check flags only an object lacking `.target` or a prose tag with a malformed shape. There is no longer an "unsupported object form" — the reviewer is the end-of-run validation surface, surfacing the 7 charter classes for review, never rewriting.

This pass is the **code-wiki** review — a SEPARATE pass over `.planning/codebase/**`. It is NOT the personal-vault epistemic lint (`runProgrammaticLint` over `Knowledge/Maps`); the two stay distinct.

Continue to create_codebase_base.
</step>

<step name="create_codebase_base">
Create the root CODEBASE.base file for cross-persona Obsidian querying.

Write `.planning/codebase/CODEBASE.base`:

```markdown
---
name: Codebase Analysis
source: folder
folder: .planning/codebase
filter:
  - property: tags
    operator: contains
    value: codebase-analysis
columns:
  - property: persona
  - property: scope
  - property: severity
  - property: updated
sort:
  - property: severity
    direction: desc
---
```

This provides a filterable root view across all persona outputs -- by persona, by concern severity, by tag (security, performance, etc.).

Continue to verify_output.
</step>

<step name="verify_output">
Verify all documents created successfully:

```bash
ls -la .planning/codebase/
wc -l .planning/codebase/*.md .planning/codebase/*.base 2>/dev/null
```

**Verification checklist:**
- INDEX files exist for each successful persona
- Shard files exist for each dispatched sub-agent
- CODEBASE.base exists
- No empty documents (each should have >20 lines, INDEX files >10 lines)

If any documents missing or empty, note which team leads may have partially failed.

Continue to scan_for_secrets.
</step>

<step name="scan_for_secrets">
**CRITICAL SECURITY CHECK:** Scan output files for accidentally leaked secrets before committing.

Run secret pattern detection:

```bash
# Check for common API key patterns in generated docs
grep -E '(sk-[a-zA-Z0-9]{20,}|sk_live_[a-zA-Z0-9]+|sk_test_[a-zA-Z0-9]+|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9_-]+|AKIA[A-Z0-9]{16}|xox[baprs]-[a-zA-Z0-9-]+|-----BEGIN.*PRIVATE KEY|eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.)' .planning/codebase/*.md 2>/dev/null && SECRETS_FOUND=true || SECRETS_FOUND=false
```

**If SECRETS_FOUND=true:**

```
SECURITY ALERT: Potential secrets detected in codebase documents!

Found patterns that look like API keys or tokens in:
[show grep output]

This would expose credentials if committed.

**Action required:**
1. Review the flagged content above
2. If these are real secrets, they must be removed before committing
3. Consider adding sensitive files to Claude Code "Deny" permissions

Pausing before commit. Reply "safe to proceed" if the flagged content is not actually sensitive, or edit the files first.
```

Wait for user confirmation before continuing to commit_codebase_map.

**If SECRETS_FOUND=false:**

Continue to commit_codebase_map.
</step>

<step name="commit_codebase_map">
Stamp the wiki regen baseline, then commit the codebase map.

After the `.planning/codebase/` docs are written, record the FRESH-02 regen-time stamp — it captures `regen_stamp_ms` + the `_Code-Index.md` entity-count baseline that the SessionStart staleness threshold compares against (without it, pre-stamp wikis fall back to capped mtime comparison):

```bash
# FRESH-02 (Phase 110): wiki regen-time stamp + entity-count baseline. Lands in
# .planning/codebase/.freshness.json — gitignored LOCAL state, never committed.
node bin/gmd-tools.cjs code-freshness --stamp-wiki
```

Commit the codebase map:

```bash
node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" commit "docs: map existing codebase (team-scaled)" --files .planning/codebase/*.md .planning/codebase/*.base
```

## Post-Workflow Vault Extraction (J6)

After the codebase/*.md artifacts are committed, extract knowledge candidates to `.vault/Knowledge/_inbox/`.

```bash
# 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 "[J6] vault-extract-knowledge skipped: obsidian component disabled" >&2
else
  # Collect codebase/*.md and pass as comma-joined --source-files (single spawn)
  SRCS=$(printf '%s,' .planning/codebase/*.md | sed 's/,$//')
  if [[ -n "$SRCS" ]]; then
    node bin/gmd-tools.cjs vault-extract-knowledge \
      --trigger J6 \
      --source-files "$SRCS" \
      --caller map-codebase \
      --phase "codebase-map-$(date +%Y%m%d)" \
    || echo "[J6] extraction returned non-zero — continuing; check .vault/_logs/" >&2
  fi
fi
```

**Flag-form rule (load-bearing):** every flag uses space separator. `--trigger J6`, NOT `--trigger=J6`. `--source-files "<paths>"`, 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 codebase mapping workflow still succeeds.

Continue to offer_next.
</step>

<step name="offer_next">
Present completion summary and next steps.

**Get line counts:**
```bash
wc -l .planning/codebase/*.md .planning/codebase/*.base 2>/dev/null
```

**Output format:**

```
Codebase mapping complete.

Created .planning/codebase/:

**INDEX Files (synthesis with cross-persona wikilinks):**
- TECH-INDEX.md ([N] lines)
- ARCHITECTURE-INDEX.md ([N] lines)
- QUALITY-INDEX.md ([N] lines)
- CONCERNS-INDEX.md ([N] lines)

**Shard Files:**
[List all shard files with line counts]

**Root View:**
- CODEBASE.base - Filterable Obsidian view across all personas

{If any team leads failed on retry:}
**Incomplete:**
- {persona} mapping failed after retry. Run `/gmd:map-codebase` to retry.

Codebase map created. This map may become stale as the project evolves. Consider re-mapping after significant changes with `/gmd:map-codebase`.

---

## Next Up

**Initialize project** -- use codebase context for planning

`/gmd:new-project`

<sub>`/clear` first -- fresh context window</sub>

---

**Also available:**
- Re-run mapping: `/gmd:map-codebase`
- Review INDEX: `cat .planning/codebase/TECH-INDEX.md`
- Browse in Obsidian: Open `.planning/codebase/CODEBASE.base`

---
```

End workflow.
</step>

</process>

<simple_mode_fallback>
## Simple Mode (--simple or < 50 code files)

When simple mode is selected, bypass team-lead architecture entirely. Dispatch 4 gmd-codebase-mapper agents directly (one per persona).

```bash
MAPPER_MODEL=$(node "$HOME/.claude/get-magic-done/bin/gmd-tools.cjs" resolve-model --complexity standard 2>/dev/null || echo "sonnet")
```

**Agent 1: Tech Focus**

```
Task(
  subagent_type="gmd-codebase-mapper",
  model="{MAPPER_MODEL}",
  run_in_background=true,
  description="Map codebase tech stack",
  prompt="Focus: tech

Analyze this codebase for technology stack and external integrations.

Write these documents to .planning/codebase/:
- STACK.md - Languages, runtime, frameworks, dependencies, configuration
- INTEGRATIONS.md - External APIs, databases, auth providers, webhooks

Explore thoroughly. Write documents directly using templates. Return confirmation only."
)
```

**Agent 2: Architecture Focus**

```
Task(
  subagent_type="gmd-codebase-mapper",
  model="{MAPPER_MODEL}",
  run_in_background=true,
  description="Map codebase architecture",
  prompt="Focus: arch

Analyze this codebase architecture and directory structure.

Write these documents to .planning/codebase/:
- ARCHITECTURE.md - Pattern, layers, data flow, abstractions, entry points
- STRUCTURE.md - Directory layout, key locations, naming conventions

Explore thoroughly. Write documents directly using templates. Return confirmation only."
)
```

**Agent 3: Quality Focus**

```
Task(
  subagent_type="gmd-codebase-mapper",
  model="{MAPPER_MODEL}",
  run_in_background=true,
  description="Map codebase conventions",
  prompt="Focus: quality

Analyze this codebase for coding conventions and testing patterns.

Write these documents to .planning/codebase/:
- CONVENTIONS.md - Code style, naming, patterns, error handling
- TESTING.md - Framework, structure, mocking, coverage

Explore thoroughly. Write documents directly using templates. Return confirmation only."
)
```

**Agent 4: Concerns Focus**

```
Task(
  subagent_type="gmd-codebase-mapper",
  model="{MAPPER_MODEL}",
  run_in_background=true,
  description="Map codebase concerns",
  prompt="Focus: concerns

Analyze this codebase for technical debt, known issues, and areas of concern.

Write this document to .planning/codebase/:
- CONCERNS.md - Tech debt, bugs, security, performance, fragile areas

Explore thoroughly. Write document directly using template. Return confirmation only."
)
```

After agents complete, skip to verify_output (no CODEBASE.base creation in simple mode -- not enough shard files to warrant it).

Apply the same failure handling as team-lead mode: retry once per failed agent, then continue.
</simple_mode_fallback>

<success_criteria>
- .planning/codebase/ directory created
- Mode determined (team-lead vs simple) based on codebase size
- Two-pass boundary honored: the structural step (`map-structural` → `.planning/codebase/.structural.json`) runs BEFORE the semantic pass; `--structural-only` stops after it (LLM-free); `--semantic-only` skips it, asserts `.structural.json` exists, and consumes it; a full run sequences structural → semantic (SC2/SC3)
- Team-lead mode: 4 gmd-mapper-team-lead agents dispatched with run_in_background=true, each receiving `.planning/codebase/.structural.json` as its entity index
- Simple mode: 4 gmd-codebase-mapper agents dispatched directly
- Graph Reviewer surface (`lint_code_edges`): after the semantic pass, the end-of-run review produces/refreshes `.planning/codebase/.review-report.md` — a deterministic `reviewCodeWiki` baseline (6 mechanical checks: dangling / stale / orphan / missing-boundary / unknown-edge / malformed-provenance) plus, on-demand via `/gmd:map-review` or an inline `gmd-map-reviewer` dispatch under the team-lead, the full 7-check pass (adding LLM claim/evidence judgment); severity-ranked critical/warning/info — fail-open (never blocks the mapper, never rewrites any wiki doc). Object form is SUPPORTED (Phase 83 CPROV resolved the deferral); the unknown-edge check rides `lintCodeWikiEdges` and flags only a verb outside the closed-10 CEDGE vocabulary
- Failure handling: retry once, then fall back to questioning-only if all fail
- CODEBASE.base created (team-lead mode only) with source, filter-by-tags, columns
- Re-map nudge present in completion output (no auto-trigger)
- Clear completion summary with line counts
- User offered clear next steps in GMD style
</success_criteria>
