docs(router-mentor): R6.2 + sub-plan A + handoff-2

This commit is contained in:
Дмитрий
2026-06-10 13:36:57 +03:00
parent 364da6bf48
commit e69fd396b2
4 changed files with 898 additions and 12 deletions
+13 -12
View File
@@ -1,6 +1,6 @@
# Brain Status (auto-generated)
Last updated: 2026-06-10T02:38:22.945Z
Last updated: 2026-06-10T02:52:33.893Z
| Контролёр | Состояние | Детали |
|---|---|---|
@@ -8,7 +8,7 @@ Last updated: 2026-06-10T02:38:22.945Z
| C2 Cross-ref consistency | ✅ | [cross-ref-checker] OK — 0 drift in 4 files |
| C3 Observer-of-observer | ✅ | [observer-of-observer] OK — last read 2 week(s) ago |
| C4 Сигнальный статус | ✅ | This file (self-reference) |
| C5 Observer-coverage | ✅ | 806 episode(s) this month · Stop-hook + post-commit OK |
| C5 Observer-coverage | ✅ | 808 episode(s) this month · Stop-hook + post-commit OK |
| C6 Chain map sync | ✅ | [chain-map-checker] OK — 16 chains in sync |
## Кто на посту (оборона М1–М6)
@@ -33,12 +33,13 @@ Last updated: 2026-06-10T02:38:22.945Z
| enforce-verify-gate.mjs | `enforce-verify-gate.mjs` | 🔴 |
| enforce-criterion-gate.mjs | `enforce-criterion-gate.mjs` | 🔴 |
Недавние escape владельца: 0 · Недавние блоки: 7
Недавние escape владельца: 0 · Недавние блоки: 8
**Недавние блоки (детали):**
| Время | Действие | Причина |
|---|---|---|
| 2026-06-10T02:52:18.601Z | write:c:/users/administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 | path «C:/Users/Administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 |
| 2026-06-10T02:37:58.544Z | write:c:/users/administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 | path «C:/Users/Administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 |
| 2026-06-10T02:33:22.617Z | write:c:/users/administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 | path «C:/Users/Administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 |
| 2026-06-10T02:28:14.775Z | write:c:/users/administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 | path «C:/Users/Administrator/.claude/projects/c---------------------crm-------------/03437265-6d58-4622-aeed-c0eeac0f2c3 |
@@ -49,8 +50,8 @@ Last updated: 2026-06-10T02:38:22.945Z
## Метрики (информационные, не алерты)
- Observer evidence: 806 episodes this month, 0 observer_error markers, 1 PII matches before filter
- Legacy v1 episodes (not in factor analysis): 806
- Observer evidence: 808 episodes this month, 0 observer_error markers, 1 PII matches before filter
- Legacy v1 episodes (not in factor analysis): 808
- Last /brain-retro: 14 day(s) ago
- Использование узлов: см. `/brain-retro` (раз в спринт). missed_activations: 0. **Неиспользованные узлы — не алерт, если профильной задачи не было** (Pravila §16.4 v1.36; capability-readiness; см. memory `feedback_brain_unused_tools_not_problem` — outside-repo memory store).
@@ -65,9 +66,9 @@ Baseline дисциплины роутера (этап 2 router discipline overh
| feature | 27 | 11.1% | 3.7% |
| bugfix | 27 | 14.8% | 18.5% |
Router step distribution: 1: 386, 2: 297, 3: 18, 5: 89
Router step distribution: 1: 388, 2: 297, 3: 18, 5: 89
Boundaries applied (ADR / границы): 8 of 790 эпизодов (1.0%).
Boundaries applied (ADR / границы): 8 of 792 эпизодов (1.0%).
## Активные многоэтапные проекты
@@ -85,10 +86,10 @@ Boundaries applied (ADR / границы): 8 of 790 эпизодов (1.0%).
| Компонент | Токены (in/out) | USD |
|---|---|---|
| Classifier (Sonnet 4.6) | 49148/205332 | $3.23 |
| Classifier (Sonnet 4.6) | 49203/206049 | $3.24 |
| Self-assessment (Sonnet 4.6) | 0/0 | $0.00 |
| Reviewer (Opus 4.7 + fallback) | 0/0 | $0.00 |
| **Итого** | | **$3.23** |
| **Итого** | | **$3.24** |
## Аномалии классификатора
@@ -101,7 +102,7 @@ Episodes since last run: 542 / threshold: 10
## Reviewer: субагент vs fallback
0 эпизодов проверено из 806.
0 эпизодов проверено из 808.
## Reviewer findings
@@ -127,8 +128,8 @@ Episodes since last run: 542 / threshold: 10
| PID | Имя | CPU-время | Возраст |
|---|---|---|---|
| 3916 | MsMpEng | 3.72ч | 14476229.1ч |
| 1208 | svchost | 1.46ч | 1327490.6ч |
| 3916 | MsMpEng | 3.74ч | 0.0ч |
| 1208 | svchost | 1.47ч | NaNч |
| 4 | System | 1.20ч | 0.0ч |
⚠️ Проверь, не «осиротевшие» ли это процессы от завершённых Claude-сессий.
@@ -0,0 +1,431 @@
# Sub-plan A — context-verity (проверенный контекст) Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Чистый модуль `tools/context-verity.mjs`, который проверяет verified-context артефакт наставника (§5.5 спеки): резолвит EXTRACTED-цитаты по символу/контенту, понижает неразрешённые до INFERRED (secure-default), и даёт freeze-side guard для ✅O2.
**Architecture:** Чистое ядро по образцу `tools/plan-lock.mjs::refResolves` `[plan-lock.mjs:226]` — никакого прямого I/O, доступ к файлам инъектируется (`readFileImpl`) для детерминированных тестов. Резолв по СИМВОЛУ (anchor-подстрока должна найтись в файле; номер строки в ref — только подсказка, SE-1). Модуль standalone и тестируем изолированно; wiring в `plan-lock.freezeArtifact` ОТЛОЖЕН в sub-plan C (там verified-context артефакт реально производится наставником и встраивается в sealed-артефакт).
**Tech Stack:** Node ESM (`.mjs`), vitest (tools-config). Источник истины спеки: `docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md` §5.5/§5.6/§5.7(secure-default)/§5.10 + ✅O2.
**Scope (граница):**
- **В A:** `tools/context-verity.mjs` (чистый) + `tools/context-verity.test.mjs`. Функции: `parseRef`, `resolveCitation`, `verifyArtifact`, `artifactHasUnresolvedExtracted`, константа `CITATION_KINDS`.
- **НЕ в A (→ sub-plan C):** вызов `artifactHasUnresolvedExtracted` из `plan-lock.freezeArtifact` (требует, чтобы verified-context артефакт уже встраивался в sealed-артефакт — это шов наставника, C). A экспортирует guard готовым к подключению.
**Квирк среды (ОБЯЗАТЕЛЬНО для шагов «Run»):** vitest запускается ТОЛЬКО из `app/`:
```
cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs <фильтр> --reporter dot
```
cwd между Bash-вызовами ненадёжен — каждый Run-шаг префиксить `cd app && ...` в одной команде.
**NB git:** в этой среде git зажат стеной у Claude — `git commit`-шаги выполняет ВЛАДЕЛЕЦ/исполнитель вне Claude-стены (или субагент с git-доступом per Pravila §15.1). Команды коммитов даны как есть.
---
### Task 1: Схема артефакта + `parseRef` + `CITATION_KINDS`
**Files:**
- Create: `tools/context-verity.mjs`
- Test: `tools/context-verity.test.mjs`
**Схема verified-context артефакта (§5.5):** массив записей
```
{ id: string, claim: string, ref: "file:line", kind: "EXTRACTED"|"INFERRED", anchor?: string, derivation_ref?: string }
```
`anchor` — литеральная подстрока исходника, которую EXTRACTED-цитата утверждает (для символ-резолва SE-1). `derivation_ref` — для INFERRED (§5.5/SE-2).
- [ ] **Step 1: Write the failing test**
```js
// tools/context-verity.test.mjs
import { describe, it, expect } from 'vitest';
import { parseRef, CITATION_KINDS } from './context-verity.mjs';
describe('parseRef', () => {
it('парсит file:line', () => {
expect(parseRef('tools/router-engine.mjs:106')).toEqual({ file: 'tools/router-engine.mjs', line: 106 });
});
it('голый файл без строки → line:null', () => {
expect(parseRef('tools/x.mjs')).toEqual({ file: 'tools/x.mjs', line: null });
});
it('не-строка → null', () => {
expect(parseRef(42)).toBe(null);
});
it('CITATION_KINDS заморожен и содержит оба вида', () => {
expect(CITATION_KINDS).toEqual(['EXTRACTED', 'INFERRED']);
expect(Object.isFrozen(CITATION_KINDS)).toBe(true);
});
});
```
- [ ] **Step 2: Run test to verify it fails**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: FAIL — `Cannot find module './context-verity.mjs'` / `parseRef is not a function`.
- [ ] **Step 3: Write minimal implementation**
```js
// tools/context-verity.mjs
#!/usr/bin/env node
/**
* context-verity (§5.6) — машинная сверка verified-context артефакта наставника.
* Резолв EXTRACTED-цитат по СИМВОЛУ/контенту (anchor-подстрока в файле; номер строки в
* ref — подсказка, SE-1). Чистое ядро (I/O инъектируется), образец — plan-lock.refResolves.
* verity = РЕЗОЛВ цитат, НЕ истина (SE-6) — ревью владельца обязателен (§5.10).
*/
// Допустимые виды цитат (§5.5).
export const CITATION_KINDS = Object.freeze(['EXTRACTED', 'INFERRED']);
/** Парс "file:line" → {file, line:number|null} | null (не-строка). Голый файл → line:null. */
export function parseRef(ref) {
if (typeof ref !== 'string') return null;
const m = ref.match(/^(.*):(\d+)$/);
if (!m) return { file: ref, line: null };
return { file: m[1], line: Number(m[2]) };
}
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — 4 passed.
- [ ] **Step 5: Commit**
```bash
git add tools/context-verity.mjs tools/context-verity.test.mjs
git commit -m "feat(context-verity): схема артефакта + parseRef + CITATION_KINDS (sub-plan A Task 1)"
```
---
### Task 2: `resolveCitation` — резолв по anchor (SE-1)
**Files:**
- Modify: `tools/context-verity.mjs`
- Test: `tools/context-verity.test.mjs`
- [ ] **Step 1: Write the failing test**
```js
// добавить в context-verity.test.mjs
import { resolveCitation } from './context-verity.mjs';
describe('resolveCitation', () => {
const fakeRead = (file) => file === 'tools/x.mjs' ? 'export function buildRouterPrompt() {}' : null;
it('anchor найден в файле → resolved', () => {
const r = resolveCitation({ ref: 'tools/x.mjs:1', anchor: 'buildRouterPrompt' }, fakeRead);
expect(r.resolved).toBe(true);
});
it('anchor НЕ найден → не resolved', () => {
const r = resolveCitation({ ref: 'tools/x.mjs:1', anchor: 'runJudge' }, fakeRead);
expect(r.resolved).toBe(false);
});
it('файл не прочитан → не resolved', () => {
const r = resolveCitation({ ref: 'tools/missing.mjs:1', anchor: 'x' }, fakeRead);
expect(r.resolved).toBe(false);
});
it('нет anchor (SE-1: резолв по символу обязателен) → не resolved', () => {
const r = resolveCitation({ ref: 'tools/x.mjs:1', anchor: '' }, fakeRead);
expect(r.resolved).toBe(false);
});
it('readFileImpl бросил → не resolved (не крашит)', () => {
const r = resolveCitation({ ref: 'tools/x.mjs:1', anchor: 'x' }, () => { throw new Error('io'); });
expect(r.resolved).toBe(false);
});
});
```
- [ ] **Step 2: Run test to verify it fails**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: FAIL — `resolveCitation is not a function`.
- [ ] **Step 3: Write minimal implementation**
```js
// добавить в context-verity.mjs
/**
* Резолв одной EXTRACTED-цитаты: anchor-подстрока ОБЯЗАНА встретиться в файле
* (SE-1: по символу/контенту, не по номеру строки — он лишь подсказка). readFileImpl
* инъектируется (в проде — fs.readFileSync; в тестах — мок). Возвращает {resolved, reason}.
*/
export function resolveCitation(cite, readFileImpl) {
const parsed = parseRef(cite && cite.ref);
if (!parsed || !parsed.file) return { resolved: false, reason: 'ref не парсится' };
const anchor = String((cite && cite.anchor) || '').trim();
if (!anchor) return { resolved: false, reason: 'нет anchor — резолв по символу невозможен (SE-1)' };
let src;
try { src = readFileImpl(parsed.file); } catch { src = null; }
if (src == null) return { resolved: false, reason: `файл не прочитан: ${parsed.file}` };
return String(src).includes(anchor)
? { resolved: true, reason: 'anchor найден (символ-резолв)' }
: { resolved: false, reason: 'anchor не найден в файле' };
}
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — 9 passed (4 + 5).
- [ ] **Step 5: Commit**
```bash
git add tools/context-verity.mjs tools/context-verity.test.mjs
git commit -m "feat(context-verity): resolveCitation по символу (SE-1, sub-plan A Task 2)"
```
---
### Task 3: `verifyArtifact` — резолв EXTRACTED + flagged
**Files:**
- Modify: `tools/context-verity.mjs`
- Test: `tools/context-verity.test.mjs`
- [ ] **Step 1: Write the failing test**
```js
// добавить в context-verity.test.mjs
import { verifyArtifact } from './context-verity.mjs';
describe('verifyArtifact — резолв EXTRACTED', () => {
const read = (file) => file === 'a.mjs' ? 'function good(){}' : null;
it('все EXTRACTED резолвятся → ok, нет flagged', () => {
const art = [{ id: '1', claim: 'есть good', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'good' }];
const r = verifyArtifact(art, read);
expect(r.ok).toBe(true);
expect(r.flagged).toEqual([]);
expect(r.extractedCount).toBe(1);
});
it('неразрешённая EXTRACTED → flagged + не ok', () => {
const art = [{ id: '2', claim: 'нет bad', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'bad' }];
const r = verifyArtifact(art, read);
expect(r.ok).toBe(false);
expect(r.flagged.map((f) => f.id)).toContain('2');
});
it('INFERRED не требует резолва', () => {
const art = [
{ id: '1', claim: 'есть good', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'good' },
{ id: '3', claim: 'предположение', ref: 'a.mjs:1', kind: 'INFERRED', derivation_ref: 'd1' },
];
const r = verifyArtifact(art, read);
expect(r.ok).toBe(true);
});
it('битая запись → flagged, не крашит', () => {
const r = verifyArtifact([null, 'bad', { kind: 'EXTRACTED', anchor: 'good', ref: 'a.mjs:1', id: '1' }], read);
expect(r.flagged.length).toBeGreaterThanOrEqual(2);
});
});
```
- [ ] **Step 2: Run test to verify it fails**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: FAIL — `verifyArtifact is not a function`.
- [ ] **Step 3: Write minimal implementation**
```js
// добавить в context-verity.mjs
/**
* Проверить весь артефакт. EXTRACTED-записи обязаны резолвиться (по anchor). Неразрешённая
* EXTRACTED попадает в flagged И downgraded (понижение — Task 4). INFERRED не резолвится.
* Битая запись (null/не-объект) → flagged, не крашит (зеркало N2 action-journal).
* ok = есть ≥1 EXTRACTED И нет неразрешённых (VA-9: 0 EXTRACTED не «проверен» — Task 4 ужесточит).
* @returns {{ok, flagged:[{id,reason}], downgraded:[{id,reason}], extractedCount, entries}}
*/
export function verifyArtifact(artifact, readFileImpl) {
const list = Array.isArray(artifact) ? artifact : [];
const flagged = [];
const downgraded = [];
let extractedCount = 0;
const entries = [];
for (const e of list) {
if (!e || typeof e !== 'object' || Array.isArray(e)) { flagged.push({ id: null, reason: 'битая запись' }); continue; }
if (e.kind === 'EXTRACTED') {
extractedCount++;
const r = resolveCitation({ ref: e.ref, anchor: e.anchor }, readFileImpl);
if (!r.resolved) {
flagged.push({ id: e.id ?? null, reason: r.reason });
downgraded.push({ id: e.id ?? null, reason: r.reason });
entries.push({ ...e, kind: 'INFERRED', downgraded_from: 'EXTRACTED' }); // secure-default (Task 4 verify)
continue;
}
}
entries.push(e);
}
const ok = extractedCount > 0 && downgraded.length === 0;
return { ok, flagged, downgraded, extractedCount, entries };
}
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — 13 passed.
- [ ] **Step 5: Commit**
```bash
git add tools/context-verity.mjs tools/context-verity.test.mjs
git commit -m "feat(context-verity): verifyArtifact резолв EXTRACTED + flagged (sub-plan A Task 3)"
```
---
### Task 4: Secure-default downgrade (S2/§5.5) + пустой артефакт (VA-9)
**Files:**
- Modify: `tools/context-verity.test.mjs` (поведение уже в коде Task 3 — фиксируем тестами + проверяем downgrade-форму)
- [ ] **Step 1: Write the failing test**
```js
// добавить в context-verity.test.mjs
describe('secure-default downgrade + VA-9', () => {
const read = (file) => file === 'a.mjs' ? 'function good(){}' : null;
it('неразрешённая EXTRACTED понижается до INFERRED в entries (S2)', () => {
const art = [{ id: '2', claim: 'нет bad', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'bad' }];
const r = verifyArtifact(art, read);
expect(r.entries[0].kind).toBe('INFERRED');
expect(r.entries[0].downgraded_from).toBe('EXTRACTED');
expect(r.downgraded.map((d) => d.id)).toContain('2');
});
it('пустой артефакт (0 EXTRACTED) НЕ проверен (VA-9)', () => {
expect(verifyArtifact([], read).ok).toBe(false);
expect(verifyArtifact([{ id: '3', kind: 'INFERRED', ref: 'a.mjs:1', claim: 'x', derivation_ref: 'd' }], read).ok).toBe(false);
});
it('не-массив → не проверен, не крашит', () => {
expect(verifyArtifact(null, read).ok).toBe(false);
expect(verifyArtifact('bad', read).ok).toBe(false);
});
});
```
- [ ] **Step 2: Run test to verify it fails OR passes (поведение в коде Task 3)**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — поведение downgrade/VA-9 уже реализовано в Task 3; этот шаг ФИКСИРУЕТ его тестами (red-green не нужен — это закрепление инварианта). Если FAIL — вернуться к Task 3 коду.
- [ ] **Step 3: (нет нового кода — инвариант закреплён тестами)**
Если все 16 проходят — реализация Task 3 корректно покрывает S2 + VA-9. Иначе исправить `verifyArtifact` по падению.
- [ ] **Step 4: Run — подтвердить 16 passed**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — 16 passed.
- [ ] **Step 5: Commit**
```bash
git add tools/context-verity.test.mjs
git commit -m "test(context-verity): закрепить secure-default downgrade + VA-9 (sub-plan A Task 4)"
```
---
### Task 5: Freeze-side guard `artifactHasUnresolvedExtracted` (✅O2, экспорт для sub-plan C)
**Files:**
- Modify: `tools/context-verity.mjs`
- Test: `tools/context-verity.test.mjs`
- [ ] **Step 1: Write the failing test**
```js
// добавить в context-verity.test.mjs
import { artifactHasUnresolvedExtracted } from './context-verity.mjs';
describe('artifactHasUnresolvedExtracted (✅O2 freeze-side guard)', () => {
const read = (file) => file === 'a.mjs' ? 'function good(){}' : null;
it('все EXTRACTED резолвятся → false (печать разрешена)', () => {
const art = [{ id: '1', claim: 'good', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'good' }];
expect(artifactHasUnresolvedExtracted(art, read)).toBe(false);
});
it('есть неразрешённая EXTRACTED → true (печать ОТКАЗана)', () => {
const art = [{ id: '2', claim: 'bad', ref: 'a.mjs:1', kind: 'EXTRACTED', anchor: 'bad' }];
expect(artifactHasUnresolvedExtracted(art, read)).toBe(true);
});
});
```
- [ ] **Step 2: Run test to verify it fails**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: FAIL — `artifactHasUnresolvedExtracted is not a function`.
- [ ] **Step 3: Write minimal implementation**
```js
// добавить в context-verity.mjs
/**
* ✅O2 freeze-side guard: артефакт с ХОТЬ ОДНОЙ неразрешённой EXTRACTED не печатается.
* Чистый предикат для подключения в plan-lock.freezeArtifact (wiring — sub-plan C, где
* verified-context артефакт встраивается в sealed-артефакт). Здесь — только готовый guard.
*/
export function artifactHasUnresolvedExtracted(artifact, readFileImpl) {
return verifyArtifact(artifact, readFileImpl).downgraded.length > 0;
}
```
- [ ] **Step 4: Run test to verify it passes**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs ../tools/context-verity.test.mjs --reporter dot`
Expected: PASS — 18 passed.
- [ ] **Step 5: Commit**
```bash
git add tools/context-verity.mjs tools/context-verity.test.mjs
git commit -m "feat(context-verity): freeze-side guard artifactHasUnresolvedExtracted (O2, sub-plan A Task 5)"
```
---
### Task 6: Регрессия tools-vitest GREEN
**Files:** (нет правок — проверка)
- [ ] **Step 1: Прогнать ВЕСЬ tools-набор**
Run: `cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs --reporter dot`
Expected: PASS — весь tools-набор зелёный, новый `context-verity.test.mjs` (18) включён, 0 регрессий в соседних машинах М1-М7. Зафиксировать число passed (baseline для следующих sub-plan).
- [ ] **Step 2: Если RED — systematic-debugging**
При падении — НЕ править наугад: `superpowers:systematic-debugging`, root cause, точечный фикс, повтор Step 1.
- [ ] **Step 3: Commit (если были фиксы Step 2; иначе пропустить)**
```bash
git add tools/context-verity.mjs tools/context-verity.test.mjs
git commit -m "fix(context-verity): регрессия tools-vitest GREEN (sub-plan A Task 6)"
```
---
## Self-Review (writing-plans)
**1. Spec coverage:**
- §5.5 артефакт `{id,claim,ref,kind}` + `anchor`/`derivation_ref` → Task 1/3. ✅
- §5.6 context-verity резолв по символу (SE-1) → Task 2. ✅
- §5.5 secure-default downgrade (S2) → Task 3/4. ✅
- §5.6 пустой артефакт ≠ проверен (VA-9) → Task 4. ✅
- ✅O2 freeze-side guard → Task 5 (wiring в plan-lock → sub-plan C, явно отложено). ✅
- Регрессия → Task 6. ✅
- **Вне A (→ C):** §5.4 staleness-поле, §5.3 слоистый граф, §6 живой шов, §6.2 вход наставника. НЕ покрыты намеренно (другие sub-plan).
**2. Placeholder scan:** реальный код в каждом code-шаге; команды Run с ожидаемым выводом; нет «TBD». ✅
**3. Type consistency:** `parseRef``{file,line}`; `resolveCitation``{resolved,reason}`; `verifyArtifact``{ok,flagged,downgraded,extractedCount,entries}`; `artifactHasUnresolvedExtracted`→boolean. Имена согласованы между задачами. ✅
**Известное ограничение (честно):** `anchor`-резолв проверяет НАЛИЧИЕ подстроки в файле, НЕ её позицию у hinted-строки (SE-1: строка — подсказка, не якорь). Это осознанно — номера строк хрупки. Точность «у нужной строки» — design-choice O-вопрос для sub-plan C при необходимости (сейчас наличие в файле достаточно для anti-fabrication).
@@ -0,0 +1,317 @@
# Живой роутер-наставник — спека пере-сборки (single live flow)
**Статус:** ЧЕРНОВИК. **R6.2.** R1 черновик → audit-context-building → sharp-edges (§12) → variant-analysis (§13) → systematic-debugging (§14) → 2-й адверсариал R5 (§15). **R6** — крупная переработка под редизайн: ДР-1..6 + P1 (§1.5), unified-цикл (§4), round-3 анализ кода. **R6.1** — фолд round-4 ре-адверсариала (8 SE-R7 + 3 системных). **R6.2** — фолд дизайн-микропрохода: 6 MUST-fix open'ов разрешены (O2/O13/O16/O17/O18/O19, §10). Дальше: writing-plans по sub-plan A-E.
**Дата:** 2026-06-10. **Эпик:** «роутер-наставник». **Кодовая фраза:** «роутер-наставник».
**Объём (одобрено владельцем):** живой шов наставника + проверенный контекст + ОДИН итеративный цикл поверх машин М1–М7; активация settings.json — шаг владельца, не в scope.
**Обозначения.** `[ФАКТ file:line]` код · `[ФАКТ D-N]` design-notes 2026-06-01 · **[ПРЕДЛОЖЕНИЕ]** новое · **[ДР-N]** §1.5 · **[SE/VA/CD-N]** §12-14 (R5) · **[R2-*]** §15 · **[CD-R6-N]/[SE-R6-N]** round-3 · **[SE-R7-N]** round-4 · **[✅O-N]** разрешённый open · `⬅OPEN`.
> ✅ Пройдено: R1 audit · sharp-edges · variant · systematic-debugging · R5 второй адверсариал · R6 round-3 на коде машин · R6.1 round-4 ре-адверсариал · **R6.2 дизайн-микропроход (6 MUST-fix разрешены).**
---
## §0. Что изменилось
**R5 → R6:** §1.5 ДР дословно · §4 один цикл · §8 FOLD в §4 · §3/§5/§6/§7 приземление ДР + CD-R6 + SE-R6 · CD-R6-A архитектурная честность.
**R6 → R6.1 (round-4):** 3 системных анти-паттерна устранены (S1 «ИЛИ»→каноничный / S2 controller-string→secure-default / S3 плоский O-список→tier) + 3 изолированных + §12 round-4 реестр.
**R6.1 → R6.2 (дизайн-микропроход 2026-06-10):** 6 MUST-fix open'ов РАЗРЕШЕНЫ выбором владельца:
- **✅O2** verity: гибрид — флаг при построении + `freezePlan` блокирует неразрешённую EXTRACTED (§5.6).
- **✅O13** escape канон `skill:<полный input.skill>` нормализованный (§6 NB).
- **✅O16** staleness: inline-поле `{stale, commits_behind, uncommitted}` в граф-секции (§5.4).
- **✅O17** task-id: persisted first-plan-anchor (§6.3).
- **✅O18** judge_mode mismatch: WARN-лог + owner-резюме, fail-safe направление (§7.3).
- **✅O19** `MENTOR_PROBE_CAP=2` файла/круг (§5.7).
---
## §1. Контекст и проблема
1.1 **Живого наставника НЕТ.** Код собран (`router-engine.mjs`), зовут ТОЛЬКО тесты `[ФАКТ router-engine.mjs:6-7]`. Роутер=наставник `[ФАКТ :106]`. `buildRouterPrompt` СОБРАН, но НЕ ПОДКЛЮЧЁН.
1.2 **Дисциплина «enforce by construction», без соавтора.** `[ФАКТ 2026-06-08-...machine-7-design.md:69,246]`.
1.3 **Предел L2.** Наставник `[ФАКТ router-engine.mjs:98]`; судья слеп `[ФАКТ judge-engine.mjs:44,55-57+:12,47; D30]`. Оба слепы к ПРОЕКТУ → фантазии Claude ловит владелец `[ФАКТ L2 design-notes:172]`.
1.4 **Собрано, не заведено:** судья (A1; обёртка `enforce-judge-gate.mjs` режимы inert/shadow/live-block `[ФАКТ :6-8]`), печать (`plan-lock.mjs`/`seal-orchestration.mjs`/`judge-seal-channel.mjs`), `refResolves` `[ФАКТ plan-lock.mjs:226]`.
**Две проблемы, запустившие редизайн (владелец):**
1. **Разную литературу читать по-разному, разными скилами.** → закрыто ДР-1/ДР-5.
2. **Наставник слишком слеп** в разгаре проекта. → закрыто ДР-3/ДР-P1.
---
## §1.5. Решения сессии — ДР-1..6 + P1 (ЯДРО, дословно)
**ДР-1 (гранулярность + чтение):**
- Единица плана = «уверенная растяжка до следующей НЕИЗВЕСТНОСТИ» (вар. B).
- Роутер задаёт крупность + ГРОМКОСТЬ церемонии по сложности/риску (вар. C) через `LEVEL_SKIP_CATEGORIES` `[ФАКТ router-engine.mjs:29]` + `detectHighRisk` `[ФАКТ :19]`. Пол C = atomic-план + роутер-выбор-скила-чтения, НИКОГДА не ноль.
- Свободного чтения НЕТ. Свободно ТОЛЬКО: чтение графа + написание плана. Любое чтение СЫРЬЯ = гейченый шаг, роутер выбирает reading-скил под тип контента (= решение проблемы 1). Граница: пред-проверенная карта (граф) — свободно; свежее понимание из сырья — под воротами.
**ДР-2 (свежесть):** авто-ИНКРЕМЕНТАЛЬНОЕ освежение графа (по git-diff с последнего снимка) ПЕРЕД заходом к наставнику. Что именно освежать/слать — уточняет P1.
**ДР-3 (понимание наставника + радары пропусков):**
- Слой 0 = прунённый граф-СТРУКТУРА (имена+связи+capabilities, БЕЗ содержимого) — ВСЕГДА (дёшево, «карта метро»). Это и есть «поверхностно».
- Слой 1 = зона задачи (релевантная партиция, освежённая, + проверенный контекст). Роутер дозирует глубину. Наставник РАССУЖДАЕТ, не читает по умолчанию.
- Пропуски ловим лестницей: граф-радар (файл-уровень: тронул X, граф связывает с Y — где Y?) + скелет-радар (раздел-уровень: grep заголовков/сигнатур, Claude отчитывается по КАЖДОМУ пункту скелета: затронуто/не релевантно/не читал) + строгий reading-скил (внутри-раздела, предотвращение, ДР-1) + машинная context-verity (верность цитат, НЕ наставник читает) + НАСТАВНИК МОЖЕТ САМ прочитать подозрительный файл/раздел (по конкретному подозрению, с обоснованием, нужным скилом, маленький бюджет — ПРОВЕРОЧНОЕ чтение критика, НЕ свободное чтение автора) + владелец (остаток). Сокращаем, не обнуляем (L2-пол).
**ДР-4 (информированность vs независимость):** информированный наставник + СЛЕПОЙ судья `[ФАКТ judge-engine.mjs:12]` — намеренная ПАРА. Захват-резистанс = РАСШИРЕНИЕ существующего «поспори-с-собой / не глотай молча / воздержание 5.2» `[ФАКТ router-engine.mjs:107-109 + :152-153]` с «выбора скила» на разбор плана-ПО-ПУНКТАМ. НЕ новый механизм. Слепота судьи + owner-гейт — backstop'ы.
**ДР-5 (выбор reading-скила):** тип контента = из дешёвых метаданных (расширение + путь + узел графа) + grep-заголовок fallback; неоднозначно → воздержание 5.2 (переспрос). Рекурсии нет.
**ДР-6 (СИММЕТРИЯ спора):** спор наставник↔Claude ДВУСТОРОННИЙ. Любая сторона, выдвигая (роутер — дозапрос/чтение/правку/возражение; Claude — ОТКАЗ принять), ОБЯЗАНА дать обоснование. Не сошлись за 3 круга → к ВЛАДЕЛЬЦУ — в ОБОИХ направлениях.
**ДР-P1 (граф 6305 узлов — НЕ слать целиком):**
- Прунинг мусора (build/node_modules/бэкапы/осиротевшее — targets ПРОВЕРИТЬ против реального graphify-out, НЕ выдумывать).
- Партиция = вар. C: свернуть 1009 communities в ~10-15 человеко-именованных «районов».
- Две резолюции: слой 0 = карта районов (всегда, дёшево); слой 1 = детали нужного района (роутер выбирает под задачу, освежается per ДР-2).
- + Наставник вправе ДОЗАПРОСИТЬ соседний район (с обоснованием) для полной оценки — дешёвое чтение КАРТЫ (не файлов), отдельный бюджет, конструктивная форма воздержания. Лечит риск «дали не тот район».
---
## §2. Фундамент (🔒 неизменен) — F1-F6 держатся; ДР РАСШИРЯЮТ, не заменяют
| # | Инвариант | Якорь |
|---|-----------|-------|
| F1 | План — ПЕРВЫМ; ничего кроме плана; оба слоя | `[ФАКТ D11/D12]` |
| F2 | Два слоя; сила проверки по фазе | `[ФАКТ 6.5/D33]` |
| F3 | Наставник — СОАВТОР; будится САМ (A0); спорит кругами | `[ФАКТ D24/D34/D35/D16]` |
| F4 | Тупик наставник↔Claude → ВЛАДЕЛЕЦ (~3 круга) | `[ФАКТ D34 :190]` |
| F5 | Замороженный план → СУДЬЯ-ворота + надзор | `[ФАКТ D30 :178]` |
| F6 | ЦЕЛЬ владельца, МЕТОД наставника | `[ФАКТ D29 :172]` |
---
## §3. Цель и не-цели (scope)
**Цель.** Живой шов наставника + конструкция проверенного контекста + ОДИН итеративный цикл.
**В scope:** §5 проверенный контекст; §6 наставник-шов; §7 owner-гейт+заморозка→судья (A1); §4 единый цикл.
**НЕ в scope:** активация settings.json (владелец); детали A1; **пересмотр М2/М5/М6 — встраиваемся ПОВЕРХ (аддитивно — CD-3).**
**[CD-R6-A] Архитектурная честность.** Движки ОДНОКРАТНЫ: `runRouter` `[ФАКТ router-engine.mjs:140]`; `runJudge` `[ФАКТ judge-engine.mjs:81]`; стена `[ФАКТ enforce-supreme-gate.mjs:135-181]`. Поток ИТЕРАТИВЕН → оркестрация контроллером. Машины энфорсят **ЧЕКПОЙНТЫ** (заморозка/печать/судья/owner-гейт), диалог — контроллер-orchestrated. Обещания спеки ограничены (asymptote floor `[ФАКТ memory feedback_asymptote_floor]`).
---
## §4. Поток целиком — ОДИН итеративный цикл (unification)
Разговорный и реализационный циклы СИММЕТРИЧНЫ: «план → роутер → (владелец) → судья → action → новый план». §8 — тот же цикл, action варьируется.
```
Промт владельца
→ [Claude молчит — F1]
↻ ИТЕРАЦИЯ (петля):
1. ПЛАН-С-ОБОСНОВАНИЯМИ-ПО-ПУНКТАМ (единица = «растяжка до неизвестности», ДР-1;
громкость по риску detectHighRisk:19/LEVEL_SKIP:29)
2. РОУТЕР-НАСТАВНИК будится СТРУКТУРНО (A0) `[ФАКТ master-roadmap.md:136]`
вход: промт + журнал переговоров ЗАДАЧИ (D36) + ПРОВЕРЕННЫЙ контекст (§5)
+ слой-0 карта районов (ВСЕГДА, ДР-3/P1) + слой-1 район + skill-каталог + контракты
→ расширяет план + скилы → круги (≤MENTOR_ROUND_CAP=3, симметрия ДР-6, память per-ЗАДАЧЕ)
→ тупик → ВЛАДЕЛЕЦ (F4, в ОБА направления)
3. СОГЛАСОВАНО → OWNER-ГЕЙТ-1 (явное одобрение, VA-1; концизное резюме, R2-SE-a)
4. ЗАМОРОЗКА (требует СОДЕРЖАТЕЛЬНЫЙ mentor-вердикт на choke freezePlan — VA-8/CD-R6-C)
5. СУДЬЯ-ВОРОТА gate-2 (СЛЕП — F5/D30)
6. ACTION (=шаг плана `[ФАКТ enforce-supreme-gate.mjs:135-181]`):
читать-граф (свободно) | читать-сырьё (гейчено, reading-скил ДР-1/5)
| собрать | спросить-владельца | сделать
→ надзор сигналит СЕМАНТИЧЕСКИЙ дрейф (guide, НЕ блок; VA-4/CD-6)
→ радары ДР-3 как проверка ПОЛНОТЫ исполнения (Q3)
7. РЕЗУЛЬТАТ → НОВЫЙ план → ↻ к п.1
⊗ ТЕРМИНАЦИЯ петли (SE-R7-6): выход ТОЛЬКО когда владелец явно объявляет «цель достигнута»
ЛИБО судья gate-3 `goal_achieved` `[ФАКТ judge-engine.mjs:26]` даёт GO на завершение.
Контроллер сам петлю НЕ закрывает.
```
**[Q3-инсайт]** Один цикл, параметризованный типом action. **[SE-R7-1]** Тип action security-критичен; в impl-режиме стена ВЫВОДИТ тип из (tool + path + plan-step), НЕ из controller-строки; в разговорном — дисциплина (CD-R6-A).
---
## §5. Конструкция проверенного контекста (фаза «понимание» цикла)
5.1 **graphify** — структурная карта `[ДР-P1]`. 5.2 **audit-context-building** — построчно.
5.3 **Слоистая подача графа (ДР-3 + ДР-P1).** **[ПРЕДЛОЖЕНИЕ]** Слой-0 = прунённая граф-СТРУКТУРА → ~10-15 «районов» (свёртка 1009 communities) — ВСЕГДА. Слой-1 = детали нужного района. **[CD-R6-G]** Project-граф — ОТДЕЛЬНАЯ секция промпта, НЕ skill-каталог; `buildRouterPrompt` разделяет `catalog` и `graph` (`groundTrace`) `[ФАКТ router-engine.mjs:99,148]` — слать прунённый каталог-район, заземлять против полного. Переписать «(100%)» `[ФАКТ :114]`. Прунинг-targets ПРОВЕРИТЬ против graphify-out.
5.4 **Свежесть (ДР-2) — staleness-сигнал каноничный (S1, ✅O16).** **[ПРЕДЛОЖЕНИЕ]** Каноничный МИНИМУМ: **inline-поле staleness в граф-секции промпта** `{stale:true, commits_behind:N, uncommitted:M}` — наставник рассуждает, ЗНАЯ о staleness, дёшево. Pre-mentor refresh — **enhancement поверх**, НЕ замена (не «триггер ИЛИ сигнал» — сигнал ВСЕГДА). **[CD-R6-D]** Сущ. `graphify-safe-update.mjs` — POST-COMMIT `[ФАКТ header]`, doc → флаг `[ФАКТ :127-141]`, код → AST-merge `[ФАКТ :143-190]`; наставник зовётся ДО коммита → триггер не совпадает с нуждой → потому каноничен СИГНАЛ, не refresh.
5.5 **Артефакт контекста — формат + secure-default (S2).** **[ПРЕДЛОЖЕНИЕ]** `{ id, claim, ref:"file:line", kind:"EXTRACTED|INFERRED" }`. **[SE-2]** `INFERRED``derivation_ref` + sign-off владельца + лимит доли (O9). **[secure-default]** `kind` НЕ доверяется controller-ставимым: `EXTRACTED` ОБЯЗАН пройти context-verity-резолв (§5.6); НЕ прошёл → понижается до `INFERRED` (sign-off). Мис-метка INFERRED→EXTRACTED не обходит owner-sign-off.
5.6 **context-verity — гибрид флаг+freeze-блок (✅O2).** **[ПРЕДЛОЖЕНИЕ]** Чистый `tools/context-verity.mjs` по образцу `refResolves` `[ФАКТ plan-lock.mjs:226]`. **[SE-1]** Резолв по СИМВОЛУ/контенту. **[✅O2]** verity ФЛАГает неразрешённые при построении (не блок посреди потока); **`freezePlan`-чекпойнт ОТКАЗывает печать артефакта, если в нём есть неразрешённая EXTRACTED-цитата** (использует существующий чекпойнт CD-R6-A, не mid-flow блок). **[VA-9]** Пустой артефакт (0 EXTRACTED) НЕ «проверен». **[R2-SE-g]** Субстанция ≠ счёт. **[SE-4]** Чтит owner-escape (§6 choke).
5.7 **Лестница радаров + bounded probe (✅O19).** Граф-радар + скелет-радар (Claude отчитывается по КАЖДОМУ пункту) + строгий reading-скил + context-verity + наставник-сам-читает + владелец. **[✅O19]** Критик-чтение наставника = `MENTOR_PROBE_CAP=2` файла/раздела на КРУГ (подозрение + сосед; ×MENTOR_ROUND_CAP=3 → макс 6/задача); НЕ «малый» аспирационно — иначе free-reading backdoor мимо ДР-1. Сокращаем, не обнуляем (L2-пол).
5.8 **Типизация чтений (CD-R6-B).** `isObserveOnly` пускает Read/Grep/Glob БЕЗУСЛОВНО `[ФАКТ enforce-supreme-gate.mjs:43]`. 4 вида: (1) граф-карта — свободно; (2) **авторское чтение СЫРЬЯ — цель гейта ДР-1**; (3) проверочное чтение критика (5.7, bounded ✅O19); (4) harness-обязательное. **R6:** reading-gate ДР-1 ТОЛЬКО на вид 2; виды 1/3/4 свободны. Имя Read-tool не отличает вид 2 от 4 → гейт ДР-1 энфорсим ТОЛЬКО в impl-режиме (frozenPlan → raw-read = plan-step). **[SE-R7-5]** В разговорном — дисциплина + read-LOG (сигнал владельцу о фронт-лоаде сырья до заморозки), не блок. CD-3-граница: новый предусловный слой ПЕРЕД observe-only.
5.9 **discovery-interview SYSTEM — ⬅OPEN (O3)** (дубль VA-3).
5.10 **Ревью владельца → проверенный контекст.** **[SE-6]** verity = РЕЗОЛВ цитат, НЕ честность. Ревью ОБЯЗАТЕЛЬНЫЙ. **verity ≠ истина.** **[VA-11]** Артефакт human-reviewable (O12). **[R2-SE-a/R2-VA-meta]** Каждый owner-гейт — КОНЦИЗНОЕ резюме; owner-точки консолидировать; ≥1 substance-гейт на задачу — неуклоняемый и редкий (O15, §15).
---
## §6. Наставник-шов (фаза «менторинг» цикла — главный OPEN)
> **🔒 Сквозной инвариант (R2-VA-7 — централизация escape).** Каждый НОВЫЙ слой-ворота чтит owner-escape. ОДНА choke-точка: стена первой строкой `decideMode` зовёт `escapeGrantOpen` `[ФАКТ enforce-supreme-gate.mjs:193]`, ДО плановых проверок; allow mode:'escape' БЕЗ advanceTo `[ФАКТ :194]`. Новые гейты — к ТОМУ ЖЕ choke (O14). **[SE-R6-1/✅O13]** Скил-escape канон сейчас = `write:<cwd>` агностичен `[ФАКТ escape-grant.mjs:43-44]`. **✅O13 (MUST-fix реализации):** канон `skill:<полный input.skill>` нормализованный (lowercase/trim; e.g. `skill:audit-context-building:audit-context-building`) — однозначно, совпадает с тем, что видит владелец в AskUser, без коллизий. Грант привязан к КОНКРЕТНОМУ скилу.
6.1 **Будится структурно (A0) + вердикт-substance.** **[ПРЕДЛОЖЕНИЕ]** Хук на запись/обновление плана (A0 `[ФАКТ master-roadmap.md:136]`), пишет вердикт.
**[VA-8 + CD-R6-C + S1 — КАНОНИЧНЫЙ choke]** Энфорсмент на ЗАМОРОЗКУ через ЕДИНСТВЕННУЮ точку — `freezePlan` `[ФАКТ plan-lock.mjs:62]` (единственное место печати плана; 5 функций печати сходятся в него). **НЕ «freezePlan ИЛИ frozenPlan-проверка».** Секвенс: наставник со-авторит → owner-гейт-1 → `freezePlan`(требует mentor-вердикт) → судья gate-2.
**[R2-SE-c + SE-R7-8 — СОБСТВЕННЫЕ слоты]** Гейт проверяет вердикт СОДЕРЖАТЕЛЕН по СОБСТВЕННЫМ слотам наставника (непустые, адресуют план ПО-ПУНКТАМ) — НЕ заимствует `validateVerdictSlots`/линзы судьи `[ФАКТ judge-engine.mjs:15,19-27]`. Паттерн-зеркало, но СВОИ слоты.
**[SE-R6-6 — substance, не presence]** Содержательный mentor-вердикт = РЕАЛЬНЫЙ заход наставника (непустые слоты + реальный router-вызов), НЕ stub/degraded. Зеркало: судья недоступен → `{decision:'GO', wired:false}` `[ФАКТ enforce-judge-gate.mjs:67-69,81]` НЕ суд.
**[CD-3]** Чек — ОТДЕЛЬНОЕ предусловие к `freezePlan`; seal/`plan-lock`/М6 не трогаются.
**[SE-3/R2-SE-h]** fail-CLOSED; на блок — owner-escape. «Наставник ОШИБСЯ» (таймаут/краш → RETRY) vs «ЗАБЛОКИРОВАЛ» (legit → escape).
6.2 **Вход — проверенный контекст.** **[ПРЕДЛОЖЕНИЕ]** `buildRouterPrompt` `[ФАКТ router-engine.mjs:98]` + журнал переговоров ЗАДАЧИ `[ФАКТ D36:217-218]` + ПРОВЕРЕННЫЙ КОНТЕКСТ (§5) + слой-0/слой-1 project-граф (§5.3).
**[CD-R6-H — НЕ противоречие]** 2026-06-05 `[ФАКТ :16-17,46]` не кормил живым контекстом. Мы НЕ кормим сырым чатом; контекст — ПРОВЕРЕННЫЙ артефакт. ОСОЗНАННАЯ ревизия `[ФАКТ handoff:60]`. Судья остаётся слеп (§7.2) `[ФАКТ judge-engine.mjs:12]`; асимметрия намеренна (ДР-4). ⬅OPEN (O8).
**[R2-VA-5]** Вердикт привязан к ХЕШУ плана `[ФАКТ enforce-supreme-gate.mjs:84 R-27]`; счётчик/журнал — к ЗАДАЧЕ.
6.3 **Состояние кругов (память per-ЗАДАЧЕ) + task-id (✅O17).** **[ПРЕДЛОЖЕНИЕ]** Счётчик + история `[ФАКТ D36:217-218]`. **[SE-7]** `MENTOR_ROUND_CAP=3`; 0 = не высказался = не заморозить; потолок → эскалация. **[VA-7→R2-SE-d]** Счётчик/журнал — per-ЗАДАЧЕ.
**[SE-R6-4 + S1 — tamper-evident]** Журнал переговоров ≠ М1 `action-journal` `[ФАКТ action-journal.mjs:17]`. **tamper-evident (хеш-цепь зеркало М1)** каноничен; НЕ «ИЛИ derivable».
**[✅O17]** task-id = **persisted first-plan-anchor**: присваивается A0-хуком при ПЕРВОМ плане задачи, ПЕРСИСТИТСЯ, НЕИЗМЕНЕН весь жизненный цикл (re-issue плана с новым хешем НЕ сбрасывает; стабилен через re-issue, различен между задачами — НЕ plan-hash, НЕ prompt).
6.4 **Эскалация → владелец (симметрия ДР-6).** `[ФАКТ F4/D16/D34/D36; :274]` Резюме спора (ОБЕ позиции). **[ДР-6]** двусторонний; каждая сторона ОБЯЗАНА обоснование; 3 круга → владелец в ОБА направления.
**[CD-R6-F]** F6 «МЕТОД наставника» `[ФАКТ D29:172]` vs ДР-6: наставник ВЕДЁТ метод → Claude вправе оспорить с обоснованием → 3 круга → владелец (F4). Не унилатерально.
6.5 **Под стеной — семена.** `[ФАКТ enforce-supreme-gate.mjs:25-27,196-198]`. **NB-мина** `[ФАКТ master-roadmap.md:149 K4]`. **[SE-5]** Наставнику НЕ seed-слот; пишет через канал гейта-1 (O5).
**[CD-R6-E]** «СВОБОДНЫХ действий НЕТ» vs seed-allowlist `[ФАКТ enforce-supreme-gate.mjs:31-36,136,196-197]` (bootstrap D12/D13). **Определение:** «свободное действие» = «мутирующее исполнение вне замороженного плана»; пред-плановый свободный набор = seeds + observe + AskUser/EnterPlanMode.
6.6 **Две роли (в одном цикле).** `[ФАКТ master-roadmap.md:141 ПОСЛЕ; :147+ ДО; D34/D35]` (1) СОАВТОР ДО; (2) ВЕДЁТ ПОСЛЕ (§4 п.6). Разделены ФАЗОЙ.
6.7 **Выбор reading-скила (ДР-5) — machine-derived (S2).** **[ПРЕДЛОЖЕНИЕ]** Тип контента из метаданных (ext + путь + узел графа) + grep-fallback; неоднозначно → `abstain 5.2` `[ФАКТ router-engine.mjs:152-153]`. **[SE-R6-7/SE-R7-1]** closed-list (как `LEVEL_SKIP_CATEGORIES` `[ФАКТ :29]`) + machine-derived (ext/graph-node, не controller-string) + grep-fallback; мис-классификация ловится abstain.
---
## §7. Owner-гейт → Заморозка → СУДЬЯ-ворота (чекпойнт цикла)
7.0 **Owner-гейт-1 на ПЛАН (VA-1).** `[ФАКТ master-roadmap.md:337]` Порядок: согласовано → owner-гейт-1 → заморозка → судья → exec. **[CD-4]** F4 (опц.) + §7.0 (всегда). **[R2-SE-a]** КОНЦИЗНОЕ резюме (≤10 пунктов + дельта). Консолидировать (O15).
7.1 **Печать гейтит СУДЬЯ.** `[ФАКТ D30; judge-seal-channel.mjs:2-5]` Наставник не печатает `[ФАКТ :6]`. **Carve-out** `[ФАКТ :8-9,32-36]`: деньги (`detectMoney` :24-29) ИЛИ тупик → ВЛАДЕЛЕЦ (F4). **[SE-8/SE-R6-2]** `detectMoney` подстрочный `[ФАКТ :23-24]` → мис-триггер; безопасное направление, кормит fatigue → сузить ⬅OPEN (O11).
7.2 **Вход судьи — слеп.** `[ФАКТ judge-engine.mjs:44,55-57+:12,47; D30]` §6.2 сюда НЕ распространяется. Линзы `[ФАКТ :19-27]`; пост-чек `[ФАКТ :81-112]`; сомнение→блок `[ФАКТ :67-70]`.
7.3 **Проводка A1 + judge_mode сигнал (✅O18).** `[ФАКТ enforce-judge-gate.mjs:6-8,209-225]` Режимы inert/shadow/live-block; Гейт-1(specs)>Гейт-2(plans) `[ФАКТ :58-60]`; судья недоступен → degraded-GO `[ФАКТ :67-69]`. ⬅OPEN (O6).
**[SE-R6-3/✅O18]** double judge_mode silent-cliff: энфорсмент только если ОБЕ печати `'live-block'` `[ФАКТ enforce-supreme-gate.mjs:211]`; рассинхрон → тихо в разговорный `[:212-216]`; footgun = ТИШИНА. **✅O18:** направление fail-safe СОХРАНИТЬ (→разговорный, не блок — не кирпичить легитимный переход), но ГРОМКО: **WARN-лог** + строка в **owner-резюме гейта-1** «энфорсмент off: judge_mode рассинхрон план≠артефакт». Владелец знает.
---
## §8. Исполнение под надзором — СВЁРНУТО в §4 (action как узел петли)
- **Действие = шаг плана** `[ФАКТ enforce-supreme-gate.mjs:135-181]`. Журнал пред-записывает намерение ДО allow (Δ3) `[ФАКТ :244-249]`; разрушительный in-plan шаг стена не благословляет (Δ7) `[ФАКТ :170-172; classify-destructive.mjs:29-39]`.
- **Надзор** — сигналит СЕМАНТИЧЕСКИЙ дрейф (НЕ блокирует) `[VA-4]`. «Ведёт»=guide `[CD-6]`. Форма ⬅OPEN (O7).
- **[Q3]** Радары ДР-3 = проверка ПОЛНОТЫ исполнения; ДР-1 громкость на рискованный шаг.
---
## §9. Новое vs существующее
Артефакт/`context-verity.mjs`, слоистый project-граф (§5.3), staleness-поле (§5.4), контекст-как-вход (§6.2), журнал переговоров tamper-evident + task-id (§6.3), живой шов (§6), escape-канон `skill:<name>` (§6 NB), reading-typing (§5.8), единый цикл + termination (§4) — **НОВОЕ**. owner-гейт-1 (A1), гейт `freezePlan` на mentor-вердикт + verity-freeze-блок (аддитивно), judge_mode WARN — поверх существующего. **Коррекция R5:** стена М2/пол М5/печать М6, судья+A1, `buildRouterPrompt`**СОБРАНО, но НЕ ПОДКЛЮЧЕНО** `[ФАКТ router-engine.mjs:6-7]`.
---
## §10. Открытые вопросы — TIERED
**✅ РАЗРЕШЕНО (дизайн-микропроход 2026-06-10):**
- **O2** verity → гибрид флаг + `freezePlan`-блок неразрешённой EXTRACTED (§5.6).
- **O13** escape-канон → `skill:<полный input.skill>` нормализованный (§6 NB).
- **O16** staleness → inline-поле `{stale, commits_behind, uncommitted}` в граф-секции (§5.4).
- **O17** task-id → persisted first-plan-anchor (§6.3).
- **O18** judge_mode mismatch → WARN-лог + owner-резюме, fail-safe направление (§7.3).
- **O19** `MENTOR_PROBE_CAP=2` файла/круг (§5.7).
**🟠 design-choice OPEN (обсуждаемо, не небезопасный дефолт):**
O1 артефакт где · O3 discovery-interview SYSTEM · O4 хук пробуждения · O5 канал записи=гейт-1 · O6 стыковка A1 · O7 форма надзора · O8 независимость наставника · O9 порог INFERRED · O10 механика escape-awareness · O11 сузить detectMoney · O12 размер артефакта · O14 централизованная choke escape · O15 консолидация owner-гейтов/анти-fatigue.
---
## §11. Реестр цитат (сверено на шаге 1 R6 — построчно)
**Код (✅):** `router-engine.mjs:6-7,19,29,98,106,107-109,114,140,148,152-153`; `judge-engine.mjs:12,15,19-27,44,55-57,47,67-70,81-112`; `enforce-supreme-gate.mjs:20-27,31-36,43,84,135-181,139,170-172,193-198,211-216,244-249`; `escape-grant.mjs:30-49,43-44,57-65,193`; `askuser-answer-parser.mjs:192-203,222-229`; `plan-lock.mjs:53-57,62,139-154,226`; `judge-seal-channel.mjs:2-9,22-36`; `classify-destructive.mjs:29-39,54-67`; `action-journal.mjs:17,53-68,77-82`; `enforce-judge-gate.mjs:6-8,58-60,67-69,81,129-135,209-225,233-250`; `seal-orchestration.mjs:25,36`; `graphify-safe-update.mjs:header,104-141,143-190`; `path-normalization.mjs:38-39,82-118`.
**Дизайн (✅):** `2026-06-01-...design-notes.md` (D11/D12/D16:130/D24/D29:172/D30:178/D33/D34:190,274/D35:198/D36:217-218; L2:172); `plans/2026-06-03-...master-roadmap.md:136,141,147+,149,337`; `specs/2026-06-05-...conversational-input...:16-17,46`; `specs/2026-06-08-...machine-7-design.md:69,246`; `specs/2026-06-09-...A1-judge-gate2-wiring-design.md`; `memory feedback_asymptote_floor`.
> **NB.** R6 round-3 сверял РЕАЛЬНЫЙ код 13 файлов. R6.1 round-4 — ре-адверсариал на тексте. R6.2 — дизайн-микропроход (6 MUST-fix). Номера строк хрупки (SE-1) — резолв по символу.
---
## §12. sharp-edges (round-1 + round-3 + round-4)
**Round-1 (R5):** SE-1..SE-8.
**Round-3 (R6):**
| ID | Footgun | Цитата | Сев. | Митигация |
|----|---------|--------|------|-----------|
| SE-R6-1 | escape агностичен (`write:cwd`) | `escape-grant.mjs:43-44` | High | ✅O13 `skill:<input.skill>` |
| SE-R6-2 | detectMoney подстрочный → fatigue | `judge-seal-channel.mjs:23-24` | Low-Med | сузить (O11) |
| SE-R6-3 | double judge_mode silent-cliff | `enforce-supreme-gate.mjs:211` | Med | ✅O18 WARN+owner |
| SE-R6-4 | журнал переговоров мутируемый | `action-journal.mjs:17` | Med | tamper-evident (§6.3) |
| SE-R6-5 | ДР-1 reading-gate ↔ isObserveOnly | `enforce-supreme-gate.mjs:43` | High | типизация, impl-only (§5.8) |
| SE-R6-6 | degraded-GO presence≠substance | `enforce-judge-gate.mjs:67-69,81` | Med-High | `wired:true` (§6.1) |
| SE-R6-7 | reading-скил из метаданных | `router-engine.mjs:29` | Low | closed-list + abstain (§6.7) |
| SE-R6-8 | task-identity не определён | — | Med | ✅O17 first-plan-anchor |
**Round-4 (R6.1) — 3 СИСТЕМНЫХ + точечные:**
| ID | Footgun | § | Митигация |
|----|---------|---|-----------|
| **S1** | «X ИЛИ слабее-Y» в резолюциях ×3 | §5.4/§6.1/§6.3 | каноничный выбор (✅) |
| **S2** | controller-string дискриминатор ×3 | §4/§5.5/§6.7 | machine-derived/secure-default (✅) |
| **S3** | плоский O-список прячет MUST-fix | §10 | tier + ✅резолв 6 (✅) |
| SE-R7-6 | внешняя петля без termination | §4 | владелец/судья gate-3 (✅) |
| SE-R7-7 | «малый бюджет» undefined | §5.7 | ✅O19 N=2 |
| SE-R7-8 | mentor заимствует слоты судьи | §6.1 | СОБСТВЕННЫЕ слоты (✅) |
| SE-R7-5 | impl-only энфорс → стимул в разговорном | §5.8 | conversational read-LOG (✅) |
## §13. variant-analysis (round-1 + round-3)
**Round-1 (R5):** VA-1 owner-гейт · VA-6 escape=circuit-breaker · VA-8 гейт заморозки · VA-7 per-задача · VA-9 пустой артефакт · VA-11 human-reviewable · VA-4 семантический надзор · VA-3(=O3).
**Round-3 — матрица приземления ДР:**
| ДР | Первичная посадка | Вторичные швы | Аддитивно? |
|----|-------------------|---------------|------------|
| ДР-1 | М3 `:29`+`:19` | ⚠️ М2 `isObserveOnly:43` (CD-R6-B) | НЕТ — трогает М2 |
| ДР-2 | `graphify-safe-update:104-118` | ⚠️ doc-флаг-only `:127` (CD-R6-D) | частично |
| ДР-3 | М3 `buildRouterPrompt:99` | context-verity по `refResolves:226` | новое + М3-вход |
| ДР-4 | М3 `:107-109,152-153` | судья слеп `:12` | аддитивно |
| ДР-5 | М3 новый классификатор | abstain `:152-153` | аддитивно |
| ДР-6 | М3 промпт | журнал ≠ М1; тупик→владелец F4 | новый стор |
| ДР-P1 | новый слой → `:99` | catalog≠graph `:148` | новое + М3-вход |
## §14. systematic-debugging — противоречия машин (round-3)
| ID | Противоречие | Резолв |
|----|--------------|--------|
| 🔴 CD-R6-A | машины однократны ↔ поток итеративен | энфорс на ЧЕКПОЙНТАХ (§3/§15) |
| 🔴 CD-R6-B | ДР-1 нет-чтения ↔ isObserveOnly | типизация, impl-only (§5.8) |
| 🔴 CD-R6-C | VA-8 mentor-вердикт ↔ seal на judge-GO | mentor-вердикт на `freezePlan` (§6.1) |
| 🟠 CD-R6-D | ДР-2 refresh ↔ post-commit+doc-флаг | staleness-сигнал каноничный (§5.4) |
| 🟠 CD-R6-E | «свободных действий нет» ↔ seed bootstrap | «свободное»=мутирующее вне плана (§6.5) |
| 🟠 CD-R6-F | F6 метод ↔ ДР-6 Claude-отказ | иерархия ведёт→оспорить→владелец (§6.4) |
| 🟠 CD-R6-G | ДР-P1 прунинг ↔ «(100%)» + 2 графа | project-граф отд. секция (§5.3) |
| 🟢 CD-R6-H | informed-mentor ↔ 2026-06-05 | сознательная ревизия (§6.2) |
**Round-1 (R5):** CD-1 🔴 переписка→журнал плана · CD-3 🟠 аддитивно · CD-4/CD-6 🟡. НЕ противоречия: CD-2/CD-5/CD-7.
---
## §15. Предельные свойства (адверсариал R5 + архитектурный вывод R6)
**🔴 R2-VA-meta — «Presence ≠ Substance» ПРОНИЗЫВАЕТ все гейты.** Вердикт наставника (R2-SE-c/SE-R6-6/SE-R7-8), owner-одобрение (R2-SE-a), context-verity (SE-6), escape-грант (SE-R6-1) — КАЖДЫЙ удовлетворяется presence-токеном без субстанции. Единственная проверка субстанции — внимательный человек, который устаёт `[ФАКТ memory feedback_asymptote_floor]`. **Дизайн ОБЯЗАН:** (1) машинно проверять субстанцию (вердикт-слоты, релевантность, реальный router/judge-вызов); (2) консолидировать owner-точки + концизные резюме (O15); (3) ≥1 неуклоняемый редкий substance-гейт.
**🔴 R2-VA-7 — централизация escape.** ОДНА choke-точка `[ФАКТ enforce-supreme-gate.mjs:193]`; новые гейты — к тому же choke (O14).
**🔴 CD-R6-A — итеративный поток на однократных движках.** Энфорсмент на ЧЕКПОЙНТАХ, НЕ на раунд-диалоге (контроллер-orchestrated). asymptote behavioral-residual/user-approval floor. **Не дефект — граница архитектуры.**
**🔴 R6.1 round-4 урок — системность анти-паттернов.** Footgun'ы R6 рекуррентны («ИЛИ» ×3, controller-дискриминатор ×3, плоский O-список). Подтверждает R5 §15. **Правило:** N-й адверсариал ищет СИСТЕМНОСТЬ (повтор паттерна по §§), не только точечные дыры.
**Реестр round-2 (R5):**
| ID | Сев. | Митигация | Статус |
|----|------|-----------|--------|
| R2-SE-a | High | концизные резюме + консолидация (O15) | §5.10/§7.0 |
| R2-SE-c | High | вердикт СОДЕРЖАТЕЛЕН (свои слоты) | §6.1 |
| R2-SE-f | High | скил-escape канон `skill:<name>` (✅O13) | §6 NB |
| R2-SE-d | Med | счётчик per-ЗАДАЧЕ | §6.3 |
| R2-SE-h | Med | error→retry vs block→escape | §6.1 |
| R2-SE-g | Low | субстанция≠счёт | §5.6 |
| R2-SE-b | Low | escape мимо гейта-1 — владелец в контроле | — |
| R2-VA-meta | High | substance-чеки + консолидация (O15) | §15/§5.10 |
| R2-VA-7 | High | централизовать escape (O14) | §6 |
| R2-VA-5 | Med | счётчик→задача, вердикт→хеш плана | §6.2/§6.3 |
| R2-VA-8 | — | escape=универсальный circuit-breaker | §6 |
| R2-VA-9 | Low | reuse validateVerdictSlots паттерн | §6.1 |
@@ -0,0 +1,137 @@
# Handoff-2 — переезд сессии (роутер-наставник), 2026-06-10 (после R6.2 + sub-plan A)
> Самодостаточный промт для НОВОЙ сессии. Скопируй блок ниже целиком.
> Durable-копия (на случай потери чата). Зафиксированы R6.2 + 6 решений + sub-plan A + остаток B-E.
---
```
роутер-наставник. Подхвати работу из прошлой сессии. Кодовая фраза эпика: «роутер-наставник».
═══ КАК РАБОТАТЬ (жёсткие правила владельца — НАРУШАТЬ НЕЛЬЗЯ) ═══
• БЕЗ ОТСЕБЯТИНЫ. Только КОД и ДИЗАЙН. КАЖДОЕ утверждение — с цитатой (file:line / ДР-/D-/O-номер).
Прошлые сессии ехали из-за плохого чтения кода и фантазий. Сомнение — читай ещё.
• КАЧЕСТВО ПРЕВЫШЕ ВСЕГО. Скорость/экономия/цена/время — НЕ важны.
• Ничего сразу: сверь, прочитай, СПРОСИ. Каждую новую фазу/задачу и цепочку скилов — на
согласование ПЕРЕД стартом (AskUserQuestion).
• Коммиты/push/правки settings.json/keychain/ENV — делает ВЛАДЕЛЕЦ. Claude settings.json не пишет.
• Каждый ответ: 1-я строка «экономия:…», 2-я «coverage:…».
• Ветка main, чекаут: c:\моя\проекты\портал crm\Документация (русские «а/и» в пути — ловушка).
• Субагенты/Task/Workflow ЗАПРЕЩЕНЫ — всё инлайн.
• git — терминал владельца; && не работает в PS 5.1.
• CLAUDE.md в основном чекауте — ЧУЖАЯ ЗОНА параллельных сессий, НЕ трогать.
═══ ⛔ МЕХАНИКА СТЕНЫ И ESCAPE (КРИТИЧНО) ═══
Оборона М1–М6 АКТИВНА. Стена `enforce-supreme-gate` в разговорном режиме ПУСКАЕТ только семена
(writing-plans / brainstorming / discovery-interview / systematic-debugging / test-driven-development /
requesting-code-review / verification-before-completion) + чтения (Read/Grep/Glob/readonly-Bash/TodoWrite),
БЛОКИРУЕТ всё мутирующее: запись файлов, формальные скилы (audit-context-building / sharp-edges /
variant-analysis), запись кода.
Режим (б): стену НЕ снимать, ЭСКЕЙПИТЬ каждое мутирующее действие. КАК: AskUserQuestion, где ОДНА
опция = строка FLOOR-ESCAPE (>30 симв.). Владелец выбирает → `enforce-askuser-answer-parser`
(PostToolUse, уже зарегистрирован) пишет ПОДПИСАННЫЙ одноразовый грант, окно 5 мин. Затем РОВНО одно
мутирующее действие проходит. Грант ОДНОРАЗОВЫЙ — на каждое действие свой.
КАНОН (lowercase / прямые слэши / NFC — проверено по escape-grant.mjs:30-49 + path-normalization.mjs:38-39,82-118
+ caseFold=toLowerCase win32):
• запись/правка файла: FLOOR-ESCAPE: write:c:/моя/проекты/портал crm/документация/<путь в нижнем регистре>
• вызов скила (канон=cwd, СКИЛ-АГНОСТИЧЕН escape-grant.mjs:43-44):
FLOOR-ESCAPE: write:c:/моя/проекты/портал crm/документация
Семена escape НЕ требуют. Один escape = одно действие. Несколько правок в файле — ОДНИМ Write (перезапись).
⚠️ УРОК ПРОШЛОЙ СЕССИИ: окно 5 мин истекает если владелец долго отвечает между AskUser(escape) и Write.
ЗАПРАШИВАЙ escape и делай мутирующее действие В ТОМ ЖЕ ХОДУ (минимальный зазор). Если Write заблокирован
«разговорный режим» — НЕ менять канон (он верен), а перезапросить свежий грант + Write немедленно.
═══ ГДЕ МЫ В ЭПИКЕ (после сессии 2026-06-10) ═══
Эпик «роутер-наставник» — строим ЖИВОГО роутера-наставника (соавтор плана). Фаза ДИЗАЙН закрыта,
ФАЗА ПЛАНИРОВАНИЯ начата (sub-plan A написан). Стройка — потом.
СПЕКА (ПРОЧИТАЙ ПЕРВОЙ): docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md — **R6.2**.
Путь: R1 черновик → audit-context-building → sharp-edges → variant-analysis → systematic-debugging →
R5 2-й адверсариал → R6 (ДР-1..6+P1 §1.5 дословно + unified-цикл §4 + round-3 анализ РЕАЛЬНОГО кода
машин М2/М3/М4 + швы) → R6.1 (round-4 ре-адверсариал: 8 SE-R7 + 3 системных анти-паттерна) →
**R6.2 (6 MUST-fix open'ов разрешены дизайн-микропроходом)**. §0 = changelog, §1.5 = ДР дословно,
§10 = O-вопросы TIERED (✅разрешено / 🟠design-choice), §11 = реестр цитат 13 файлов, §12-15 реестры.
6 РЕШЕНИЙ МИКРОПРОХОДА (в R6.2, дословно — НЕ переоткрывать без причины):
✅O2 context-verity: ГИБРИД — флаг при построении + freezePlan ОТКАЗывает печать артефакта с
неразрешённой EXTRACTED (использует существующий чекпойнт, не mid-flow блок). §5.6.
✅O13 escape канон `skill:<полный input.skill>` нормализованный (lowercase/trim), НЕ суффикс. §6 NB.
✅O16 staleness: inline-поле {stale, commits_behind, uncommitted} в граф-секции промпта; СИГНАЛ
каноничен, refresh — enhancement поверх (не «триггер ИЛИ сигнал»). §5.4.
✅O17 task-id: persisted first-plan-anchor (присвоен A0-хуком при ПЕРВОМ плане задачи, неизменен
весь жизненный цикл; re-issue не сбрасывает). §6.3.
✅O18 judge_mode mismatch: WARN-лог + строка в owner-резюме гейта-1; fail-safe направление
(→разговорный) СОХРАНЕНО, не блок. §7.3.
✅O19 MENTOR_PROBE_CAP=2 файла/круг (макс 6/задача при MENTOR_ROUND_CAP=3). §5.7.
ПЛАНЫ: docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md — **sub-plan A НАПИСАН**
(6 TDD-задач, placeholder-free: parseRef / resolveCitation / verifyArtifact / secure-default downgrade /
artifactHasUnresolvedExtracted guard / регрессия; wiring guard'а в plan-lock.freezeArtifact ОТЛОЖЕН в C).
ДЕКОМПОЗИЦИЯ R6.2 на 5 sub-plan (writing-plans Scope Check — каждый = работающий тестируемый софт):
A (НАПИСАН) — проверенный контекст: context-verity.mjs + артефакт {id,claim,ref,kind} + secure-default. §5.5/5.6.
B — слоистый project-граф + staleness: прунинг (targets ПРОВЕРИТЬ против graphify-out!) + ~10-15 районов
(свёртка 1009 communities) + inline staleness-поле (✅O16). §5.3/5.4. Зависит: graphify-out.
C — ЖИВОЙ ШОВ наставника (ЯДРО): A0-хук пробуждения + buildRouterPrompt-вход (проверенный контекст +
журнал переговоров задачи + слой-0/1 граф) + runRouter live caller + журнал переговоров tamper-evident +
task-id (✅O17) + mentor-вердикт freeze-gate на freezePlan choke (СОБСТВЕННЫЕ слоты, не судьи) +
wiring artifactHasUnresolvedExtracted из A в freezeArtifact (✅O2). §6/6.1/6.3. Зависит: A + B.
D — дисциплина чтения: reading-typing gate (вид-2 raw-read, impl-only) + reading-скил селектор (ДР-5,
machine-derived) + conversational read-LOG (SE-R7-5) + MENTOR_PROBE_CAP=2 (✅O19). §5.8/6.7/5.7.
Аддитивно к стене (CD-3).
E — footgun-фиксы: escape `skill:<name>` (✅O13, escape-grant.mjs canonicalAction) + judge_mode WARN
(✅O18) + detectMoney сузить (O11) + loop-termination (§4, владелец/судья gate-3). Существующие машины.
═══ ЧТО ДАЛЬШЕ — выбор владельца (НЕ начинать без «вперёд») ═══
Варианты: (1) writing-plans sub-plan B/C/D/E (по одному, сверять структуру ДО записи); (2) реализация
sub-plan A инлайн (executing-plans, Task 1→6, каждый код-Write под escape, регрессия tools-vitest);
(3) что-то ещё по решению владельца. ПЕРВОЕ ДЕЙСТВИЕ: прочитать R6.2 + sub-plan A + этот handoff,
подтвердить, спросить владельца какой из вариантов, дождаться «вперёд».
⚠️ Файлы НЕ закоммичены (git зажат у Claude). Спека R6.2 + sub-plan A + этот handoff на диске uncommitted.
Команда владельцу: git add docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md
docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md
docs/superpowers/specs/2026-06-10-router-mentor-session-handoff-2.md && git commit -m "docs(router-mentor): R6.2 + sub-plan A + handoff-2"
═══ КЛЮЧЕВЫЕ ФАЙЛЫ КОДА (цитаты сверены построчно round-3, 13 файлов) ═══
tools/router-engine.mjs (М3 наставник, НЕ живой :6-7) — buildRouterPrompt:98, runRouter:140,
воздержание 5.2 :152-153, LEVEL_SKIP:29, detectHighRisk:19, groundTrace:73-79, catalog/graph :99,148.
tools/judge-engine.mjs (М4 судья слеп :12) — buildJudgePrompt:44, validateVerdictSlots:15,
VOTE_LAYOUTS:19-27 (gate3 goal_achieved :26), classifyByReversibility:67-70, runJudge:81-112.
tools/enforce-supreme-gate.mjs (М2 стена) — isSeed:31-36, isObserveOnly:39-64 (Read always-allow :43),
decideMode:188 (escape choke :193 ПЕРВОЙ строкой :194), decide:135-181, judge_mode whitelist :211-216,
Δ7 разрушительное :170-172, Δ3 журнал-до-allow :244-249, R-27 resolveStepPtr:84.
tools/escape-grant.mjs — canonicalAction:30-49 (Skill→write:cwd агностичен :43-44), findOpenGrant:57-65,
окно 5мин FLOOR_ESCAPE_WINDOW_MS:17, loadFloorEscapes key-gated :96-104.
tools/askuser-answer-parser.mjs — toFloorEscapeRecord:192-203, verifyFloorEscapeRecord:222-229.
tools/plan-lock.mjs — freezePlan:62, freezeArtifact:194, refResolves:226, validatePlanTree:139-154,
assertValidJudgeMode:53-57, treeLeafAt:126-135.
tools/judge-seal-channel.mjs — sealOnApproval:48-67, detectMoney MONEY_RE :23-24 (подстрочный, O11),
requiresOwnerSeal:33-36 (carve-out деньги/тупик→владелец).
tools/classify-destructive.mjs — FLOOR_RE:29-39, classifyDestructive:54-67.
tools/action-journal.mjs (М1) — хеш-цепь computeEntryHash:17, verifyChain:53-68, assertSafeSessionId:77-82.
tools/enforce-judge-gate.mjs (A1/M7) — режимы :6-8,209-225, runJudgeGate:55-82 (degraded-GO :67-69,
wired :81), extractGate2Product:129-135, sealOnWiredGo:233-250.
tools/seal-orchestration.mjs — sealArtifact:25, sealPlan:36.
tools/graphify-safe-update.mjs — post-commit :header, doc→флаг :127-141, код→AST-merge :143-190.
tools/path-normalization.mjs — caseFold:38-39 (toLowerCase win32), pathNormalize:82-118 (realpath→caseFold→
forward-slash→NFC).
═══ КЛЮЧЕВЫЕ ФАЙЛЫ ДИЗАЙНА ═══
СПЕКА R6.2 (выше). design-notes 2026-06-01 (D11/D12/D16:130/D24/D29:172/D30:178/D33/D34:190,274/D35:198/
D36:217-218; L2:172). master-roadmap 2026-06-03 (A0:136 / роли ПОСЛЕ:141 / ДО:147+ / K4-мина:149 /
owner-гейт-1:337). conversational-input 2026-06-05:16-17,46 (НЕ кормить сырым — осознанно ревизуем).
machine-7 2026-06-08:69,246. A1-judge-gate2-wiring 2026-06-09. machine-4-judge 2026-06-05.
memory feedback_asymptote_floor (asymptote ~0.5% irreducible).
═══ КВИРКИ ═══
• vitest ТОЛЬКО из app/: cd app && node node_modules/vitest/vitest.mjs run --config vitest.config.tools.mjs
<фильтр> --reporter dot. cwd между Bash-вызовами ненадёжен → префиксить cd app && в одной команде.
• keytar рабочий ТОЛЬКО в КОРНЕВОМ node_modules (в app/node_modules битый).
• settings.json под Read-deny — Claude не читает; правит ВЛАДЕЛЕЦ по тексту.
• graphify-out = карта проекта (junction на spike worktree), ~6305 узлов / 1009 communities.
• escape окно 5 мин — request+act в одном ходу (см. УРОК выше).
СТАРТ: прочитай R6.2 + sub-plan A + этот handoff, подтверди, спроси владельца (B/C/D/E план ИЛИ реализация A
ИЛИ другое), дождись «вперёд». Без отсебятины. Качество превыше всего. Спрашивай перед каждой фазой.
```