# context

## Objective

Replace the `learn` tool with a `docs` tool. All built-in documentation (including the current learn articles: create-skill, update-permissions, plan) lives in `doc/*.txt` as vim help files. User-defined docs are discovered from `.magenta/docs/*.md`. The tool's input schema lists all available docs by name with descriptions.

## Key design decisions

- **Single source for built-in docs**: Move create-skill, update-permissions, and plan content into `doc/` as vim help files (e.g. `doc/magenta-skills.txt`, `doc/magenta-permissions.txt`, `doc/magenta-plan.txt`). Delete `node/core/src/tools/learn/`.
- **Hardcoded registry**: `docs.ts` has a `BUILTIN_DOCS` array with `{ name, description }` for each `doc/*.txt` file. Content is read from `doc/` at runtime via path relative to `__dirname`.
- **User docs**: Flat `.md` files in `.magenta/docs/` with YAML frontmatter (`name` + `description`). Discovered at runtime. User docs with the same name as a built-in doc override it (e.g. a user can customize `plan` or `update-permissions`).
- **Dynamic spec**: Like `spawn_subagents`, the tool spec is generated at runtime to include both built-in and user doc names in the enum/description.
- **Precommit check**: Verifies every `doc/*.txt` (except `tags`) has a matching entry in `BUILTIN_DOCS` and vice versa.

## Relevant files

- `node/core/src/tools/learn.ts` → rename to `docs.ts`
- `node/core/src/tools/learn/` → delete (content moves to `doc/`)
- `doc/*.txt` — vim help files (add 3 new ones for former learn articles)
- `node/core/src/tools/tool-registry.ts` — `STATIC_TOOL_NAMES`, capability map
- `node/core/src/tools/toolManager.ts` — `StaticToolMap`, `TOOL_SPEC_MAP`, `getToolSpecs()`
- `node/core/src/tools/create-tool.ts` — `createTool()` switch, `CreateToolContext`
- `node/core/src/tools/helpers.ts` — `validateInput()` switch
- `node/core/src/tool-types.ts` — `ToolStructuredResult` union
- `node/render-tools/index.ts` — tool display rendering
- `node/render-tools/streaming.ts` — streaming display
- `node/tools/learn.test.ts` → rename to `docs.test.ts`
- `node/core/src/providers/skills.ts` — `extractYamlFrontmatter` (reuse for user docs)
- `node/core/src/thread-core.ts` — calls `getToolSpecs()`, has `cwd` in context
- `.git/hooks/pre-commit` — existing precommit script

# implementation

## Step 1: Convert learn articles to vim help files

- [ ] Convert `node/core/src/tools/learn/create-skill.md` → `doc/magenta-skills.txt` (vim help format)
- [ ] Convert `node/core/src/tools/learn/update-permissions.md` → `doc/magenta-permissions.txt`
- [ ] Convert `node/core/src/tools/learn/plan.md` → `doc/magenta-plan.txt`
- [ ] Add appropriate vim help tags (e.g. `*magenta-skills*`) and modeline
- [ ] Add entries in `doc/magenta.txt` table of contents
- [ ] Delete `node/core/src/tools/learn/` directory
- [ ] Run `:helptags doc/` to regenerate tags

## Step 2: Rename `learn` → `docs` and implement built-in doc loading

- [ ] Rename `node/core/src/tools/learn.ts` → `node/core/src/tools/docs.ts`
- [ ] Rewrite `docs.ts`:
  - Define `BUILTIN_DOCS` array with all 8 entries (5 existing + 3 new), each with `name` and `description`
  - Compute `DOC_DIR = join(__dirname, "../../../../doc")` to locate `doc/`
  - `loadDoc(name)` reads `join(DOC_DIR, name + ".txt")`
  - Static `getBuiltinSpec()` returns the spec with just built-in docs (for when no user docs are available)
  - `getSpec(userDocs)` returns dynamic spec including both built-in and user docs
  - `execute()` handles both built-in and user doc requests
  - `validateInput()` accepts both built-in and user doc names
