# Spec: Docs Extraction and Template Fixes

**Created by:** AnaPlan
**Date:** 2026-05-23
**Scope:** .ana/plans/active/cli-polish/scope.md

## Approach

Phase 2 fixes the docs pipeline so all 12 CLI commands appear on the reference page, updates the ana-learn template to use `--json` (eliminating agent risk from Phase 1's table changes), and adds missing commands to the README.

**Add Learn to funcToFile.** One line: `Learn: 'src/commands/learn.ts'`. Learn uses `new Command('learn')` so the first pass in `buildCommandTree` will pick it up — no regex changes needed for Learn.

**Fix `buildCommandTree` for `program.command()` pattern.** Doctor uses `program.command('doctor')` in doctor.ts. The third pass in `buildCommandTree` finds `.command()` chains but skips when `parentVar === 'program'` because `program` isn't in `varToName`. Fix: when `parentVar === 'program'`, treat the child as a top-level command — create a new entry in the `commands` map directly instead of trying to find a parent. This is a 3-line addition inside the existing third pass's `while` loop, after line 320 (`if (!parentName) continue;`). Replace the blanket `continue` with: if `parentVar === 'program'`, extract details from the chain block, add to `commands` map, and `continue`.

**Update ana-learn template.** Change `ana proof audit --matrix` to `ana proof audit --matrix --json` at line 66 of `templates/.claude/agents/ana-learn.md`. The `--json` path produces all the same data. This eliminates the only agent reference to human-formatted proof table output.

**Add `config get` and `config set` to README.** Both are user-facing commands documented in config.ts but missing from the README commands table. Add them to the "Getting started" table near `config show` and `config delete`.

**Regenerate commands.json.** Run the extract script and verify Doctor and Learn appear in the output with their subcommands.

## Output Mockups

### commands.json — new entries
```json
{
  "name": "doctor",
  "description": "Check project health and configuration",
  "flags": ["--json"],
  "subcommands": []
}
```

```json
{
  "name": "learn",
  "description": "Manage learn sessions",
  "flags": [],
  "subcommands": [
    {
      "name": "end",
      "description": "End learn session — mark timestamp for next session",
      "flags": ["--json"]
    }
  ]
}
```

### README commands table addition
```markdown
| `ana config get <field>` | Get a config field value. Dot notation supported |
| `ana config set <field> <value>` | Set a config field value |
```

## File Changes

### `website/scripts/extract-docs-data.ts` (modify)
**What changes:** Add `Learn: 'src/commands/learn.ts'` to the `funcToFile` map. Fix the third pass in `buildCommandTree` to handle `parentVar === 'program'` by creating a top-level command entry instead of skipping.
**Pattern to follow:** The existing `funcToFile` entries and the existing third pass logic at lines 311-337.
**Why:** Without these changes, Doctor and Learn don't appear in commands.json or the CLI reference page.

### `packages/cli/templates/.claude/agents/ana-learn.md` (modify)
**What changes:** Change `ana proof audit --matrix` to `ana proof audit --matrix --json` at the line where the agent is instructed to run the matrix command.
**Pattern to follow:** All other agent template proof commands already use `--json`.
**Why:** Phase 1 changes the human-formatted matrix output. This template change ensures the Learn agent uses the JSON path, which is unaffected.

### `README.md` (modify)
**What changes:** Add `config get` and `config set` rows to the commands table in the Getting started section, near the existing `config show` and `config delete` entries.
**Pattern to follow:** The existing table format at lines 161-168.
**Why:** Both are user-facing commands missing from the README.

### `website/data/commands.json` (modify — regenerated)
**What changes:** Regenerated by running the extract script. Will now include Doctor and Learn entries.
**Pattern to follow:** N/A — generated file.
**Why:** The reference page reads this file. Missing entries = missing docs.

## Acceptance Criteria

- [ ] AC8: `commands.json` includes both `doctor` and `learn` commands with their subcommands.
- [ ] AC9: The CLI reference page at anatomia.dev/docs/reference/cli renders Doctor and Learn.
- [ ] AC10: All existing `--json` output is unchanged.
- [ ] AC11: Tests pass: `pnpm run test -- --run`.
- [ ] AC12: The ana-learn template uses `ana proof audit --matrix --json`.
- [ ] AC13: README commands table includes `config get` and `config set`.

## Testing Strategy

- **Unit tests:** The website package has `lib/__tests__/docs-data/data-integrity.test.ts` which validates commands.json structure. After regeneration, existing tests should pass and cover the new entries.
- **Integration tests:** Run `cd website && pnpm run build` to verify the reference page renders. Check that the build succeeds without errors.
- **Edge cases:** Verify the `program.command()` fix doesn't create duplicate entries — the third pass could match commands already found by the first pass. Add a guard: only add to `commands` map if the command name isn't already present.

## Dependencies

Phase 1 must be complete — the `learn` description change in learn.ts affects what the extract script reads.

## Constraints

- The ana-learn template change is to the product template (`templates/.claude/agents/`), not the dogfood installation (`.claude/agents/`). It ships to all customers on next `ana init`.
- The README table format must match the existing pipe-delimited markdown table structure.

## Gotchas

- **Learn description source.** The extract script reads the description from the source file (learn.ts), not from runtime. Phase 1 changes learn.ts — Phase 2's regeneration will pick up the new description. If Phase 1 isn't done first, commands.json will have the old description.
- **Doctor has no subcommands.** The `program.command('doctor')` fix should produce an entry with `subcommands: []`. Doctor's flags (`--json`) are chained directly on the `.command()` call — `extractDetailsFromBlock` already handles this.
- **Duplicate command guard.** The third-pass fix for `program.command()` could theoretically re-add a command already found by the first pass. Guard with `if (!commands.has(childName))` before adding.
- **commands.json path.** The generated file is at `website/data/commands.json`. Run the extract script from the website directory or with the correct working directory.
- **The dogfood ana-learn.md.** The scope says to update the template at `packages/cli/templates/.claude/agents/ana-learn.md`. The dogfood copy at `.claude/agents/ana-learn.md` may also need the same change — but that's a separate concern (dogfood vs product). The scope targets the product template. Check whether the dogfood copy has the same line and update it too if so.

## Build Brief

### Rules That Apply
- All imports use `.js` extensions and `node:` prefix for built-ins.
- README changes: match existing table format exactly — pipe-delimited, backtick-wrapped commands.
- Template changes: the template is markdown, not code — no lint rules apply, but maintain consistent style.
- Website build must succeed after changes: `cd website && pnpm run build`.

### Pattern Extracts

**funcToFile map (extract-docs-data.ts:449-461) — add Learn here:**
```typescript
  const funcToFile: Record<string, string> = {
    Scan: 'src/commands/scan.ts',
    Init: 'src/commands/init/index.ts',
    Setup: 'src/commands/setup.ts',
    Work: 'src/commands/work.ts',
    Artifact: 'src/commands/artifact.ts',
    Verify: 'src/commands/verify.ts',
    Pr: 'src/commands/pr.ts',
    Config: 'src/commands/config.ts',
    Proof: 'src/commands/proof.ts',
    Agents: 'src/commands/agents.ts',
    Doctor: 'src/commands/doctor.ts',
  };
```

**Third pass — the fix location (extract-docs-data.ts:311-337):**
```typescript
  // Third pass: handle `.command('name')` chain pattern (multiline)
  const collapsed = content.replace(/\n\s*/g, ' ');
  const chainRegex = /(\w+)\s*\.command\(\s*['"]([^'"]+)['"]\)/g;
  let chainMatch;
  while ((chainMatch = chainRegex.exec(collapsed)) !== null) {
    const parentVar = chainMatch[1];
    const childName = chainMatch[2];
    const parentName = varToName.get(parentVar);
    if (!parentName) continue;  // <-- This skips when parentVar === 'program'

    // Extract the chain from the match point to the next .action(
    const rest = collapsed.substring(chainMatch.index);
    const actionIdx = rest.indexOf('.action(');
    const chainBlock = actionIdx !== -1 ? rest.substring(0, actionIdx) : rest.substring(0, 300);

    const details = extractDetailsFromBlock(chainBlock);
    const childCmd: Command = { name: childName, ...details, subcommands: [] };

    const parent = commands.get(parentName);
    if (parent) {
      if (!parent.subcommands.find(s => s.name === childName)) {
        parent.subcommands.push(childCmd);
      }
    }
  }
```

**README commands table (README.md:161-168) — add rows near config entries:**
```markdown
| Command | Description |
|---------|-------------|
| `ana config show` | Display current ana.json settings |
| `ana config delete <field>` | Remove a config field, reverting to detected default |
```

**ana-learn template line (ana-learn.md ~line 66) — the line to change:**
```
Run `ana proof audit --matrix` to get the full orientation
```

### Proof Context

**extract-docs-data.ts** (2 cycles, last 2026-05-15):
- [observation] stripJsx logic duplicated between extraction script and website/lib — not relevant to this change
- No active findings for the buildCommandTree or funcToFile areas

### Checkpoint Commands
- After extract-docs-data.ts changes: `(cd website && pnpm run build)` — Expected: build succeeds, commands.json includes doctor and learn
- After all changes: `pnpm run test -- --run` — Expected: all tests pass
- Lint: `pnpm run lint`

### Build Baseline
- Current tests: 2906 passed (CLI) + 68 passed (website) = 2974 total
- Current test files: 122 (CLI) + 10 (website) = 132 total
- Command used: `pnpm run test -- --run`
- After build: same test count (no new tests in Phase 2 — existing data-integrity tests cover the new commands.json entries)
- Regression focus: `website/lib/__tests__/docs-data/data-integrity.test.ts`
