From e69fd396b29d81637cd3c0badb2cadbcb5ba2df2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Wed, 10 Jun 2026 13:36:57 +0300 Subject: [PATCH] docs(router-mentor): R6.2 + sub-plan A + handoff-2 --- docs/observer/STATUS.md | 25 +- ...-router-mentor-subplan-a-context-verity.md | 431 ++++++++++++++++++ ...06-10-router-mentor-live-rebuild-design.md | 317 +++++++++++++ ...6-06-10-router-mentor-session-handoff-2.md | 137 ++++++ 4 files changed, 898 insertions(+), 12 deletions(-) create mode 100644 docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md create mode 100644 docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md create mode 100644 docs/superpowers/specs/2026-06-10-router-mentor-session-handoff-2.md diff --git a/docs/observer/STATUS.md b/docs/observer/STATUS.md index 6334c880..a2e2dadb 100644 --- a/docs/observer/STATUS.md +++ b/docs/observer/STATUS.md @@ -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-сессий. diff --git a/docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md b/docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md new file mode 100644 index 00000000..afabf722 --- /dev/null +++ b/docs/superpowers/plans/2026-06-10-router-mentor-subplan-a-context-verity.md @@ -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). diff --git a/docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md b/docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md new file mode 100644 index 00000000..8a5ba02e --- /dev/null +++ b/docs/superpowers/specs/2026-06-10-router-mentor-live-rebuild-design.md @@ -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:` агностичен `[ФАКТ 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:` (§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:` | +| 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:` (✅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 | diff --git a/docs/superpowers/specs/2026-06-10-router-mentor-session-handoff-2.md b/docs/superpowers/specs/2026-06-10-router-mentor-session-handoff-2.md new file mode 100644 index 00000000..ce6f3168 --- /dev/null +++ b/docs/superpowers/specs/2026-06-10-router-mentor-session-handoff-2.md @@ -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:` (✅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 +ИЛИ другое), дождись «вперёд». Без отсебятины. Качество превыше всего. Спрашивай перед каждой фазой. +```