- [ ] Update all references from `learn` to `docs`:
  - `tool-registry.ts`: replace `"learn"` with `"docs"` in all arrays and capability map
  - `toolManager.ts`: update import, `StaticToolMap` key, remove from `TOOL_SPEC_MAP` (now dynamic)
  - `create-tool.ts`: update import and switch case
  - `helpers.ts`: update import and switch case
  - `tool-types.ts`: update import and `ToolStructuredResult`
  - `render-tools/index.ts`: replace `"learn"` cases with `"docs"`
  - `render-tools/streaming.ts`: replace `"learn"` case
  - `node/core/src/index.ts`: update any exports
- [ ] Run type check (`npx tsgo -b`) and fix remaining references
- [ ] Test: existing learn test (renamed) still passes
  - **Setup**: `withDriver` test
  - **Actions**: mock agent requests `docs` tool with `{ name: "magenta-plan" }`
  - **Assertions**: tool result contains planning guide content (e.g. "Planning Process")

## Step 3: Add user doc discovery

- [ ] Export `extractYamlFrontmatter` from `node/core/src/providers/skills.ts` (or extract to shared utility)
- [ ] Add `loadUserDocs(cwd, logger)` function in `docs.ts`:
  - Scans `.magenta/docs/` relative to `cwd` for `*.md` files
  - Parses frontmatter for `name` + `description`
  - Returns `UserDoc[]` (with `name`, `description`, `filePath`)
  - User docs with the same `name` as a built-in doc override the built-in
- [ ] Make `getToolSpecs()` support dynamic docs spec:
  - Add `userDocs` parameter (or a `docsContext` object)
  - For `"docs"` tool, call `Docs.getSpec(userDocs)` instead of using static `TOOL_SPEC_MAP`
  - Thread from `ThreadCore` which has `cwd` — call `loadUserDocs()` there and pass result through
- [ ] Update `CreateToolContext` to include `userDocs` so `execute()` can resolve user doc file paths
- [ ] Update `validateInput()` to accept a set of valid names (built-in + user)
- [ ] Test: user doc discovery
  - **Setup**: temp dir with `.magenta/docs/my-guide.md` containing frontmatter
  - **Actions**: call `loadUserDocs()` with temp dir as cwd
  - **Assertions**: returns entry with correct name/description/path
- [ ] Test: requesting a user doc via the tool returns its content
  - **Setup**: `withDriver` with `.magenta/docs/` fixture
  - **Actions**: mock agent requests `docs` with `{ name: "my-guide" }`
  - **Assertions**: tool result contains the file's markdown content
- [ ] Test: user doc overrides built-in doc
  - **Setup**: `.magenta/docs/magenta-plan.md` with frontmatter `name: magenta-plan`
  - **Actions**: request `docs` with `{ name: "magenta-plan" }`
  - **Assertions**: tool result contains user doc content, not built-in `doc/magenta-plan.txt`

## Step 4: Add precommit check

- [ ] Create `scripts/check-docs-linked.mjs`:
  - List `doc/*.txt` files, filter out `tags`
  - Extract expected names (filename without `.txt`)
  - Read `node/core/src/tools/docs.ts`, extract `BUILTIN_DOCS` entries via regex
  - Assert bijection: every file has an entry, every entry has a file
  - Exit non-zero with clear message on mismatch
- [ ] Add to `.git/hooks/pre-commit` as a parallel check alongside typecheck and biome
- [ ] Verify: add a temporary `doc/fake.txt`, run check, confirm failure; remove, confirm pass

## Step 5: Final cleanup

- [ ] Rename test `node/tools/learn.test.ts` → `node/tools/docs.test.ts`
- [ ] Update test to use `"docs"` tool name and test a neovim help doc
- [ ] Update `doc/magenta-skills.txt` to mention `.magenta/docs/` for user reference docs (vs `.magenta/skills/` for scripts)
- [ ] Run full test suite: `TEST_MODE=sandbox npx vitest run`
- [ ] Run `npx biome check .`
