# Фикс (wall, v2): резолв ID узлов → имена в скил-контексте наставника

## Цель

На ревью плана наставник получает рекомендацию роутера как голые ID узлов (#4, #6) и не может
оценить их уместность — в живом вердикте он буквально пишет «не могу подтвердить их содержание».
Скил-сверка наставника при этом полая. Сделать скил-контекст человекочитаемым: резолвить каждый
рекомендованный ID в «#N — имя» через уже загруженный реестр, чтобы наставник реально судил
уместность скилов.

## Границы

- `classify` (мозг роутера), вердикт наставника, судья, печать — НЕ трогаем.
- Меняем только слой рендера скил-контекста + проброс реестра в него.
- Граф `nodes.yaml` и карточки — НЕ меняем (только читаем имена/описания).

## Решение D1 — renderSkillContext резолвит ID→имя через реестр {#D1}

`renderSkillContext` (tools/mentor-seam.mjs) принимает дополнительный вход `registry` и рендерит
каждый ID рекомендации как `#N — имя` через новый хелпер `resolveNodeName(id, registry)`:
`registry.indexById.get(id)` → `node.name || node.slug`. Fail-safe: нет узла / нет реестра /
неизвестный ID → голый `#N` (не падать, не выдумывать имя). Покрытие: тест с реестром (#4 →
имя), без реестра (голый #4), неизвестный ID (#999 → голый, не падает).

## Решение D2 — onPlanWrite прокидывает registry в renderSkillContext {#D2}

`onPlanWrite` (tools/on-plan-write.mjs) добавляет уже доступный ему параметр `registry` в вызов
`renderSkillContext({ declared: declaredSkills, recommendedChain, registry })` (строка 55). Реестр
он получает параметром (для classify). Покрытие: тест на то, что промпт наставника несёт имя
скила (`markdownlint-cli2`), а не голый `#4`.

## Решение D3 — регрессия tools-only зелёная {#D3}

Полная регрессия `npx vitest run --root app --config vitest.config.tools.mjs` зелёная (база 3901
+ новые скил-сверочные тесты), 0 регрессий. RED → systematic-debugging. Затем
superpowers:verification-before-completion.

## Исполнение под способ-B стеной

Фикс исполняется ПОД способ-B стеной по TDD: план переоформлен в линейный wall-исполнимый скрипт
(`docs/superpowers/plans/2026-06-13-mentor-skill-resolve-wall-plan-v3.md`), где каждое действие
(правка теста → vitest RED → правка исходника → vitest GREEN → полная регрессия) — отдельный шаг
плана с `ref` на решение D1/D2/D3 этой спеки (closed-door SE-1: каждый шаг обязан ref'ать
опечатанную секцию артефакта).

## Критерий приёмки

- `renderSkillContext` с реестром резолвит `#N` → имя; без реестра/неизвестный ID → голый `#N`
  (fail-safe), не бросает.
- `onPlanWrite` передаёт реестр в `renderSkillContext`; промпт наставника несёт имена скилов.
- Регрессия tools-only зелёная (база 3901), скил-сверочные тесты обновлены.

```verified-context-json
[{"id":"1","kind":"EXTRACTED","claim":"renderSkillContext склеивает рекомендацию сырыми ID","ref":"tools/mentor-seam.mjs:58","anchor":"export function renderSkillContext"},
{"id":"2","kind":"EXTRACTED","claim":"onPlanWrite строит skillContext без registry","ref":"tools/on-plan-write.mjs:55","anchor":"renderSkillContext({ declared: declaredSkills"},
{"id":"3","kind":"EXTRACTED","claim":"реестр индексирует узлы по id (node.name есть)","ref":"tools/registry-load.mjs:31","anchor":"const indexById = new Map"},
{"id":"4","kind":"EXTRACTED","claim":"узел #4 имеет name markdownlint-cli2","ref":"docs/registry/nodes.yaml:40","anchor":"name: \"markdownlint-cli2\""}]
```
