From 49aa4ba72595f1be9dccfa502c824465cec5113b 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: Mon, 25 May 2026 04:23:33 +0300 Subject: [PATCH] =?UTF-8?q?docs(brain):=20spec=20v2.1=20+=20reviewer-agent?= =?UTF-8?q?=20=E2=80=94=2016=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20code=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2.0 → v2.1 — 3 группы изменений (16 пунктов суммарно): Группа 1 — решения принятые после v2.0, не внесённые: - 1.1 Памятка classifier (4 паттерна: brainstorming / discovery-interview / writing-plans / systematic-debugging). +flag prompt-enrichment-mode. - 1.2 Reviewer как полноценный Claude Code subagent (tools=[Read,Grep,Glob, Skill], model=opus). Новый файл .claude/agents/reviewer-agent.md. +стоимость $240-1200/мес vs $40-80 direct API. Crash fallback на direct API. Context bloat cap 10 соседних эпизодов. - 1.3 Inheritance + 3 группы коротких prompt'ов (continuation/acknowledgment/ cancellation) + 30-минутный таймаут. +flag inheritance-mode. Новые поля в schema v4.1: inherited_from_task_id, inheritance_age_minutes, previous_direction_rejected, previous_task_id_rejected. Группа 2 — edge cases: - 2.1 Reviewer model явно opus в agent file. - 2.2 Reviewer subagent crash → fallback direct API call. - 2.3 Reviewer context bloat: max 10 episodes в agent system prompt. - 2.4 Manual override приоритет №1 в prefilter (раньше inheritance). - 2.5 Cancellation clears state + previous_task_id_rejected marker. Группа 3 — мелкие упущения: - 3.1 brain-retro SKILL.md description: раз в 1-2 недели (не sprint). - 3.2 recommended_chain_id nullable для custom chains. - 3.3 Embedding только для non-prefilter эпизодов. - 3.4 PII filter wraps sanity-check comments. - 3.5 requested_node fuzzy matching fallback. - 3.6 Anchor word list inline initial. - 3.7 Self-retrospect counter init в фазе 3 step 3.3. - 3.8 Sanity-check answer file schema_version=1. Cost rewrite: 720-1380 USD (v2.0) -> 1940-8200 USD (v2.1) на 6 месяцев из-за reviewer subagent. Granular rollback через reviewer-mode=direct-api возвращает к v2.0 ценам. §21 новый — changelog v2.0 → v2.1 со всеми 16 пунктами и где правка. Реализация — после закрытия Биллинга v2 Спек C. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/agents/reviewer-agent.md | 231 +++ cspell-words.txt | 1 + docs/observer/STATUS.md | 14 +- ...-05-24-llm-first-router-overhaul-design.md | 1341 ++++++++--------- 4 files changed, 854 insertions(+), 733 deletions(-) create mode 100644 .claude/agents/reviewer-agent.md diff --git a/.claude/agents/reviewer-agent.md b/.claude/agents/reviewer-agent.md new file mode 100644 index 00000000..a26b5388 --- /dev/null +++ b/.claude/agents/reviewer-agent.md @@ -0,0 +1,231 @@ +--- +name: reviewer-agent +description: | + Independent reviewer of routing decisions for Лидерра brain governance. + Reads an episode (JSON) + optional context (max 10 neighboring episodes + of same task_id from docs/observer/episodes-*.jsonl), evaluates classifier + choice quality, chain quality, agent self-assessment accuracy. Returns + structured JSON review. + + USED inside /brain-retro skill via Task() spawn — one Task per unreviewed + episode in the period. NEVER edits files. NEVER commits. NEVER touches + nodes.yaml / episodes / нормативку. + + Escalates to controller if episode is malformed or schema unknown. + + Reviewer-agent is part of LLM-first router overhaul (see spec + docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md + §4.6 v2.1). Replaces direct Opus API call (v2.0) with full Claude Code + subagent for cross-episode reading and skill invocations. +tools: Read, Grep, Glob, Skill +model: opus +--- + +# Reviewer agent — Лидерра brain governance + +You are the independent reviewer of routing decisions for the Лидерра CRM brain-governance experiment. Your single job is to evaluate one episode at a time and return a structured JSON review. + +You DO NOT edit files. You DO NOT commit. You DO NOT modify the episode you are reviewing. You DO NOT make architectural decisions. If the episode is malformed or contradicts itself irreparably, escalate to the controller with `{"reviewer_error": ""}` and return. + +## Context + +You are spawned from inside `/brain-retro` skill via `Task(subagent_type='reviewer-agent', prompt=)`. Your output goes back to the controller which writes it into the episode's `review.*` fields. + +Spec reference: `docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md` §4.6. + +## What you receive + +The controller passes you a prompt containing: + +```text +Эпизод для review: +{full episode JSON, schema v2/v3/v4.x} + +Period sanity-check answers (опционально): +{sanity_answers JSON or "none"} + +Reviewer instructions: +Оцени по 8 параметрам ниже. +Return ONLY JSON, no prose. +``` + +## What you can read additionally (context) + +Use `Read`, `Grep`, `Glob` to fetch: + +1. **Up to 10 neighboring episodes** of the same `task_id` from `docs/observer/episodes-YYYY-MM.jsonl`. Use Grep to find them by `task_id`. **HARD LIMIT: 10**. If more exist, take the 10 closest in time. +2. **`docs/registry/nodes.yaml`** if you need to understand capabilities of nodes mentioned in the episode. +3. **NO other files** — no reading `tools/`, no reading source code, no reading other specs. Stay focused. + +## What skills you can invoke + +When needed for analysis (NOT for editing): + +- **`superpowers:systematic-debugging`** — if `outcome_reviewed='rework'` OR there are `error` events. Apply 3-hypothesis methodology to identify `error_root_cause`. +- **`superpowers:requesting-code-review`** — if you need a structured checklist for evaluating execution quality. +- **`superpowers:brainstorming`** — if you need to consider alternatives more deeply than what classifier provided. + +Skills are tools for YOUR thinking. They don't change anything. After invocation, return back to evaluating the episode. + +## What you evaluate (8 dimensions) + +Return JSON with these exact keys: + +```json +{ + "node_quality": "correct | wrong_node | overkill | underkill | disputable", + "chain_quality": "correct | missing_step | extra_step | wrong_order | n/a", + "gap_assessment": "acceptable | mistake_should_complete | mistake_should_not_start | n/a", + "agent_self_assessment_accuracy": "accurate | over_confident | under_confident | no_self_assessment", + "error_root_cause": "wrong_skill | wrong_tool | wrong_chain_order | external_failure | n/a", + "alternative_better": "", + "outcome_reviewed": "success | soft_success | rework | blocked", + "reasoning": "1-3 предложения объяснения. Конкретно, не общо." +} +``` + +### Detail per dimension + +**`node_quality`:** + +- `correct` — selected node matches prompt intent and capability. +- `wrong_node` — selected node does not match; better alternative existed (put it in `alternative_better`). +- `overkill` — node is more heavy than needed (e.g., systematic-debugging for typo fix). +- `underkill` — node is too light (e.g., direct edit for security-sensitive area). +- `disputable` — reasonable but not obviously best. + +**`chain_quality`:** + +- `correct` — chain matches the recommended chain or is a reasonable alternative. +- `missing_step` — important step skipped (e.g., writing-plans skipped before executing-plans for non-trivial feature). +- `extra_step` — unnecessary step added. +- `wrong_order` — steps executed in wrong order. +- `n/a` — single-node task, no chain. + +**`gap_assessment`** (only if `chain_gaps[].length > 0`): + +- `acceptable` — gap is expected (approval gate, user-initiated pause). +- `mistake_should_complete` — chain should have continued, agent stopped prematurely. +- `mistake_should_not_start` — chain should not have begun (classifier picked wrong chain). + +**`agent_self_assessment_accuracy`:** + +- Сравни `self_assessment.confidence_in_choice` с реальным `outcome_inferred`/`outcome_reviewed`. +- `confidence ≥ 0.7 + outcome=rework` → `over_confident`. +- `confidence ≤ 0.4 + outcome=success` → `under_confident`. +- Соответствие → `accurate`. +- `self_assessment_pending: true` → `no_self_assessment`. + +**`error_root_cause`** (only if `events.error.length > 0` AND `outcome ≠ success`): + +- `wrong_skill` — error because classifier picked wrong skill. +- `wrong_tool` — error from tool within correct skill (e.g., Edit instead of MultiEdit on multi-occurrence). +- `wrong_chain_order` — error from misordered chain steps. +- `external_failure` — network/lock/race/API-down (not agent's fault). +- `n/a` — no error or success outcome. + +**`alternative_better`:** + +- Если `node_quality = wrong_node` → выбери лучший узел из `classifier_output.alternatives_considered[].node`. +- Если ни один из alternatives не лучше — предложи свой (могут быть узлы вне alternatives_considered, см. `docs/registry/nodes.yaml`). +- Иначе → `null`. + +**`outcome_reviewed`** (proxy — закрывает 19.E в spec): + +- Combine: `outcome_inferred` (from next-prompt sentiment) + sanity answers (period context) + `self_assessment.confidence` vs actual. +- `success` — task completed and user moved on positively. +- `soft_success` — task completed but with caveats (corrections, partial). +- `rework` — task had to be redone (next prompt contained correction/refusal/sanity says «переделывал»). +- `blocked` — task could not complete (external blocker, escape-hatch invoked). + +**`reasoning`:** + +- 1-3 предложения объяснения твоего решения. +- Конкретно: ссылайся на episode fields, not general principles. +- Если использовал cross-episode context — упомяни. + +## Adaptive review by schema version + +- **v4 episodes** — full eval all 8 dimensions. +- **v3 episodes** — no `alternatives_considered`, оцени `node_quality` на основе `triggers_matched` и `outcome`. `alternative_better` ставь null. +- **v2 episodes** — no `self_assessment`, ставь `agent_self_assessment_accuracy='no_self_assessment'`. Остальное как обычно. +- **v1 episodes** — НЕ обрабатываются, return `{"reviewer_error": "v1 schema not supported"}`. + +## What you DON'T do + +- Не редактируешь episode (controller сам пишет review.* поля по твоему JSON output). +- Не правишь nodes.yaml. +- Не правишь spec. +- Не делаешь коммиты. +- Не общаешься с пользователем — твой output идёт controller'у. +- Не читаешь больше 10 соседних эпизодов (cost cap). +- Не читаешь tools/* / source code — это вне scope review. + +## Output format + +ОНLY valid JSON, no markdown, no code fences, no explanation text. Controller парсит твой output напрямую как JSON. + +Если решил escalate — return: + +```json +{"reviewer_error": ""} +``` + +И ничего больше. + +## Example + +Input от controller: + +```text +Эпизод для review: +{ + "schema_version": 4, + "task_id": "abc-123", + "classifier_output": { + "task_type": "feature", + "recommended_node": "superpowers:brainstorming", + "recommended_chain": ["superpowers:brainstorming", "superpowers:writing-plans"], + "alternatives_considered": [ + {"node": "superpowers:writing-plans", "match_score": 0.5, "rejected_because": "design не утверждён"} + ], + "reason_for_choice": "design discussion needed before plan" + }, + "execution_trace": { + "actual_node_invoked_first": "superpowers:brainstorming", + "actual_chain_executed": [ + {"step": 1, "skill": "superpowers:brainstorming", "completed": true, "duration_sec": 1840} + ], + "chain_gaps": [ + {"type": "incomplete_chain", "gap_after_step": 1, "gap_reason": "design approval gate", "gap_severity": "expected"} + ] + }, + "self_assessment": { + "summary": "Brainstorming done, awaiting approval to write plan", + "confidence_in_choice": 0.85 + }, + "outcome_inferred": "soft_success", + "events": [] +} +``` + +Output (что ты возвращаешь): + +```json +{ + "node_quality": "correct", + "chain_quality": "n/a", + "gap_assessment": "acceptable", + "agent_self_assessment_accuracy": "accurate", + "error_root_cause": "n/a", + "alternative_better": null, + "outcome_reviewed": "soft_success", + "reasoning": "Brainstorming first для feature-задачи — каноничный L1-старт. Gap after step 1 ожидаем: дизайн нуждается в approval. Self-assessment confidence=0.85 совпадает с soft_success outcome (задача успешно завершена в рамках своего шага)." +} +``` + +## Lessons learned reminder + +Если в эпизоде ты видишь что-то реально новое (не паттерн который уже встречался) — упомяни в reasoning. Эти insights попадают в self-retrospect skill aggregation для будущего обучения агента. + +Но НЕ делай self-retrospect сам — это отдельный skill. diff --git a/cspell-words.txt b/cspell-words.txt index 80b939dc..9a6b291e 100644 --- a/cspell-words.txt +++ b/cspell-words.txt @@ -1745,3 +1745,4 @@ uniqid префлайт Префлайт скоупа +unreviewed diff --git a/docs/observer/STATUS.md b/docs/observer/STATUS.md index db604e08..acaab043 100644 --- a/docs/observer/STATUS.md +++ b/docs/observer/STATUS.md @@ -1,6 +1,6 @@ # Brain Status (auto-generated) -Last updated: 2026-05-25T00:09:15.184Z +Last updated: 2026-05-25T00:27:09.894Z | Контролёр | Состояние | Детали | |---|---|---| @@ -8,13 +8,13 @@ Last updated: 2026-05-25T00:09:15.184Z | C2 Cross-ref consistency | 🔴 | Update cross-refs in offending files. | | C3 Observer-of-observer | ✅ | [observer-of-observer] OK — last read 0 week(s) ago | | C4 Сигнальный статус | ✅ | This file (self-reference) | -| C5 Observer-coverage | ⚠️ | 290 episode(s) this month · Stop-hook + post-commit OK · 21 missed activation(s) — see /brain-retro | +| C5 Observer-coverage | ⚠️ | 296 episode(s) this month · Stop-hook + post-commit OK · 21 missed activation(s) — see /brain-retro | | C6 Chain map sync | ✅ | [chain-map-checker] OK — 16 chains in sync | ## Метрики (информационные, не алерты) -- Observer evidence: 290 episodes this month, 0 observer_error markers, 21 PII matches before filter -- Legacy v1 episodes (not in factor analysis): 151 +- Observer evidence: 296 episodes this month, 0 observer_error markers, 21 PII matches before filter +- Legacy v1 episodes (not in factor analysis): 157 - Last /brain-retro: 0 day(s) ago - Использование узлов: см. `/brain-retro` (раз в спринт). missed_activations: 21. **Неиспользованные узлы — не алерт, если профильной задачи не было** (Pravila §16.4 v1.36; capability-readiness; см. memory `feedback_brain_unused_tools_not_problem` — outside-repo memory store). @@ -28,13 +28,13 @@ Baseline дисциплины роутера (этап 2 router discipline overh | bugfix | 9 | 44.4% | 44.4% | | feature | 9 | 22.2% | 0.0% | | planning | 6 | 0.0% | 0.0% | -| monitoring | 4 | 0.0% | 0.0% | +| monitoring | 5 | 0.0% | 0.0% | | refactor | 1 | 0.0% | 0.0% | | cleanup | 1 | 0.0% | 0.0% | -Router step distribution: 1: 117, 2: 94, 3: 36, 5: 38 +Router step distribution: 1: 120, 2: 96, 3: 37, 5: 38 -Boundaries applied (ADR / границы): 45 of 285 эпизодов (15.8%). +Boundaries applied (ADR / границы): 46 of 291 эпизодов (15.8%). ## Активные многоэтапные проекты diff --git a/docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md b/docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md index 7a6e262c..94ecbc07 100644 --- a/docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md +++ b/docs/superpowers/specs/2026-05-24-llm-first-router-overhaul-design.md @@ -1,8 +1,8 @@ -# LLM-first router overhaul — spec v2.0 +# LLM-first router overhaul — spec v2.1 -**Дата:** 2026-05-24 (v1.0) / 2026-05-25 (v2.0 — переписана целиком после критического анализа v1.0). -**Эпик:** пересборка маршрутизации мозга — переход с regex-первичного классификатора + §12 hard-rule (whitelist 14 типов) на LLM-first классификатор Sonnet 4.6 + §17 universal skill-coverage rule (default-deny кроме conversation/micro/manual_override) + автоматический evidence loop с Opus 4.7 ревьюером для последующей дистилляции эмпирических regex-правил. -**История версий:** v1.0 → v2.0. v1.0 содержал 8 фактических ошибок (несуществующие файлы skill-discipline, отсутствующие поля nodes.yaml, неверные пути L1-L16), 11 пропусков скоупа, 10 underspecified механизмов, 6 логических противоречий. v2.0 переписана с реальным state inventory (§18) и явными accepted trade-offs (§19). +**Дата:** 2026-05-24 (v1.0) / 2026-05-25 (v2.0 — переписана целиком) / 2026-05-25 (v2.1 — 16 правок после code review). +**Эпик:** пересборка маршрутизации мозга — переход с regex-первичного классификатора + §12 hard-rule на LLM-first классификатор Sonnet 4.6 (с prompt enrichment памяткой) + §17 universal skill-coverage rule + Reviewer как полноценный Claude Code subagent + inheritance для коротких follow-up prompt'ов + автоматический evidence loop для последующей дистилляции эмпирических regex-правил. +**История версий:** v1.0 → v2.0 → v2.1. v1.0 — 8 фактических ошибок. v2.0 — переписана с реальным state inventory. v2.1 — внесены 3 решения принятые после v2.0 (памятка classifier, reviewer-subagent, inheritance) + 5 edge cases + 8 мелких упущений = 16 правок. **Реализация:** 3 implementation-фазы за один эпик (~3.5-4.5 недели), затем ~5-6 месяцев passive evidence collection, затем 4-я фаза distillation (~2-3 недели) через ~6 месяцев. --- @@ -17,20 +17,21 @@ | 4 | Компоненты по слоям (детально) | | 5 | Schema эпизода v4.* (поэтапные bumps) | | 6 | §17 — формальное определение | -| 7 | Что меняется в нормативке (с реальными путями файлов) | +| 7 | Что меняется в нормативке | | 8 | Что остаётся нетронутым | | 9 | Адаптация контролёров C1-C6 | -| 10 | Гранулярные flag-переключатели + rollback (с dry-run автоматизацией) | -| 11 | Фазы реализации (с явным разделением implementation vs passive) | -| 12 | Cost monitoring (без cap, но с daily dashboard) | -| 13 | Связанные изменения в нормативке (карта правок) | -| 14 | Risk register (расширен) | +| 10 | Гранулярные flag-переключатели + rollback | +| 11 | Фазы реализации | +| 12 | Cost monitoring | +| 13 | Связанные изменения в нормативке | +| 14 | Risk register | | 15 | Открытые вопросы implementation-уровня | | 16 | Definition of Done | -| 17 | Связь с другими эпиками (no dependencies) | -| 18 | **Pre-implementation state inventory** (новое — реальное состояние) | -| 19 | **Accepted trade-offs** (новое — явные компромиссы) | -| 20 | **Что НЕ делается этим эпиком** (явный non-goals) | +| 17 | Связь с другими эпиками | +| 18 | Pre-implementation state inventory | +| 19 | Accepted trade-offs | +| 20 | Что НЕ делается этим эпиком | +| 21 | Changelog v2.0 → v2.1 (новое — все 16 правок) | --- @@ -38,138 +39,125 @@ ### 1.1. Что не так с текущим состоянием -- **Routing-словари вручную поддерживаются в 5 документах.** Tooling §3.3 / CLAUDE.md §3.3 / `docs/routing-off-phase.md` / `docs/router-procedure.md` / PSR_v1 R15 — пересекающееся знание «задача → узел». Каждый новый узел требует ручной правки в нескольких местах. По мере роста мозга (сейчас 84 узла) дрейф ускоряется. Реестр в `docs/registry/nodes.yaml` был введён как single source, но текстовые шпаргалки остались параллельно. -- **Regex-классификатор `tools/router-classifier.mjs` — ручной word-list (~60 ключевиков на 11 категорий)** (router-classifier.mjs:17-32) не покрывает новые домены (marketing #74-83, infosec #68-73, finance #61-63 — для них есть только узкие keyword-триггеры в nodes.yaml без category-уровня в classifier'е). -- **§12 hard-rule** (Pravila §12) принуждает Superpowers skill для 14 типов задач. Это a-priori правило (Pravila v1.4, 09.05.2026), не выведенное из эмпирики. Принуждение skill'а смещает evidence — agent выбирает skill потому что должен, не потому что лучше. -- **Brain-governance evidence — собирается, но почти не оценивается.** Episode `outcome` = `unknown` при записи, brain-retro угадывает по тону следующего prompt'а. Нет per-episode оценки качества выбора узла → дистилляция regex невозможна без human-labeled выборки. Ручной labeling 20 эпизодов раз в 2-3 недели даёт 1.3% покрытия выборки за 6 месяцев — статистически недостаточно. +- **Routing-словари вручную поддерживаются в 5 документах.** Tooling §3.3 / CLAUDE.md §3.3 / `docs/routing-off-phase.md` / `docs/router-procedure.md` / PSR_v1 R15 — пересекающееся знание «задача → узел». Каждый новый узел требует ручной правки в нескольких местах. +- **Regex-классификатор `tools/router-classifier.mjs` — ручной word-list (~60 ключевиков на 11 категорий)** (router-classifier.mjs:17-32) не покрывает новые домены (marketing #74-83, infosec #68-73, finance #61-63). +- **§12 hard-rule** принуждает Superpowers skill для 14 типов задач. Это a-priori правило (Pravila v1.4), не выведенное из эмпирики. +- **Brain-governance evidence — собирается, но почти не оценивается.** Episode `outcome` = `unknown` при записи, brain-retro угадывает по тону следующего prompt'а. Ручной labeling 20 эпизодов раз в 2-3 недели даёт 1.3% покрытия выборки за 6 месяцев — статистически недостаточно. +- **Короткие follow-up prompt'ы теряют контекст** (новое в v2.1). Ты пишешь «продумай архитектуру X», я обсуждаю, ты пишешь «да» → диспетчер видит conversation, контекст «работаем над X» теряется в эпизоде «да». Аудитор видит обрубленный эпизод вместо связной задачи. ### 1.2. Что хочется получить через ~6 месяцев -- **Эмпирическая база ~1500 эпизодов**, из которых ~70-80% (≈1000-1200) имеют заполненный `review.*` от Opus 4.7 ревьюера → пригодна для дистилляции regex. +- **Эмпирическая база ~1500 эпизодов**, ~70-80% с заполненным `review.*` от Opus 4.7 subagent ревьюера → пригодна для дистилляции regex. - **Regex-правила выведены из факта**, не из угадывания. -- **§17 либо подтверждена эмпирикой и ужесточена, либо ослаблена до hybrid, либо снята** — решение по результатам distillation phase. -- **LLM-classifier остаётся как fallback** для пограничных случаев; distilled regex покрывает топ-20 паттернов нагрузки. -- **Мозг сжат** на ~30-50% за счёт удаления routing-дублей; nodes.yaml — единственный источник истины routing. +- **§17 либо подтверждена, либо ослаблена, либо снята** — решение по результатам distillation. +- **LLM-classifier остаётся fallback** для пограничных случаев. +- **Мозг сжат** на ~30-50% за счёт удаления routing-дублей. -### 1.3. Что НЕ делается этим эпиком (non-goals) +### 1.3. Что НЕ делается этим эпиком -См. §20 расширенно. +См. §20. --- -## 2. Принципы (с явными accepted trade-offs) +## 2. Принципы -1. **Эмпирика бьёт теорию — но не в принципе skill-coverage.** Routing-правила «какой узел выбрать» дистиллируются из эмпирики, **но сам принцип «использовать skill, не direct» (§17) остаётся a-priori safety-rail** на время эксперимента. Trade-off обсуждён в §19.A. -2. **Один touchpoint для владельца.** Единственное действие, требуемое от Дмитрия — вызов `/brain-retro`. Внутри него ему задаются 3-4 простых вопроса. Sanity-check **обязательный** (без ответов /brain-retro не завершается), формат настолько простой что занимает 2-5 минут. -3. **Чистота данных vs скорость работы.** Где конфликтуют — выбираем чистоту: routing-docs архивируются одним движением, не постепенно. -4. **Гранулярный rollback.** 7 независимых flag-переключателей. Каждый можно flip независимо. -5. **Реестр узлов — единый источник routing.** Все routing-решения исходят из `docs/registry/nodes.yaml`. -6. **Universal coverage — §17.** Все задачи кроме явных conversation/micro/manual_override/escape-hatch покрыты skill или цепочкой. -7. **Backwards compatibility forward-only.** Schema эпизода bumps делаются поэтапно (v4.0 → v4.1 → v4.2 → v4.3), парсер всегда поддерживает все версии для read. -8. **Cost transparency без cap.** Жёсткого лимита нет (per user decision), но daily cost dashboard обновляется каждым Stop-hook'ом — runaway виден в течение часа, не недели. +1. **Эмпирика бьёт теорию — но не в принципе skill-coverage.** §17 — a-priori safety-rail. Trade-off §19.A. +2. **Один touchpoint для владельца.** Только `/brain-retro` + ответы на 3-4 простых вопроса внутри. +3. **Чистота данных vs скорость.** Где конфликтуют — выбираем чистоту. +4. **Гранулярный rollback.** 9 независимых flag-переключателей (было 7 в v2.0, +2 для памятки и inheritance). +5. **Реестр узлов — единый источник routing** (`docs/registry/nodes.yaml`). +6. **Universal coverage — §17.** Default-deny кроме conversation/micro/manual_override/escape-hatch. +7. **Backwards compatibility forward-only.** Schema bumps поэтапные (v4.0 → v4.3). +8. **Cost transparency без cap.** Daily cost dashboard каждым Stop-hook'ом. --- ## 3. Архитектура — общая картина (8 слоёв) -``` +```text ┌──────────────────────────────────────────────────────────────────┐ │ ТВОЙ PROMPT │ └──────────────────────────────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────────────┐ -│ СЛОЙ 1 — Conversation/micro/manual_override/anchor prefilter │ -│ regex, $0, ~1мс │ -│ - manual override («делай через X») → md_override, direct │ -│ - длина <15 И не содержит anchor → conv, direct │ -│ - в CONVERSATION_PATTERNS И не содержит anchor → conv, direct │ -│ - в MICRO_KEYWORDS → micro, direct │ -│ - иначе → передаётся в LLM-classifier │ +│ СЛОЙ 1 — Prefilter (regex, $0, ~1мс) │ +│ Порядок проверки: │ +│ 1. Manual override («делай через X») → md_override, direct │ +│ 2. Continuation («да», «делай», «дальше», ...) → inherit │ +│ предыдущую классификацию из state, помечаем continuation │ +│ 3. Acknowledgment («спасибо», «ок») → conversation чистая │ +│ 4. Cancellation («нет», «отбой») → conversation + reject flag │ +│ 5. Длина <15 И не содержит anchor → conversation, direct │ +│ 6. В MICRO_KEYWORDS → micro, direct │ +│ 7. Иначе → передаётся в LLM-classifier │ └────────────────────┬─────────────────────────────────────────────┘ - ↓ (не-conversation/не-micro/не-md_override) + ↓ (только non-prefilter) ┌──────────────────────────────────────────────────────────────────┐ -│ СЛОЙ 2 — LLM-classifier (Sonnet 4.6, ~$0.02/prompt, ~500-1500мс) │ -│ Вход: prompt + nodes.yaml capabilities (без полей-подсказок) │ -│ Выход (JSON): │ -│ - task_type, recommended_node, recommended_chain (array) │ -│ - alternatives_considered (топ-3 со scores + rejected_because) │ -│ - reason_for_choice │ -│ - no_skill_found (если ни один узел не подходит) │ -│ - usage (для cost tracking) │ -│ Защита от direct: prompt классификатора жёстко требует skill │ +│ СЛОЙ 2 — LLM-classifier (Sonnet 4.6 + ПАМЯТКА, ~$0.025/prompt) │ +│ Вход: prompt + nodes.yaml capabilities │ +│ ПАМЯТКА (4 паттерна, ~200 слов в system prompt): │ +│ - brainstorming: ≥3 alternatives со scoring │ +│ - discovery-interview: ambiguous → no_skill_found │ +│ - writing-plans: single vs chain decomposition │ +│ - systematic-debugging: bugfix → проверь system/expected/actual│ +│ Выход JSON: task_type / recommended_node / recommended_chain │ +│ / alternatives_considered / reason_for_choice │ └────────────────────┬─────────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────────────┐ -│ СЛОЙ 3 — Embedding (local @xenova/transformers, $0, ~50мс) │ -│ prompt → 384-dim float32 vector │ -│ Pre-warm на SessionStart hook (избегает cold-start latency) │ -│ Хранится в episode как Base64 │ +│ СЛОЙ 3 — Embedding (local, $0, ~50мс) │ +│ ТОЛЬКО для task_type ∉ {conversation, micro, manual_override} │ +│ Pre-warm на SessionStart hook │ └────────────────────┬─────────────────────────────────────────────┘ ↓ ┌──────────────────────────────────────────────────────────────────┐ -│ СЛОЙ 4 — §17 enforcement (router-tool-gate.mjs расширен) │ -│ Блокирует ТОЛЬКО при mode='enforce': │ -│ - actual_node='direct' для task_type ∉ {conv,micro,override} │ -│ - no_skill_found → блок + сигнал «расширить nodes.yaml» │ -│ Mode переключатель: ~/.claude/runtime/router-gate-mode.json │ +│ СЛОЙ 4 — §17 enforcement (router-tool-gate.mjs) │ +│ warn-only или enforce (mode переключатель) │ └────────────────────┬─────────────────────────────────────────────┘ ↓ [ Claude исполняет skill/chain ] - execution_trace + chain_gaps пишутся Stop-hook'ом - events.error/interrupt/retry — как сейчас ↓ ┌──────────────────────────────────────────────────────────────────┐ │ СЛОЙ 5 — Self_assessment (Stop-hook, Opus 4.7, ~$0.03/task) │ -│ Я в конце task пишу 3 поля: │ -│ - summary, confidence_in_choice, what_could_be_better │ -│ Timeout 15сек, fallback на retroactive fill в /brain-retro │ +│ Timeout 15сек + retroactive fallback │ └────────────────────┬─────────────────────────────────────────────┘ ↓ - [ Episode v4.3 готов, JSONL append ] + [ Episode v4.3 готов ] ↓ - ↓ (асинхронно, в /brain-retro) ┌──────────────────────────────────────────────────────────────────┐ -│ СЛОЙ 6 — Opus 4.7 reviewer (внутри /brain-retro, ~$10/run) │ -│ Для каждого unreviewed episode периода: │ -│ - Читает episode + outcome_inferred + alternatives │ -│ + self_assessment + period sanity-check answers │ -│ - Заполняет review.* (включая error_root_cause) │ -│ - Заполняет outcome_reviewed (proxy: outcome_inferred │ -│ + sanity-context + self_assessment.confidence) │ -│ Adaptive prompt template — handles v2/v3/v4 episodes │ +│ СЛОЙ 6 — Reviewer SUBAGENT (Task spawn в /brain-retro) │ +│ Полноценный Claude Code subagent с tools=[Read,Grep,Glob,Skill]│ +│ Model: claude-opus-4-7 │ +│ ЦЕНА: $0.30-1.50 per episode (×5-15 vs direct API) │ +│ Может: читать соседние эпизоды (max 10), вызывать systematic- │ +│ debugging / requesting-code-review / brainstorming │ +│ Fallback: при Task crash → direct API call как backup │ └────────────────────┬─────────────────────────────────────────────┘ ↓ ┌────────────────────────────────────────┐ ↓ ↓ ┌──────────────────────────┐ ┌────────────────────────────────────┐ │ СЛОЙ 7 — /brain-retro │ │ СЛОЙ 8 — /self-retrospect (opt-in)│ -│ (мой ход) │ │ Запускается отдельной командой │ -│ - sanity-check (3-4 ?) │ │ ИЛИ опциональным prompt'ом из │ -│ - Opus reviewer pickup │ │ /brain-retro. НЕ auto. │ -│ - factor matrix │ │ Cost ~$2-5 за запуск. │ -│ - candidates for owner │ │ Читает 150+ episodes с review.* │ -│ │ │ Lesson_learned → memory feedback. │ └──────────────────────────┘ └────────────────────────────────────┘ ↓ - Через ~6 месяцев → ФАЗА 4 DISTILLATION: - золотая выборка → кластеризация по embedding → regex v2.0 + Через ~6 месяцев → ФАЗА 4 DISTILLATION ``` --- ## 4. Компоненты по слоям -### 4.1. Слой 1 — Conversation/micro/manual_override/anchor prefilter +### 4.1. Слой 1 — Prefilter с 3 группами и inheritance (РАСШИРЕНО v2.1) -**Файл:** `tools/router-classifier.mjs` (существующий, расширяется). +**Файл:** `tools/router-classifier.mjs` (расширяется). -**Зоны определения** (порядок проверки сверху вниз): +**Порядок проверок (важен):** -#### Manual override detection (новое) +#### Проверка 1 — Manual override (приоритет №1) Pattern: prompt начинается с глагола команды + явная ссылка на skill/node. -Regex (примерно): `^(делай|сделай|используй|применя[йи]|запусти|вызови)\s+(через|с помощью|skill|skill[оа]м)\s+([\w\-:]+)` +Regex: `^(делай|сделай|используй|применя[йи]|запусти|вызови)\s+(через|с помощью|skill|skill[оа]м)\s+([\w\-:]+)` Примеры match: @@ -177,34 +165,63 @@ Regex (примерно): `^(делай|сделай|используй|прим - «используй superpowers:brainstorming» - «вызови billing-audit» -→ `{ task_type: 'manual_override', node: 'direct', source: 'prefilter', requested_node: '' }` +**Fuzzy matching для `requested_node` extraction (закрывает 3.5):** если extracted slug не точно совпадает с node_id в nodes.yaml — пробуем fuzzy match (Levenshtein distance ≤2 или substring match). Если не найден → `requested_node: 'unknown_'`, classifier рекомендует, я уточняю у пользователя. -#### Conversation detection +→ `{ task_type: 'manual_override', node: 'direct', source: 'prefilter', requested_node: '' }` -Триггер: `длина < 15 символов` ИЛИ `prompt в CONVERSATION_PATTERNS` И **не содержит anchor**. +#### Проверка 2 — Continuation (наследование классификации, новое v2.1) -`CONVERSATION_PATTERNS`: +`CONTINUATION_PATTERNS`: ```text -['а', 'б', 'с', 'делай', 'спасибо', 'обожди', 'дальше', 'продолжай', - 'отбой', 'да', 'нет', 'ок', 'понял', 'хорошо', 'верно', 'отлично', - 'привет', 'пока', 'пропусти', 'согласен'] +['да', 'делай', 'давай', 'продолжай', 'дальше', 'ага', 'валяй', + 'поехали', 'утверждаю', 'одобряю', 'ок делай', 'хорошо делай', 'согласен делай'] ``` -#### Anchor detection (защита от false-positives conversation) +**Действие:** если prompt в списке И **возраст предыдущего state ≤ 30 минут** → читать state файл, наследовать `classification` от предыдущего хода. Записать в episode `inherited_from_task_id: `, `inheritance_age_minutes: N`. -`Anchor` — наличие в prompt'е существительного/глагола из проектного словаря: +Если предыдущий state >30 минут или отсутствует → fall through как обычный conversation. + +→ `{ task_type: , node: , source: 'prefilter_inherited', ... }` + +#### Проверка 3 — Acknowledgment (чистая conversation, новое v2.1) + +`ACKNOWLEDGMENT_PATTERNS`: + +```text +['спасибо', 'понял', 'ок', 'хорошо', 'отлично', 'верно', + 'круто', 'годится', 'молодец', 'норм'] +``` + +→ `{ task_type: 'conversation', node: 'direct', source: 'prefilter' }` + +#### Проверка 4 — Cancellation (отмена, новое v2.1) + +`CANCELLATION_PATTERNS`: + +```text +['стоп', 'нет', 'отмени', 'отбой', 'не надо', + 'забей', 'хватит', 'достаточно'] +``` + +**Действие:** task_type=conversation, дополнительно state classification обнуляется (`task_type='conversation'`), но в episode записывается `previous_task_id_rejected: ` для аудитора (закрывает 2.5). + +→ `{ task_type: 'conversation', node: 'direct', source: 'prefilter', previous_rejected: true }` + +#### Проверка 5 — Short conversation + anchor protection + +Длина prompt'а <15 символов И **не содержит anchor**. + +**Anchor list (inline в `tools/router-classifier.mjs`, закрывает 3.6):** - Существительные: `аудит`, `баг`, `план`, `спека`, `фича`, `тест`, `миграция`, `endpoint`, `файл`, `функция`, `класс`, `компонент`, `view`, `модель`, `биллинг`, `маркетинг`, `безопасность`, `пдн`, `регион`, `портал`, `проект`, `сделка`, `лид`, `админка`, `база`, `схема`, `воронка`... -- Императивы (если длина > 30 символов): `проанализируй`, `проверь`, `исправь`, `почини`, `создай`, `добавь`, `удали`, `переименуй`, `улучши`, `расширь`. +- Императивы (если длина >30): `проанализируй`, `проверь`, `исправь`, `почини`, `создай`, `добавь`, `удали`, `переименуй`, `улучши`, `расширь`. -Список расширяется по факту missed-conversation cases (через self-retrospect lessons). +Если разрастётся — вынесем в `tools/anchor-words.json` (не сейчас). -`Anchor` найден → fall through в LLM-classifier (несмотря на conversation-pattern). Это закрывает кейс «делай аудит» (matches conversation «делай», anchor «аудит» спасает). +#### Проверка 6 — Micro -#### Micro detection - -`MICRO_KEYWORDS` (взято из router-classifier.mjs:34-42): +`MICRO_KEYWORDS`: ```text ['опечатк', 'typo', 'переименуй', 'rename', 'удали мёртв', 'dead code', @@ -214,22 +231,22 @@ Regex (примерно): `^(делай|сделай|используй|прим → `{ task_type: 'micro', node: 'direct', source: 'prefilter' }` -#### Иначе → передаётся в Слой 2 +#### Проверка 7 — Forward в Слой 2 -**Все 4 типа решений** (conversation/micro/manual_override/forward) пишутся в эпизод с `source: 'prefilter'` или `source: 'llm'`. +Если ничего не сработало — содержательный prompt идёт в LLM-classifier. -### 4.2. Слой 2 — LLM-classifier (Sonnet 4.6) +### 4.2. Слой 2 — LLM-classifier (Sonnet 4.6) + ПАМЯТКА -**Файл:** `tools/router-classifier.mjs` — функция `classify()` существующая на строке 231, переписывается. +**Файл:** `tools/router-classifier.mjs` функция `classify()` переписывается. **Изменения vs текущее:** -- Модель: `claude-haiku-4-5-20251001` → `claude-sonnet-4-6-` (точный ID **верифицируется на старте фазы 2** через `anthropic.models.list()` или из CLAUDE.md глобального instruction). -- `classifyByRegex` Layer 1 → **удаляется** как primary path. Logic переезжает в Layer 1 prefilter (conversation/micro/manual_override). `TASK_TYPE_KEYWORDS` (router-classifier.mjs:17-32) — частично архивируется (специфичные keyword'ы переезжают в nodes.yaml `triggers[]` если их там нет). -- `shouldEscalate` (router-classifier.mjs:195) — удаляется (всегда escalate). -- `HARD_KEYWORD_STEMS` (router-classifier.mjs:114-118) — удаляется (confidence считается LLM'ом). +- Модель: `claude-haiku-4-5-20251001` → `claude-sonnet-4-6-` (verified через `anthropic.models.list()` на старте фазы 2). +- `classifyByRegex` Layer 1 → **удаляется** как primary path (logic переезжает в Слой 1 prefilter). +- `shouldEscalate` → удаляется (всегда escalate). +- `HARD_KEYWORD_STEMS` → удаляется. -**Promпт классификатора:** +**Promпт классификатора (с памяткой):** ```text @@ -237,16 +254,33 @@ Regex (примерно): `^(делай|сделай|используй|прим ОБЯЗАТЕЛЬНЫЕ выходные правила: 1. Верни ровно один из: skill ИЛИ chain ИЛИ no_skill_found. -2. "direct" НЕ разрешён в этом классификаторе. Conversation/micro обрабатываются ДО тебя. +2. "direct" НЕ разрешён. Conversation/micro обрабатываются ДО тебя. 3. Верни топ-3 alternatives_considered со score (0-1) и причиной отклонения. -4. reason_for_choice — конкретно, со ссылкой на capability узла; не «общее». -5. recommended_chain — массив из 1-5 skill IDs в порядке исполнения. -6. Если ни один узел НЕ подходит — no_skill_found=true И no_skill_found_suggestion. +4. reason_for_choice — конкретно, со ссылкой на capability. +5. recommended_chain — массив из 1-5 skill IDs. +6. Если ни один узел не подходит — no_skill_found=true + suggestion. -Реестр доступных узлов (с capabilities): +=== ПАМЯТКА (4 паттерна, закрывает 1.1) === + +ПАТТЕРН 1 (brainstorming): обязательно рассмотри минимум 3 alternative_considered. +Один кандидат без альтернатив — плохо. + +ПАТТЕРН 2 (discovery-interview): если запрос можно интерпретировать двумя+ +способами — НЕ угадывай. Верни no_skill_found=true с +no_skill_found_suggestion: "ambiguous — clarify A vs B vs C". + +ПАТТЕРН 3 (writing-plans): различай single-step и multi-step. +- Один глагол + объект ("поправь typo") → chain 1 элемент. +- "и"/"потом"/"затем" или подразумевается несколько этапов → chain ≥2 в порядке. + +ПАТТЕРН 4 (systematic-debugging): для task_type=bugfix — проверь, чётко ли +описаны system/expected/actual. Если хотя бы одного нет — рекомендуй +superpowers:systematic-debugging (он сам потребует прояснить). + +=== РЕЕСТР УЗЛОВ === {nodes_block} -Реестр канонических цепочек (для справки, можешь предложить новую): +=== РЕЕСТР ЦЕПОЧЕК (справочно) === {chains_block} Output — ONLY JSON object, no prose, no code fences. @@ -257,107 +291,67 @@ Prompt: {user_prompt} ``` -**`nodes_block` структура** — генерится из nodes.yaml live: +**`nodes_block`** — генерится из nodes.yaml live (без полей-подсказок): ```yaml - skill_id: superpowers:brainstorming name: Brainstorming - capabilities: «creative work — exploring user intent, requirements, design before implementation» - triggers: [«brainstorm», «обсудим», «варианты»] + capabilities: "creative work — exploring user intent, requirements, design before implementation" + triggers: ["brainstorm", "обсудим", "варианты"] ``` -(без полей `когда выбирать` / `chain_membership` — они не передаются) - -**`chains_block`** — те 16 cепочек L1-L16 из nodes.yaml `chains:` блока, как **справка** не предписание. - **Output (JSON):** ```json { "task_type": "feature", "recommended_node": "superpowers:brainstorming", - "recommended_chain": [ - "superpowers:brainstorming", - "superpowers:writing-plans", - "superpowers:executing-plans" - ], + "recommended_chain": ["superpowers:brainstorming", "superpowers:writing-plans"], "recommended_chain_id": "L1", - "reason_for_choice": "архитектурное обсуждение перед изменением behavior; brainstorming раскрывает intent ДО plan", + "reason_for_choice": "архитектурное обсуждение перед изменением behavior", "alternatives_considered": [ - { - "node": "superpowers:writing-plans", - "match_score": 0.6, - "rejected_because": "слишком ранняя стадия — требования ещё не зафиксированы" - }, - { - "node": "product-management:write-spec", - "match_score": 0.5, - "rejected_because": "product-management для PRD/roadmap, здесь архитектурная задача" - }, - { - "node": "ccpm", - "match_score": 0.3, - "rejected_because": "CCPM для PRD→issue лайфцикла, не для design-обсуждений" - } + { "node": "...", "match_score": 0.6, "rejected_because": "..." } ], "no_skill_found": false, "no_skill_found_suggestion": null } ``` -**Caching:** hash(prompt) → result. Hit-rate реалистично ~5-15%. +**`recommended_chain_id` может быть `null`** если chain custom (не из L1-L16) (закрывает 3.2). Тогда только `recommended_chain` array значимый. -**Fallback цепочка (если Sonnet недоступен):** +**Памятка управляется flag'ом `prompt-enrichment-mode.json`** (`on`/`off`) — можно выключить если паттерны overfit. -1. Попробовать Haiku 4.5 как secondary classifier. -2. Если Haiku тоже down → regex Layer 1 (восстанавливается из архива в `tools/router-classifier-regex-fallback.mjs`). -3. Если и regex недоступен → `{ task_type: 'unknown', node: 'direct', source: 'fallback', degraded: true }`. В episode пишется `degraded_mode: true`. В чате я начинаю ответ с маркера `[router degraded: ]`. +**Caching:** hash(prompt) → result. Hit-rate ~5-15%. -**Hot-reload classifier mode:** при каждом UserPromptSubmit hook читает `~/.claude/runtime/router-classifier-mode.json`. Перерасчёт сразу, без перезапуска сессии. Это **изменение от текущего поведения**. +**Fallback цепочка:** -**Cost tracking writing:** classifier-call в router-prehook.mjs пишет `task_cost.classifier_input_tokens` + `classifier_output_tokens` напрямую в `~/.claude/runtime/router-state-.json`, оттуда подхватывается Stop-hook'ом. +1. Sonnet 4.6 down → Haiku 4.5. +2. Haiku down → regex Layer 1 из `tools/router-classifier-regex-fallback.mjs`. +3. Всё down → `{ task_type: 'unknown', node: 'direct', source: 'fallback', degraded: true }`. В чате explicit маркер `[router degraded: ]`. + +**Hot-reload classifier mode:** при каждом UserPromptSubmit hook читает `~/.claude/runtime/router-classifier-mode.json`. + +**Cost tracking writing:** classifier-call пишет `task_cost.classifier_input/output_tokens` в `~/.claude/runtime/router-state-.json`. ### 4.3. Слой 3 — Embedding layer **Файл:** `tools/router-embedding.mjs` (новый). -**Модель:** `Xenova/all-MiniLM-L6-v2` — npm `@xenova/transformers`, локально, 384-dim float32, ~50мс после warmup. +**Модель:** `Xenova/all-MiniLM-L6-v2` — npm `@xenova/transformers`. -**Установка:** `npm i @xenova/transformers` (~150MB deps). Модель скачивается из HF ~80MB при первом вызове, кешируется в `~/.cache/huggingface/transformers/`. +**Условие вычисления (закрывает 3.3):** embedding вычисляется ТОЛЬКО для эпизодов с `task_type ∉ {conversation, micro, manual_override}`. На «да», «делай», «спасибо», «делай через TDD» — embedding не считаем (расточительно, никто не будет искать «семантически похожие "да"»). -**Pre-warm на SessionStart** (закрывает C3 cold-start risk) — новый hook на `SessionStart` event: +**Pre-warm на SessionStart:** новый hook `tools/router-embedding-warmup.mjs`. -```javascript -// tools/router-embedding-warmup.mjs -import { pipeline } from '@xenova/transformers'; -async function warmup() { - const extractor = await pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2'); - await extractor('warmup', { pooling: 'mean', normalize: true }); -} -warmup().catch(() => process.exit(0)); // fail silently -``` +**Storage:** Base64-encoded float32 array (~2050 chars). -**Persistence решение в фазе 2:** keep model в long-running daemon (PM2 service) ИЛИ принять ~200мс cold-start на каждый hook-invocation. Решение по smoke-тесту latency. - -**Использование:** - -- Stop-hook вычисляет `prompt_embedding`. -- Self-retrospect использует cosine similarity. -- Brain-retro может кластеризовать в Phase 4. - -**Storage в episode:** Base64-encoded float32 array (1536 bytes raw → ~2050 chars base64). - -**Fallback:** `prompt_embedding: null` + `embedding_unavailable: true` в `environment`. Self-retrospect фоллбек на task_type-based clustering. +**Fallback:** `prompt_embedding: null` + `embedding_unavailable: true` в `environment`. ### 4.4. Слой 4 — §17 enforcement -**Файл:** `tools/router-tool-gate.mjs` (существующий, расширяется). +**Файл:** `tools/router-tool-gate.mjs` (расширяется). -**Существующая логика (line 39-53):** проверяет `state.enforcementRequired` (от router-prehook). После перехода на §17 — расширяется. - -**Триггер:** PreToolUse событие на `Edit`, `Write`, `MultiEdit`, `Bash` (не read-only). Read-only Bash list — router-tool-gate.mjs:20-25. - -**Логика §17 enforcement:** +**Логика §17:** ```javascript const NON_BLOCKING_TASK_TYPES = ['conversation', 'micro', 'manual_override']; @@ -365,59 +359,36 @@ const NON_BLOCKING_TASK_TYPES = ['conversation', 'micro', 'manual_override']; function shouldBlock(tool, state, responseText, options) { const mode = options.mode; // 'warn-only' | 'enforce' | 'off' if (mode === 'off') return false; - if (mode === 'warn-only') return false; // только stderr warning - - if (state.classification.no_skill_found === true) { - return { block: true, reason: 'no_skill_found_block' }; - } - - if (NON_BLOCKING_TASK_TYPES.includes(state.classification.task_type)) { - return false; - } + if (mode === 'warn-only') return false; + if (state.classification.no_skill_found === true) return { block: true, reason: 'no_skill_found_block' }; + if (NON_BLOCKING_TASK_TYPES.includes(state.classification.task_type)) return false; if (state.skillInvokedThisTurn === true) return false; - if (decodeRoutingTag(responseText)?.directJustified) return false; - if (tool === 'Bash' && isReadOnlyBash(options.bashCommand)) return false; - if (!['Edit', 'Write', 'MultiEdit', 'Bash'].includes(tool)) return false; return { block: true, reason: 'direct_in_non_conversation' }; } ``` -**Block message format:** +**Manual override** — обрабатывается prefilter'ом, gate пропускает. Classifier параллельно shadow-evaluates для сравнения. -```text -[§17 enforcement BLOCK] -Эта задача классифицирована как: {task_type} -Реестр рекомендует узел: {recommended_node} ({recommended_chain_summary}) -Reason: {classifier.reason_for_choice} +**Mode переключатель:** `~/.claude/runtime/router-gate-mode.json` → `{"mode": "off" | "warn-only" | "enforce"}`. Default `warn-only` всё bootstrap. -Возможные действия: -1. Инвокируй skill: {recommended_node} -2. Используй escape-hatch: -3. Если узел не подходит — переклассифицируй prompt или расширь nodes.yaml. -``` +**Permission interaction:** gate ДО permission. Сознательно (разные слои). -**Manual override** — обрабатывается prefilter'ом (§4.1), gate просто пропускает (task_type='manual_override' в NON_BLOCKING). Episode помечается `decision_provenance.kind='user_directed_method'` + `requested_node` сохранён + classifier параллельно записывает свою рекомендацию в shadow-режиме. +### 4.5. Слой 5 — Self_assessment -**Mode переключатель:** `~/.claude/runtime/router-gate-mode.json` → `{"mode": "off" | "warn-only" | "enforce"}`. По умолчанию `warn-only` ВСЁ ВРЕМЯ bootstrap-периода. Переключение в `enforce` — отдельное решение в фазе 4. - -**Permission interaction:** gate срабатывает **ДО** permission-проверки settings.json. Сознательно (gate = routing-discipline, permissions = safety; разные слои). - -### 4.5. Слой 5 — Self_assessment (Stop-hook) - -**Файл:** `tools/observer-stop-hook.mjs` (существующий, расширяется). +**Файл:** `tools/observer-stop-hook.mjs` (расширяется). **Изменения:** -1. **Timeout** в settings.json для Stop-hook: 5s → **15s**. -2. **Опциональный self_assessment call** — если timeout позволяет. -3. **Retroactive fill** — если не успел в 15s, episode пишется без него с `self_assessment_pending: true`. /brain-retro Opus reviewer дозаполняет на reviewer-pass. +1. Stop-hook timeout 5s → 15s. +2. Опциональный self_assessment call (если timeout позволяет). +3. Retroactive fill — если не успел, episode пишется без него с `self_assessment_pending: true`. Reviewer subagent дозаполняет. -**Action:** один API call к Claude (model = текущая сессия, обычно Opus 4.7): +**Prompt:** ```text @@ -437,157 +408,125 @@ Chain executed: {chain_executed} ``` -**Стоимость:** ~$0.02-0.04/call. 50-100 task/день = ~$1-4/день, ~$30-120/мес. +**Стоимость:** ~$0.02-0.04/call. -**Cost tracking:** API response содержит `usage` — пишется в episode. +### 4.6. Слой 6 — Reviewer SUBAGENT (ПЕРЕПИСАНО v2.1) -**Fallback:** `self_assessment: null` + `self_assessment_pending: true`. Reviewer дозаполнит. +**Файл агента:** `.claude/agents/reviewer-agent.md` (новый). -### 4.6. Слой 6 — Opus 4.7 reviewer +**Вызов:** изнутри `/brain-retro` skill controller (главный Claude) делает `Task(subagent_type='reviewer-agent', prompt=)` для каждого unreviewed эпизода периода. -**Файл:** `tools/brain-retro-opus-reviewer.mjs` (новый). +**Agent specification (`reviewer-agent.md` frontmatter):** -**Триггер:** вызывается из skill `/brain-retro` шагом 6 (между existing analyzer и aggregation). +```yaml +--- +name: reviewer-agent +description: | + Independent reviewer of routing decisions for Лидерра brain governance. + Reads an episode + optional context (max 10 neighboring episodes of same + task_id), evaluates classifier choice quality, chain quality, agent + self-assessment accuracy. Returns structured JSON review. + Used inside /brain-retro skill. NEVER edits files, NEVER commits. +tools: Read, Grep, Glob, Skill +model: opus +--- +``` -**Логика:** +**Что reviewer-agent МОЖЕТ:** -```javascript -async function reviewPeriod(periodStart, periodEnd, sanityAnswers) { - const episodes = readEpisodesInPeriod(periodStart, periodEnd); - for (const ep of episodes) { - if (ep.review?.reviewed_at) continue; - if (['conversation', 'micro'].includes(ep.classifier_output?.task_type)) continue; - if (ep.schema_version < 2) continue; // can't review v1 +- Read эпизод который ему передан в prompt. +- Read до 10 соседних эпизодов того же task_id из `docs/observer/episodes-*.jsonl` (context bloat control — закрывает 2.3). +- Read nodes.yaml (понять capabilities узлов). +- Invoke `superpowers:systematic-debugging` skill для глубокого разбора failed эпизодов. +- Invoke `superpowers:requesting-code-review` skill для chek-листа качества. +- Invoke `superpowers:brainstorming` skill для перебора alternatives глубже. - const prompt = buildAdaptiveReviewPrompt(ep, sanityAnswers); - const review = await callOpus(prompt); - ep.review = parseReview(review); - ep.review.reviewer = 'opus-4-7'; - ep.review.reviewed_at = nowIso(); +**Что reviewer-agent НЕ МОЖЕТ:** - if (!ep.outcome_reviewed) { - ep.outcome_reviewed = inferOutcomeReviewed( - ep.outcome_inferred, - ep.self_assessment, - sanityAnswers, - review - ); - ep.outcome_reviewed_source = 'opus_proxy'; - } +- Edit / Write — нет в tools. +- Bash — нет в tools. +- Делать коммиты. +- Менять nodes.yaml / эпизоды / нормативку. - rewriteEpisodeInJsonl(ep); - } +**Что reviewer-agent ВОЗВРАЩАЕТ:** + +```json +{ + "node_quality": "correct | wrong_node | overkill | underkill | disputable", + "chain_quality": "correct | missing_step | extra_step | wrong_order | n/a", + "gap_assessment": "acceptable | mistake_should_complete | mistake_should_not_start | n/a", + "agent_self_assessment_accuracy": "accurate | over_confident | under_confident | no_self_assessment", + "error_root_cause": "wrong_skill | wrong_tool | wrong_chain_order | external_failure | n/a", + "alternative_better": "", + "outcome_reviewed": "success | soft_success | rework | blocked", + "reasoning": "1-3 предложения объяснения" } ``` -**Adaptive prompt template** — handles v2/v3/v4 episodes (закрывает B5): +**Контроллер (я) парсит ответ и пишет в episode:** -- **v4 эпизоды:** полный prompt с alternatives + self_assessment + chain_gaps. -- **v3 эпизоды:** без alternatives — prompt спрашивает «оцени выбор узла на основе rationale». -- **v2 эпизоды:** без alternatives + self_assessment — prompt спрашивает «оцени выбор на основе triggers_matched + outcome». -- **v1 эпизоды:** skip. +- `review.*` поля заполняются. +- `review.reviewer = 'subagent-opus-4-7'`. +- `outcome_reviewed_source = 'subagent_opus'`. +- `review.reviewed_at = nowIso()`. -**Review prompt (v4 пример):** +**Стоимость:** ~$0.30-1.50 per episode (Opus subagent invocation). При ~200 эпизодов = **$60-300 за один /brain-retro**. -```text - -Ты — независимый ревьюер routing-решений Claude. Никакого prose, только JSON. - - -Эпизод: -- Original prompt: {prompt_truncated_2K} -- Period sanity answers: {sanity_block} -- Classifier рекомендовал: {recommended_node}, chain: {recommended_chain} -- Classifier reasoning: {reason_for_choice} -- Alternatives рассмотрены: {alternatives} -- Реально использовано: {actual_node}, chain: {actual_chain_executed} -- Chain gaps: {chain_gaps} -- Outcome inferred: {outcome_inferred} (по тону next-prompt) -- Self-assessment: {self_assessment} +**Per-/brain-retro время:** ~17-100 минут вместо 5 минут direct API. -Оцени: -1. node_quality: correct | wrong_node | overkill | underkill | disputable -2. chain_quality: correct | missing_step | extra_step | wrong_order | n/a -3. gap_assessment: acceptable | mistake_should_complete | mistake_should_not_start | n/a -4. agent_self_assessment_accuracy: accurate | over_confident | under_confident | no_self_assessment -5. error_root_cause: wrong_skill | wrong_tool | wrong_chain_order | external_failure | n/a -6. alternative_better: если node_quality=wrong_node, какой из alternatives лучше -7. outcome_reviewed: success | soft_success | rework | blocked - (proxy: outcome_inferred + sanity + self_assessment.confidence vs actual) -8. reasoning: 1-3 предложения +**Fallback (закрывает 2.2):** если `Task(subagent_type='reviewer-agent', ...)` падает (timeout, crash) — controller делает **direct Opus API call** с тем же review prompt'ом (без subagent capabilities — без cross-episode reading, без skill invocations). Это backup, эпизод помечается `review.reviewer = 'direct-opus-fallback'`. Если и direct API down — episode остаётся unreviewed для следующего /brain-retro. -Output — ONLY JSON. - -``` +**Adaptive prompt template** — handles v2/v3/v4 episodes: -**Стоимость:** ~$0.05-0.10/review. При ~200 эпизодов за /brain-retro = $10-20. - -**Fallback при API failure:** - -- Per-episode try/catch. Если 1 episode упал — skip, continue. -- Если упало >50% эпизодов — abort с сообщением «Opus reviewer недоступен, повторить retro позже». -- Episode с `review.reviewer_error: ` — попытка снова в следующем /brain-retro. +- v4: полный prompt с alternatives + self_assessment + chain_gaps. +- v3: без alternatives — prompt спрашивает «оцени на основе rationale». +- v2: без alternatives + self_assessment — prompt спрашивает «оцени на основе triggers + outcome». +- v1: skip. ### 4.7. Слой 7 — /brain-retro skill (расширенный) -**Файл:** `.claude/skills/brain-retro/SKILL.md` (существующий, расширяется). +**Файл:** `.claude/skills/brain-retro/SKILL.md` (расширяется). -**Текущая процедура** (см. строки 22-34 SKILL.md): 9 шагов с подэтапом 8a. +**Description update (закрывает 3.1):** изменить с «Use ONCE PER SPRINT» на «Use каждые 1-2 недели OR при триггере sanity-check threshold». В references/aggregation-template.md тоже sync. **Новая процедура:** ```text 1. Determine period (как сейчас). -2. Read evidence (включая v4.* episodes). -3. Read optional notes (как сейчас). -4. Update read-counter (как сейчас). -5. [НОВОЕ] Sanity-check questions: - - Analyzer выдаёт top-5 candidate questions. - - Я выбираю 3-4 наиболее релевантных, формулирую на русском. +2. Read evidence (v4.*). +3. Read optional notes. +4. Update read-counter. +5. [v2.1] Sanity-check questions: + - Analyzer выдаёт top-5 candidate questions (через tools/brain-retro-sanity-generator.mjs). + - Я выбираю 3-4, формулирую на русском. - Задаю через AskUserQuestion (multiple-choice + free comment). - - Ответы пишутся в docs/observer/sanity-checks/YYYY-MM-DD.json - И ALSO event-streamed в эпизод(ы) периода как events. -6. [НОВОЕ] Opus reviewer pickup: - - Для эпизодов без review.reviewed_at → call Opus 4.7. - - Sanity-answers передаются в prompt как контекст. - - review.* + outcome_reviewed заполняются. + - ПЕРЕД сохранением: применяю tools/observer-pii-filter.mjs к comment (закрывает 3.4). + - Ответы пишутся в docs/observer/sanity-checks/YYYY-MM-DD.json со schema_version=1 + (закрывает 3.8) + event-stream в эпизоды периода. +6. [v2.1] Reviewer subagent pickup: + - Для каждого unreviewed episode → Task(subagent_type='reviewer-agent', prompt=ep). + - Sanity-answers передаются как период context. + - Controller парсит response, пишет в episode review.* + outcome_reviewed + outcome_reviewed_source. + - Per-episode try/catch; fallback на direct API при subagent crash. 7. Run analyzer (расширенный для v4 факторов). 8. Aggregate (per references/aggregation-template.md, обновлённый). -9. [НОВОЕ — opt-in] Если 150+ episodes с review с last self-retrospect: +9. [v2.1 — opt-in] Если 150+ episodes с review с last self-retrospect: - prompt user: «Запустить self-retrospect? (~$2-5, ~3-5 минут)» - Если да — call /self-retrospect. -10. Propose candidates for owner review (как сейчас). -11. Save retro note (с sanity-answers + cost report + Opus stats). -11a. Refresh STATUS.md (как сейчас). -12. Report to user (high-signal summary). +10. Propose candidates for owner review. +11. Save retro note (с sanity-answers + cost report + reviewer stats). +11a. Refresh STATUS.md. +12. Report to user. ``` -**Sanity-check generation logic (закрывает C1):** - -Analyzer `tools/brain-retro-sanity-generator.mjs` (новый, ~50 строк) выдаёт **5 candidate questions**: - -```text -- Если в периоде >10 эпизодов task_type=bugfix: - "10 раз я фиксил баги. Помнишь — что-то пришлось переделывать?" -- Если в периоде >5 эпизодов с overkill candidate: - "5 раз я брал большую процедуру для маленьких задач. Это напрягало?" -- Если в периоде >3 эпизода с chain_deviation: - "3 раза я бросал процедуру на полпути. Это было оправдано?" -- Если есть blocked outcome: - "Был случай когда я заявил готово, а потом нашлись косяки?" -- Generic фоллбэк: - "Общее впечатление от моей работы за период?" -``` - -Я выбираю 3-4 наиболее релевантных, formulate на русском. - -**Cost report в /brain-retro summary:** +**Cost report:** ```text ## Cost report за период -- Classifier (Sonnet 4.6): $X.XX (Y prompts) +- Classifier (Sonnet 4.6 + памятка): $X.XX (Y prompts) - Self-assessment (Opus): $X.XX (Z task ends) -- Reviewer (Opus, this run): $X.XX (W episodes) +- Reviewer subagent (Opus, this run): $X.XX (W episodes) +- Reviewer direct-API fallback: $X.XX (V episodes) - Self-retrospect (if invoked): $X.XX - Embedding: $0 (local) Total: $X.XX @@ -597,43 +536,35 @@ Total: $X.XX **Файл:** `.claude/skills/self-retrospect/SKILL.md` (новый). -**Триггер:** **opt-in** (closes C2 honest cost): +**Триггер:** -1. Пользователь явно: `/self-retrospect` или «сделай self-retrospect». -2. /brain-retro prompt'ит «запустить?» если накопилось 150+ unreviewed-since-last episodes. - -**Не auto-trigger без подтверждения** — cost не нулевой ($2-5). +1. Явно: `/self-retrospect`. +2. /brain-retro prompt'ит если накопилось 150+ unreviewed-since-last episodes. **Action:** -1. Read last 150+ episodes с `review.reviewed_at` filled (since last self-retrospect, tracker в `docs/observer/.self-retrospect-counter.json`). +1. Read last 150+ episodes с `review.reviewed_at` filled. 2. Compute patterns (без LLM API — pure aggregation): - - **Промахи classifier:** group by `(task_type, recommended_node, review.node_quality)`. Если для пары ≥5 эпизодов с `wrong_node` И одинаковый `alternative_better` → паттерн. - - **Калибровка confidence:** bucket `confidence_in_choice` vs `outcome_reviewed`. Если высокий confidence + rework — over-confident. - - **Когнитивные ошибки:** group by `chain_deviation_reason`. Если одна причина в 3+ эпизодах с rework → bias. + - Промахи classifier. + - Калибровка confidence. + - Когнитивные ошибки. 3. Write report в `docs/observer/self-retrospect/YYYY-MM-DD.md`. -4. Update counter. +4. Update `docs/observer/.self-retrospect-counter.json`. 5. `lesson_learned` → новый `memory/feedback_self_calibration_YYYY-MM.md`. -6. Return summary to user. +6. Return summary. -**Стоимость:** ~$2-5 (моя current-session Opus inference + write). **Не нулевой как в v1.0 заявлено — факт честный.** - -**Output для future sessions:** memory создаётся, auto-loaded на старте каждой сессии. +**Стоимость:** ~$2-5 (моя current-session Opus inference). **Не нулевой.** --- ## 5. Schema эпизода v4.* (поэтапные bumps) -Закрывает E16 — atomic bumps вместо одного v4.1. - -| version | когда вводится | что добавляется | +| version | когда | что добавляется | |---|---|---| -| v4.0 | фаза 2 | `classifier_output` (с alternatives), `environment.classifier_model`, `environment.degraded_mode` | -| v4.1 | фаза 3 step 1 | `execution_trace` (с chain_gaps), `chain_progress` | -| v4.2 | фаза 3 step 2 | `self_assessment`, `review` (пустой template) | -| v4.3 | фаза 3 step 3 | `prompt_embedding_base64`, `outcome_reviewed`, `task_cost.*` extended | - -**Парсер** `tools/observer-transcript-parser.mjs` детектирует `schema_version` и обрабатывает все версии для read. Write — только latest available. +| v4.0 | фаза 2 | classifier_output + environment.classifier_model + environment.degraded_mode | +| v4.1 | фаза 3 step 1 | execution_trace + chain_gaps + chain_progress + **inherited_from_task_id + inheritance_age_minutes + previous_direction_rejected** (v2.1 inheritance fields) | +| v4.2 | фаза 3 step 2 | self_assessment + review (template) | +| v4.3 | фаза 3 step 3 | prompt_embedding_base64 + outcome_reviewed + task_cost extended | **Полная финальная схема v4.3:** @@ -654,6 +585,13 @@ Total: $X.XX "requested_node": null }, + "inheritance": { + "inherited_from_task_id": null, + "inheritance_age_minutes": null, + "previous_direction_rejected": false, + "previous_task_id_rejected": null + }, + "environment": { "economy_level": 100, "model": "claude-opus-4-7", @@ -663,7 +601,8 @@ Total: $X.XX "session_turn": 1, "parallel_session": false, "degraded_mode": false, - "embedding_unavailable": false + "embedding_unavailable": false, + "prompt_enrichment_active": true }, "task_size": { @@ -682,7 +621,9 @@ Total: $X.XX "self_assessment_input_tokens": 0, "self_assessment_output_tokens": 0, "reviewer_input_tokens": 0, - "reviewer_output_tokens": 0 + "reviewer_output_tokens": 0, + "reviewer_subagent_usd": 0, + "reviewer_direct_fallback_usd": 0 }, "prompt_embedding_base64": "...", @@ -698,7 +639,7 @@ Total: $X.XX "reason_for_choice": "...", "no_skill_found": false, "no_skill_found_suggestion": null, - "classifier_source": "llm | regex_fallback | haiku_fallback | unknown" + "classifier_source": "llm | llm_with_enrichment | regex_fallback | haiku_fallback | prefilter_inherited | unknown" }, "execution_trace": { @@ -759,43 +700,41 @@ Total: $X.XX } ``` -**Sanity-check answers separate storage** `docs/observer/sanity-checks/YYYY-MM-DD-period.json`: +**Sanity-check answers** в `docs/observer/sanity-checks/YYYY-MM-DD-period.json`: ```json { + "schema_version": 1, "period_start": "ISO", "period_end": "ISO", "answered_at": "ISO", "questions_and_answers": [ - { "q": "...", "a": "yes | no | unsure", "comment": "..." } + { "q": "...", "a": "yes | no | unsure", "comment_pii_filtered": "..." } ] } ``` -Также — duplicate в episodes как `events: [{ kind: 'sanity_check_answer', q, a, comment, period_id }]`. +Также — duplicate в episodes как `events: [{ kind: 'sanity_check_answer', q, a, comment_pii_filtered, period_id }]`. --- ## 6. §17 — формальное определение -**Текст для добавления в Pravila** (новая секция, замещает §12): +**Текст для Pravila:** -> **§17. Universal skill-coverage rule.** Все задачи, кроме явных `conversation`, `micro`, `manual_override`, должны быть покрыты skill или цепочкой skill'ов из реестра `docs/registry/nodes.yaml`. Direct-исполнение разрешено только для: +> **§17. Universal skill-coverage rule.** Все задачи, кроме явных `conversation`, `micro`, `manual_override`, должны быть покрыты skill или цепочкой из реестра `docs/registry/nodes.yaml`. Direct-исполнение разрешено только для: > -> 1. **Conversation** — короткие разговорные prompt'ы (length < 15 OR в `CONVERSATION_PATTERNS`), при отсутствии anchor-слова. -> 2. **Micro** — тривиальные правки (опечатка/переименование/format/bump), определённые `MICRO_KEYWORDS`. -> 3. **Manual override** — явное указание заказчика «делай через X» (помечается `decision_provenance.kind='user_directed_method'`). -> 4. **Escape-hatch** — маркер `` в начале ответа Claude с явным обоснованием. +> 1. **Conversation** — короткие prompt'ы (length < 15 OR в `CONVERSATION_PATTERNS`) без anchor. +> 2. **Micro** — тривиальные правки (опечатка/переименование/format/bump). +> 3. **Manual override** — явное указание «делай через X». +> 4. **Continuation/Acknowledgment/Cancellation** (v2.1) — короткие follow-up'ы; classifier обрабатывает через prefilter (continuation наследует, acknowledgment чистая, cancellation с reject flag). +> 5. **Escape-hatch** — ``. > -> Enforcement через `tools/router-tool-gate.mjs` (PreToolUse hook). Mode: +> Enforcement через `tools/router-tool-gate.mjs`. Mode: `off | warn-only | enforce`. Default `warn-only` всё bootstrap. > -> - `warn-only` (default во время bootstrap; stderr-сигнал, не блокирует); -> - `enforce` (включается отдельным решением после анализа evidence; блокирует); -> - `off` (для отката). -> -> §17 — **не hard-rule под §9 «Отступления»**. В режиме экономии 0% правило логически встроено в classifier, но enforcement-хук может быть выключен через `~/.claude/runtime/router-gate-mode.json`. **Замещает §12** полностью. +> §17 — **не hard-rule под §9 «Отступления»**. Замещает §12 полностью. -**Pravila §12 → удаление в этом эпике** (текст в архив). +**Pravila §12 → удаление, текст в архив.** --- @@ -803,50 +742,43 @@ Total: $X.XX **Архив:** `docs/archive/llm-bootstrap-2026-05/` со структурой: -- `pravila-12/` — текст §12 (sub-секции 12.1-12.4). -- `routing-docs/` — routing-off-phase.md, router-procedure.md, CLAUDE.md §3.3 snapshot, PSR_v1 R15 snapshot. -- `tooling-when-to-use/` — извлечённые поля «когда брать» из Tooling §4.X (inventory подтвердил их отсутствие в текущей версии — папка пустая или содержит NOTE). +- `pravila-12/` — текст §12. +- `routing-docs/` — routing-off-phase.md, router-procedure.md, CLAUDE.md §3.3, PSR_v1 R15. +- `tooling-when-to-use/` — извлечённые поля «когда брать» (inventory подтвердил отсутствие — пусто или NOTE). - `memory/` — feedback_superpowers_hard_rule.md, feedback_feature_via_writing_plans.md. -- `settings-skill-discipline/` — diff `~/.claude/settings.json` user-level до и после удаления skill-discipline hooks (фактический list определяется в фазе 1 после inventory user settings.json). -- `nodes-yaml-archive/` — снимок до правок. -- `ROLLBACK.md` — пошаговая инструкция. +- `settings-skill-discipline/` — diff `~/.claude/settings.json` user-level (если есть skill-discipline hooks). +- `nodes-yaml-archive/` — snapshot. +- `ROLLBACK.md`. -**Pravila §12 удаляется целиком.** §17 добавляется. §16.4 обновляется (missed-activations работают с §17). Cross-refs §12 → §17 в CLAUDE.md §5 п.11, PSR_v1 R0.4.A, Tooling §7. +Pravila §12 — целиком в архив. §17 добавляется. §16.4 обновляется (missed-activations теперь работают с §17). -**CLAUDE.md §3.3 удаляется** — заменяется на однострочный pin: `См. реестр docs/registry/nodes.yaml`. §5 п.11 переписывается. §0 cross-refs обновляются. +CLAUDE.md §3.3 — в архив, заменяется на pin на nodes.yaml. §5 п.11 переписывается. -**PSR_v1 R10.1 счётчики** → pin на nodes.yaml. **R15** удаляется. **R0.4.A** упоминание §12 → §17. +PSR_v1 R10.1 счётчики → pin на nodes.yaml. R15 удаляется. R0.4.A: §12 → §17. -**Tooling Прил.Н** — поля «когда брать» (если есть в attribute-блоках) извлекаются в архив. §0 счётчики — pin на header nodes.yaml. §3.X cross-ref на router-procedure.md удаляется. +Tooling Прил.Н — поля «когда брать» в архив. §0 счётчики — pin на nodes.yaml. §3.X cross-refs на router-procedure.md удаляются. -**routing-off-phase.md, router-procedure.md** — целиком в архив. +routing-off-phase.md, router-procedure.md — целиком в архив. -**nodes.yaml — изменения:** +nodes.yaml: -- Поля `triggers[].keyword` и `triggers[].classification` — **остаются** (input для classifier). -- L1-L16 chains — **остаются** (input как справка для classifier). -- Добавляется НОВОЕ поле верхнего уровня `capabilities:` для каждого узла. На старте фазы 2 — controller заполняет capabilities (~30 мин либо subagent task). -- Удаляется (если есть) поле `when_to_use` — **проверено в инвентаре §18 — поля нет, удалять нечего**. +- Добавляется `capabilities:` per узел (фаза 2). +- `triggers[]` — остаются. +- L1-L16 chains — остаются. -**Memory:** `feedback_superpowers_hard_rule.md` + `feedback_feature_via_writing_plans.md` → архив. **Другие brain-governance memory** (`feedback_brain_unused_tools_not_problem.md`, `project_brain_governance_design.md`) — **остаются** с обновлёнными cross-refs (§12 → §17). - -**`tools/observer-classification-map.json`** — **архивируется в этом эпике** (закрывает B2). DEPRECATED 24.05 — окончательно удаляется. +`tools/observer-classification-map.json` — архивируется (DEPRECATED 24.05, теперь физически удаляется). --- ## 8. Что остаётся нетронутым -- **Pravila §1-§11** — без изменений. -- **Pravila §13** — без изменений. -- **Pravila §14** — без изменений (Ruflo dormant). -- **Pravila §15** — без изменений (procedural rule). -- **Pravila §16** — без изменений. §16.4 — minor update. -- **ADR** — все сохраняются. ADR ссылающиеся на §12 — minor добавление примечания. -- **Schema БД, открытые вопросы, schema нормативки structurе** — не трогается. -- **Memory user/project/reference** — не трогаются (кроме 2 архивируемых). -- **`router-stop-gate.mjs`, `observer-of-observer.mjs`, `observer-coverage-checker.mjs`, экономические хуки, subagent-prompt-prefix.mjs** — без изменений. -- **Project-skills** (`audit-portal`, `regression`, `brain-retro`, `billing-audit`, `security-go-live`) — не трогаются. На старте фазы 2 controller добавляет их `capabilities` в nodes.yaml. -- **Permission allowlist в settings.json** — не трогается. Gate работает независимо. +- Pravila §1-§11, §13, §14, §15. §16 (только §16.4 minor). +- ADR — все сохраняются. +- Schema БД, открытые вопросы, schema нормативки structure — не трогаются. +- Memory user/project/reference — не трогаются (кроме 2 архивируемых). +- `router-stop-gate.mjs`, `observer-of-observer.mjs`, `observer-coverage-checker.mjs`, экономические хуки, subagent-prompt-prefix.mjs — без изменений. +- Project-skills (`audit-portal`, `regression`, `brain-retro`, `billing-audit`, `security-go-live`) — не трогаются. Capabilities добавляются в nodes.yaml. +- Permission allowlist в settings.json — не трогается. --- @@ -854,344 +786,287 @@ Total: $X.XX ### 9.1. C1 L1-watcher -**Сейчас** (`tools/l1-watcher.mjs`): проверяет `.claude/settings.json` enabledPlugins ↔ Tooling §3.3. - -**После:** переключается на `.claude/settings.json` ↔ `docs/registry/nodes.yaml` registered plugins. +Сейчас: `.claude/settings.json` ↔ Tooling §3.3. После: ↔ `docs/registry/nodes.yaml` registered plugins. ### 9.2. C2 Cross-ref-checker -**Сейчас** (`tools/cross-ref-checker.mjs`): version cross-refs между 4 нормативными файлами. - -**После:** обновляется список ожидаемых cross-refs (§12 → §17, удаляются §3.3-cross-refs). +Обновляется список ожидаемых cross-refs (§12 → §17). ### 9.3. C3 Observer-of-observer -**Сейчас:** 54-week self-prune detection. **После:** без изменений. +Без изменений. -### 9.4. C4 Сигнальный статус (STATUS.md generator) +### 9.4. C4 STATUS.md generator -**Сейчас** (`tools/status-md-generator.mjs`): генерит STATUS.md с C1-C5 + discipline metrics. - -**После:** расширяется секциями: - -- Cost monitoring (per-month). -- Classifier anomaly count. -- Self-retrospect last run date + key findings. -- Sanity-check coverage %. +Расширяется секциями: Cost monitoring, Classifier anomaly, Self-retrospect last, Sanity-check coverage, Reviewer subagent vs direct-fallback ratio. ### 9.5. C5 Observer-coverage-checker -**Сейчас:** missed-activations count + episode coverage. +Missed-activations логика работает с §17. -**После:** missed-activations логика **работает с §17** — теперь missed-activation = «classifier рекомендовал skill, но actual_node=direct без escape-hatch». +### 9.6. C6 Chain-map-checker -### 9.6. C6 Chain-map-checker (closes B7) - -**Сейчас:** проверяет chains в map. - -**После:** обновляется источник — nodes.yaml chains section. +Источник: nodes.yaml chains section. --- -## 10. Гранулярные flag-переключатели + откат +## 10. Гранулярные flag-переключатели + rollback -**Все flag'и в `~/.claude/runtime/`:** +**9 flag'ов в `~/.claude/runtime/` (было 7 в v2.0, +2):** -| flag-файл | значения | по умолчанию (после фазы N) | управляет | +| flag-файл | значения | по умолчанию | управляет | |---|---|---|---| | `router-classifier-mode.json` | `llm-first` \| `hybrid` \| `regex-first` | `llm-first` после ф.2 | какой classifier работает | | `router-gate-mode.json` | `off` \| `warn-only` \| `enforce` | `warn-only` всё bootstrap | §17 enforcement | | `self-assessment-mode.json` | `on` \| `off` | `on` после ф.3 step 2 | Stop-hook self-assessment | -| `opus-reviewer-mode.json` | `on` \| `off` | `on` после ф.3 | reviewer в /brain-retro | +| `reviewer-mode.json` | `subagent` \| `direct-api` \| `off` | `subagent` после ф.3 | reviewer в /brain-retro (v2.1 расширены значения) | | `self-retrospect-mode.json` | `on` \| `off` | `on` после ф.3 step 3 | /self-retrospect доступен | | `embedding-mode.json` | `on` \| `off` | `on` после ф.3 step 3 | embedding в episodes | | `sanity-check-mode.json` | `mandatory` \| `optional` \| `off` | `mandatory` после ф.3 | sanity в /brain-retro | +| `prompt-enrichment-mode.json` (новое v2.1) | `on` \| `off` | `on` после ф.2 | памятка classifier | +| `inheritance-mode.json` (новое v2.1) | `on` \| `off` | `on` после ф.2 | inheritance + 3 группы в prefilter | -**Hot-reload:** каждый component читает свой flag при invocation. Flip — мгновенно, без перезапуска сессии. +**Hot-reload:** каждый component читает свой flag при invocation. **Полный откат:** -1. Все flag'и → pre-overhaul state. -2. Run `node tools/test-rollback.mjs --dry-run`. -3. Run `node tools/test-rollback.mjs --execute` — восстанавливает все файлы. +1. Flag'и → pre-overhaul state. +2. `node tools/test-rollback.mjs --dry-run`. +3. `node tools/test-rollback.mjs --execute`. 4. Smoke regression. -5. Время: ~1 час. +5. Время ~1 час. -**Granular откат:** flip один flag, smoke regression. +**Granular откат:** flip один flag, smoke. Inheritance off — короткие prompt'ы возвращаются к чистой conversation без наследования. Памятка off — classifier работает без 4 паттернов. -**Git tag pre-overhaul:** `brain-pre-llm-bootstrap` на коммите ДО фазы 1. +**Git tag pre-overhaul:** `brain-pre-llm-bootstrap`. -**Dry-run rollback automation** (`tools/test-rollback.mjs` — новый): - -- Создаёт временный git worktree. -- Восстанавливает all files из archive. -- Запускает smoke (lint + tests + key analyzer). -- Удаляет worktree. -- Reports: pass/fail per check. +**Dry-run rollback automation:** `tools/test-rollback.mjs` (новый). --- ## 11. Фазы реализации -### 11.A. Phase split - -**Implementation phases** (work для controller + subagents) — фазы 1, 2, 3. -**Passive phase** — evidence collection (4-6 месяцев между фазой 3 и фазой 4). -**Final implementation** — фаза 4 (distillation). - ### 11.1. Фаза 1 — Foundation + delete + archive (~1 неделя) -**Цель:** убрать §12, заархивировать routing-docs, подготовить инфру для §17. - -**Tasks:** - 1. Git tag `brain-pre-llm-bootstrap`. -2. Создать `docs/archive/llm-bootstrap-2026-05/` со структурой. -3. **Inventory** реального state (§18 содержит initial snapshot, фаза 1 обновляет под фактическое): - - List user-level hooks из `~/.claude/settings.json` (если есть). - - Snapshot nodes.yaml. - - Snapshot затронутых settings.json. -4. Архивировать Pravila §12. -5. Удалить cross-refs §12 из CLAUDE.md §5 п.11, PSR_v1 R0.4.A, Tooling §7. -6. Удалить skill-discipline hooks из `~/.claude/settings.json` (если найдены при inventory). -7. Архивировать routing-off-phase.md, router-procedure.md. -8. Архивировать CLAUDE.md §3.3 → заменить на pin. -9. Архивировать PSR_v1 R15. -10. Архивировать `tools/observer-classification-map.json`. -11. Архивировать 2 memory-файла. -12. Создать flag-переключатели в `~/.claude/runtime/`: - - `router-gate-mode.json` = `off`. - - `skill-discipline-mode.json` = `off`. -13. Создать `ROLLBACK.md` в архиве. -14. Создать `tools/test-rollback.mjs` (dry-run автоматизация). -15. Smoke regression. -16. Добавить Pravila §17 (новая секция). -17. Создать **ADR-016 «§17 universal skill-coverage rule»** (закрывает E17). -18. Subagent-driven implementation per Pravila §15.1 (Sonnet/Opus для git-задач). +2. Создать `docs/archive/llm-bootstrap-2026-05/`. +3. Inventory user-level hooks `~/.claude/settings.json`. +4. Архивировать Pravila §12, удалить cross-refs. +5. Удалить skill-discipline hooks из `~/.claude/settings.json` (если найдены). +6. Архивировать routing-off-phase.md, router-procedure.md. +7. Архивировать CLAUDE.md §3.3 → pin на nodes.yaml. +8. Архивировать PSR_v1 R15. +9. Архивировать `tools/observer-classification-map.json`. +10. Архивировать 2 memory-файла. +11. Создать flag-переключатели в `~/.claude/runtime/`. +12. Создать ROLLBACK.md в архиве. +13. Создать `tools/test-rollback.mjs`. +14. Smoke regression. +15. Добавить Pravila §17. +16. Создать ADR-016 «§17 universal skill-coverage». +17. Subagent-driven implementation per Pravila §15.1. -**Выход фазы 1:** §12 нет, §17 в Pravila, ничего не enforce'ится (gate off). Routing работает по старому regex Layer 1 (временно). Это **переходное окно**, длится 1 неделю. Trade-off обсуждён в §19.B. +**Выход:** §12 нет, §17 в Pravila, ничего не enforce'ится. Переходное окно 1 неделя. -### 11.2. Фаза 2 — Classifier + nodes.yaml capabilities + §17 logic (~1-1.5 недели) +### 11.2. Фаза 2 — Classifier + памятка + inheritance + §17 logic (~1-1.5 недели) -**Цель:** перевести classifier на LLM-first, ввести §17 enforcement (warn-only), schema v4.0. - -**Tasks:** - -1. Verify model ID Sonnet 4.6 через `anthropic.models.list()`. Записать точный ID в config. -2. Заполнить `capabilities:` в nodes.yaml для всех 84 узлов (subagent task ~2-4 часа). +1. Verify model ID Sonnet 4.6. +2. Заполнить `capabilities:` в nodes.yaml для всех 84 узлов. 3. Переписать `tools/router-classifier.mjs`: - - Conversation/micro/manual_override/anchor prefilter (§4.1). - - LLM-classifier на Sonnet 4.6 (§4.2). - - Удалить `classifyByRegex` primary path. Сохранить как `tools/router-classifier-regex-fallback.mjs`. - - Cost tracking writes в router-state. -4. Создать `tools/router-embedding.mjs` (§4.3). -5. Создать SessionStart hook для embedding warmup. -6. Расширить `tools/router-tool-gate.mjs` (§17 enforcement, mode warn-only). + - **Prefilter с 3 группами + manual override + anchor + micro + continuation inheritance + cancellation + acknowledgment** (закрывает 1.3, 2.4, 2.5). + - LLM-classifier на Sonnet 4.6. + - **+ ПАМЯТКА (4 паттерна) в LLM_SYSTEM_PROMPT** (закрывает 1.1). + - Удалить classifyByRegex primary, сохранить как fallback. + - Cost tracking writes. +4. Создать `tools/router-embedding.mjs` **с условием skip для conversation/micro/manual_override** (закрывает 3.3). +5. Создать SessionStart hook для warmup. +6. Расширить `tools/router-tool-gate.mjs` (§17 enforcement, warn-only). 7. Расширить `tools/router-prehook.mjs`: - - Удалить `ENFORCEMENT_TYPES` whitelist (старая §12 логика). + - Удалить ENFORCEMENT_TYPES whitelist. - Использовать новые поля classifier_output. -8. Обновить `tools/observer-transcript-parser.mjs` — handle schema v4.0. -9. Adapt `tools/registry-load.mjs` + `tools/registry-render.mjs` если требуется (закрывает A6). -10. Smoke regression + integration test «prompt → classifier → gate → tool». -11. Flip `router-classifier-mode` → `llm-first`. + - **Inheritance logic** (если continuation pattern → read prev state, наследовать) (закрывает 1.3). + - **30-минутный таймаут наследования** (закрывает 1.3). +8. Обновить `tools/observer-transcript-parser.mjs` — handle v4.0. +9. Adapt `tools/registry-load.mjs`, `tools/registry-render.mjs`. +10. Smoke regression + integration test. +11. Flip flags `router-classifier-mode → llm-first`, `prompt-enrichment-mode → on`, `inheritance-mode → on`. -**Выход фазы 2:** новый router работает. Эпизоды v4.0 пишутся. §17 warn-only активен. +**Выход:** новый router работает. Эпизоды v4.0 + inheritance fields. §17 warn-only. ### 11.3. Фаза 3 — Evidence loop (~1.5-2 недели) -**Цель:** evidence pipeline (self_assessment + Opus reviewer + sanity-check + self-retrospect). - **Step 3.1 (~3-4 дня):** - Расширить `tools/observer-stop-hook.mjs`: execution_trace + chain_gaps writing. -- Bump schema v4.0 → v4.1. +- Bump v4.0 → v4.1 (включая inheritance fields в episode). - Settings.json: Stop-hook timeout 5s → 15s. **Step 3.2 (~4-5 дней):** -- Добавить self_assessment в Stop-hook (§4.5). -- Создать `tools/brain-retro-opus-reviewer.mjs` (§4.6). -- Bump schema v4.1 → v4.2. +- Добавить self_assessment в Stop-hook. +- **Создать `.claude/agents/reviewer-agent.md` (закрывает 1.2, 2.1, 2.3) — Claude Code subagent с tools=[Read,Grep,Glob,Skill], model=opus, system prompt со skill доступом.** +- Расширить `/brain-retro` skill: шаг 6 теперь делает `Task(subagent_type='reviewer-agent', ...)` per episode. +- **Fallback на direct API при subagent crash (закрывает 2.2).** +- Bump v4.1 → v4.2. **Step 3.3 (~4-5 дней):** - Создать `tools/brain-retro-sanity-generator.mjs`. -- Расширить `.claude/skills/brain-retro/SKILL.md`: новые шаги 5/6/9/11. -- Обновить `.claude/skills/brain-retro/references/aggregation-template.md`. -- Создать `.claude/skills/self-retrospect/SKILL.md` (§4.8). -- Расширить `tools/brain-retro-analyzer.mjs` для v4.* факторов. -- Расширить `tools/status-md-generator.mjs` для cost + classifier anomaly + self-retrospect секций. -- Создать `docs/observer/.self-retrospect-counter.json`. +- Расширить `.claude/skills/brain-retro/SKILL.md`: новые шаги. +- **Обновить description в SKILL.md frontmatter (закрывает 3.1):** «Use каждые 1-2 недели OR при триггере sanity-check threshold». +- **Обновить references/aggregation-template.md** под расширенную процедуру. +- Создать `.claude/skills/self-retrospect/SKILL.md`. +- Расширить `tools/brain-retro-analyzer.mjs` для v4.* факторов + inheritance анализ. +- Расширить `tools/status-md-generator.mjs` для cost + classifier anomaly + self-retrospect + reviewer subagent/fallback ratio секций. +- **Init `docs/observer/.self-retrospect-counter.json` с `{last_run_at: null, episodes_since_last: 0}` (закрывает 3.7).** +- **Init `docs/observer/sanity-checks/` directory.** - Embedding pre-warm SessionStart hook. -- Bump schema v4.2 → v4.3. +- **PII filter wrapping для sanity comments (закрывает 3.4).** +- Bump v4.2 → v4.3. - Smoke regression. -- Flip flags `self-assessment-mode`, `opus-reviewer-mode`, `self-retrospect-mode`, `embedding-mode`, `sanity-check-mode` → on/mandatory. +- Flip flags: self-assessment-mode, reviewer-mode=subagent, self-retrospect-mode, embedding-mode, sanity-check-mode=mandatory → on. -**Выход фазы 3:** полный evidence pipeline работает. +**Выход:** полный evidence pipeline. Reviewer — subagent. Episode v4.3 с inheritance + памяткой. -### 11.P. Passive period — evidence collection (~5-6 месяцев) +### 11.P. Passive period (~5-6 месяцев) - Без implementation work. -- Дмитрий вызывает `/brain-retro` раз в 1-2 недели. -- Накапливается база. -- Self-retrospect — по необходимости. -- Mid-bootstrap checkpoint (через 3 месяца, закрывает E4): - - Snapshot метрик: % эпизодов с review, distribution outcome_reviewed, top patterns. - - Decide: extend/shrink bootstrap, adjust §17 mode. +- /brain-retro раз в 1-2 недели. +- Mid-bootstrap checkpoint (через 3 месяца). ### 11.4. Фаза 4 — Distillation (~2-3 недели, через ~6 месяцев) -**Цель:** вывести regex-правила из эмпирики, переключить на hybrid. - -**Tasks:** - -1. **Sample selection:** `review.node_quality='correct'` AND `outcome_reviewed in {'success', 'soft_success'}`. Ожидаемо ~300-500 эпизодов. -2. **Кластеризация** по embedding (DBSCAN или hierarchical, eps подбирается на validation set). -3. **Per-cluster regex extraction** — keyword-stems из prompt'ов кластера. -4. **Сборка regex-классификатора v2.0** из дистиллированных правил. -5. **A/B тест** на holdout (20% эпизодов): accuracy regex vs LLM. -6. **Если regex accuracy < 70%** — extend bootstrap. -7. **Если regex accuracy ≥ 70%** — flip `router-classifier-mode` → `hybrid`. -8. **Обновить nodes.yaml** `triggers[]` — эмпирические. -9. **Решение по §17** — на основе evidence: - - 95%+ задач имели skill-coverage без issues → §17 confirmed, можно flip enforce. - - 70-95% → soft-§17, оставить warn-only. - - <70% → §17 не работает, снять. -10. **Spec-документ результатов** в `docs/superpowers/specs/2026-XX-XX-distillation-results.md`. -11. Update ADR-016 status. +1. Sample selection: `review.node_quality='correct' AND outcome_reviewed in {success, soft_success}`. +2. Кластеризация по embedding. +3. Per-cluster regex extraction. +4. Сборка regex v2.0. +5. A/B тест на holdout. +6. Если accuracy <70% — extend bootstrap. +7. Если ≥70% — flip `router-classifier-mode` → `hybrid`. +8. Обновить nodes.yaml triggers — эмпирические. +9. Решение по §17. +10. Spec результатов в `docs/superpowers/specs/2026-XX-XX-distillation-results.md`. +11. Update ADR-016. --- ## 12. Cost monitoring (без cap, с daily dashboard) -**Решение владельца:** жёсткого лимита нет. **Усиление в v2.0:** daily cost dashboard обновляется каждым Stop-hook'ом. - **Что мониторится:** - `task_cost.classifier_input/output_tokens` × Sonnet 4.6 pricing - `task_cost.self_assessment_*` × Opus 4.7 pricing -- `task_cost.reviewer_*` × Opus 4.7 pricing +- **`task_cost.reviewer_subagent_usd` — Opus subagent invocation cost (новое v2.1)** +- **`task_cost.reviewer_direct_fallback_usd` — fallback при subagent crash (новое v2.1)** - Self-retrospect cost при invocation -**Где показывается:** +**Daily aggregation:** `~/.claude/runtime/cost-daily.json`: -1. **Daily aggregation:** `~/.claude/runtime/cost-daily.json` — updated по Stop-hook'у. Rolling 30-day: +```json +{ + "2026-06-15": { + "classifier_usd": 2.10, + "self_assessment_usd": 3.40, + "reviewer_subagent_usd": 0.00, + "reviewer_direct_fallback_usd": 0.00, + "self_retrospect_usd": 0.00, + "total_usd": 5.50, + "episode_count": 87 + } +} +``` - ```json - { - "2026-06-15": { - "classifier_usd": 2.10, - "self_assessment_usd": 3.40, - "reviewer_usd": 0.00, - "self_retrospect_usd": 0.00, - "total_usd": 5.50, - "episode_count": 87 - } - } - ``` +**STATUS.md** секция «Cost monitoring» + `/brain-retro` summary. -2. **STATUS.md** секция «Cost monitoring» — top 7 days + monthly total. -3. **`/brain-retro` summary** — per-period cost report. - -**Anomaly detection** (закрывает E15): +**Anomaly detection:** - Per-episode WARN: `task_cost.classifier_output_tokens > MAX(median × 3, 5000)`. - Per-day WARN: `total_usd > 1.5 × median_30day`. -- WARN записывается в STATUS.md секцию «Anomalies» + episode `classifier_anomaly: true`. -**Если runaway:** - -- Daily WARN видим в течение суток. -- Flip `router-classifier-mode` → `regex-first`. -- Granular rollback ~1 час. - -**Ожидаемая стоимость (revised):** +**Ожидаемая стоимость (revised v2.1 — reviewer subagent):** | компонент | $$/мес ожидание | |---|---| -| Sonnet 4.6 classifier (50-100 prompt/день × $0.02) | $30-60 | +| Sonnet 4.6 classifier + памятка (50-100 prompt/день × $0.025) | $38-75 | | Self-assessment в Stop-hook (50-100 task/день × $0.03) | $30-60 | -| Opus 4.7 reviewer (200 episodes × 4 retro/мес × $0.07) | $50-90 | +| Reviewer SUBAGENT (200 episodes × 4 retro/мес × $0.50) | $240-1200 (главный driver) | +| Reviewer direct-fallback (1-5% crashes × $0.05) | $5-15 | | Self-retrospect (~$2-5 × 2-4 calls/мес) | $10-20 | -| Embedding (локально) | $0 | -| **Total** | **$120-230/мес** | +| Embedding (локально, только non-prefilter) | $0 | +| **Total** | **$323-1370/мес** | -За 6 месяцев bootstrap: **~$720-1380**. Шире чем v1.0 ($1140) — учитывает honest self-retrospect и variability. +За 6 месяцев bootstrap: **~$1940-8200**. **Значительно выше v2.0 ($720-1380)** из-за reviewer-subagent (×6-15 vs direct API). Это **сознательный trade-off** за качество review (cross-episode context, skill invocations). + +**Если subagent reviewer слишком дорог — granular rollback:** flip `reviewer-mode` → `direct-api`. Возвращаемся к v2.0 стоимости. --- -## 13. Связанные изменения в нормативке (карта правок) - -Все через subagent-driven-development, pre-flight Pravila §15.2. +## 13. Связанные изменения в нормативке ### 13.1. Pravila -- **§12 удаляется** (sub-секции 12.1-12.4). -- **§17 добавляется**. -- **§16.4** обновляется (missed-activations интегрируются с §17). -- **§0/§1 cross-refs** обновляются. -- **§9 changelog** entry. +- §12 удаляется. +- §17 добавляется (с подпунктами включая Continuation/Acknowledgment/Cancellation от v2.1). +- §16.4 обновляется. +- §0/§1 cross-refs. +- §9 changelog. ### 13.2. CLAUDE.md -- **§3.3 удаляется** (→ pin на nodes.yaml). -- **§5 п.11 переписывается** («§17 universal skill-coverage; classifier рекомендует, sturdy enforces в warn-only»). -- **§0 cross-refs** обновляются. -- **§9 history** entry. +- §3.3 удаляется. +- §5 п.11 переписывается. +- §0 cross-refs. +- §9 history. ### 13.3. PSR_v1 -- **R10.1 счётчики** → pin на nodes.yaml. -- **R15** удаляется. -- **R0.4.A** упоминание §12 → §17. -- **§0 cross-refs** обновляются. +- R10.1 счётчики → pin. +- R15 удаляется. +- R0.4.A: §12 → §17. ### 13.4. Tooling Прил.Н -- **§4.X поля «когда брать»** удаляются (inventory подтвердил их отсутствие — проверить повторно на старте фазы 1). -- **§0 счётчики** — pin на nodes.yaml header. -- **§3.X cross-refs на router-procedure.md** удаляются. -- **§9.X changelog** entry. +- §4.X «когда брать» удаляются (inventory подтвердил отсутствие). +- §0 счётчики → pin. +- §3.X cross-refs. ### 13.5. nodes.yaml -- Добавляются `capabilities:` per узел (новое поле, фаза 2). -- `triggers[]` — остаются. -- L1-L16 chains — остаются. -- Capabilities для project-skills — добавляются если нет. +- `capabilities:` per узел. +- triggers + chains остаются. ### 13.6. ADR-016 (новый) -«§17 universal skill-coverage rule replaces §12». Структура: - -- Status: Accepted. -- Context: §12 a-priori bias on routing evidence; empirical distillation requires removing principal bias. -- Decision: replace §12 with §17 (default-deny except conversation/micro/manual_override). -- Consequences: see §19. -- Boundaries: §17 vs Pravila §14 (Ruflo dormant) vs §15 (procedural). +«§17 universal skill-coverage rule replaces §12». Структура: Status / Context / Decision / Consequences / Boundaries. --- -## 14. Risk register (расширен) +## 14. Risk register | риск | вероятность | impact | митигация | |---|---|---|---| -| Classifier систематически промахивается | средняя | высокий | Opus reviewer + sanity-check ловят, гранулярный rollback | -| Self-assessment Stop-hook жрёт $$ | высокая | средний | Daily cost dashboard, anomaly WARN, flag off | -| Sonnet/Opus API down во время /brain-retro | средняя | низкий | Fallback chain (Haiku → regex), повтор | -| Embedding-модель не загружается на Windows | низкая | высокий | Fallback NULL embedding, self-retrospect → task_type clustering | -| §17 enforcement блокирует легитимные direct | средняя | средний | warn-only всё bootstrap, escape-hatch, flag rollback | -| Anthropic breaking change в API | средняя | высокий | classifier_model в episode → датасет разделим; fallback chain | -| Cost runaway (баг в цикле) | низкая | высокий | Daily dashboard, anomaly WARN, granular rollback ~1 час | -| Дмитрий не вызывает /brain-retro | средняя | высокий | self-retrospect opt-in, reviewer накапливает queue | -| Mid-bootstrap evidence низкого качества | средняя | средний | Checkpoint через 3 месяца — decide extend | -| Spec устаревает за phase split | низкая | низкий | Refresh check перед каждой фазой | -| Conversation prefilter false-positive «делай аудит» | средняя | средний | Anchor detection ловит существительное → fall through | -| outcome_reviewed качество низкое (Opus proxy) | средняя | средний | Sanity-check answers как signal, marker source | +| Classifier систематически промахивается | средняя | высокий | Reviewer subagent + sanity-check, granular rollback | +| Self-assessment Stop-hook жрёт $$ | высокая | средний | Daily dashboard, flag off | +| Sonnet/Opus API down | средняя | низкий | Fallback chain (Haiku → regex для classifier; direct API для reviewer) | +| Embedding не загружается на Windows | низкая | высокий | Fallback NULL embedding | +| §17 enforcement блокирует legitimate direct | средняя | средний | warn-only всё bootstrap, escape-hatch, rollback | +| Anthropic breaking change в API | средняя | высокий | classifier_model в episode → датасет split; fallback chain | +| Cost runaway | низкая | высокий | Daily dashboard, anomaly WARN, granular rollback ~1 час | +| **Reviewer subagent stoимость взлетает (v2.1)** | **высокая** | **высокий** | **Daily monitoring, flag `reviewer-mode → direct-api` для отката к v2.0 ценам** | +| **Reviewer subagent crashes часто (v2.1)** | **средняя** | **средний** | **per-episode try/catch, fallback на direct API, tracked в episode review.reviewer field** | +| **Reviewer subagent context bloat (v2.1)** | **средняя** | **средний** | **agent system prompt: max 10 соседних эпизодов** | +| Дмитрий не вызывает /brain-retro | средняя | высокий | self-retrospect opt-in, reviewer queue | +| Mid-bootstrap evidence низкого качества | средняя | средний | Checkpoint через 3 месяца | +| Spec устаревает за phase split | низкая | низкий | Refresh check | +| Conversation prefilter false-positive «делай аудит» | низкая | средний | Anchor detection (закрытый риск v2.1) | +| outcome_reviewed качество proxy | средняя | средний | sanity-check + reviewer subagent cross-episode insights | | Sanity-check вопросы шумные | средняя | низкий | top-5 candidates, калибровка | -| Self-retrospect не находит паттернов первые 3 месяца | высокая | низкий | OK — мало данных, calibration period | +| Self-retrospect не находит паттернов первые 3 месяца | высокая | низкий | OK — calibration period | | nodes.yaml capabilities пропускает узлы | низкая | средний | Subagent task с verification | -| Permission interaction breakage | низкая | высокий | Smoke test «все existing скрипты работают» в фазе 2 | +| Permission interaction breakage | низкая | высокий | Smoke test | +| **Inheritance переносит неверный контекст (v2.1)** | **средняя** | **низкий** | **30-минутный таймаут, следующее сообщение откатывает; ущерб = 1 лишний tool-call** | +| **Inheritance + manual override приоритет (v2.1)** | **низкая** | **низкий** | **Manual override проверка первая в prefilter (закрыто 2.4)** | +| **PII утечка через sanity-check comments (v2.1)** | **низкая** | **высокий** | **PII filter wraps comment перед сохранением (закрыто 3.4)** | --- @@ -1199,25 +1074,28 @@ Total: $X.XX **Фаза 1:** -- Точные имена hooks в `~/.claude/settings.json` user-level — inventory шаг. -- Точная структура архивных папок. +- Точные имена hooks `~/.claude/settings.json` user-level. +- Структура архивных папок. **Фаза 2:** - Exact model ID Sonnet 4.6. - Capabilities-описания узлов — generation strategy. -- Embedding daemon vs per-call decision (latency-based). -- Recommended_chain хранение: id vs array vs both. +- Embedding daemon vs per-call (latency). +- recommended_chain хранение: id vs array vs both. +- **Inheritance edge case «да в ответ на мой вопрос с выбором» — переходить ли в decision_provenance.kind=user_chose_from_options (v2.1, deferred to явному triggered case в evidence).** **Фаза 3:** -- Sanity questions formulation — calibration на первых 2-3 /brain-retro. -- Self-retrospect counter — exact threshold. -- Self-retrospect skill `description` formulation. +- Sanity questions formulation calibration. +- Self-retrospect counter exact threshold. +- Self-retrospect skill description formulation. +- **Reviewer agent system prompt — детальная формулировка чек-листа review (v2.1).** +- **Reviewer agent maximum context cap — 10 эпизодов hard-limit или soft? (v2.1)** **Фаза 4:** -- Embedding clustering algorithm. +- Embedding clustering algorithm (DBSCAN/k-means/hierarchical). - Regex extraction algorithm. - A/B test threshold. @@ -1228,53 +1106,56 @@ Total: $X.XX ### После фазы 3 - ✅ Pravila §12 в архиве, §17 в Pravila, ADR-016 в `docs/adr/`. -- ✅ Skill-discipline hooks (если были) в архиве, выключены в `~/.claude/settings.json`. +- ✅ Skill-discipline hooks (если были) в архиве. - ✅ Routing-docs в архиве. -- ✅ Sonnet 4.6 classifier работает с verified model ID, prefilter активен. +- ✅ Sonnet 4.6 classifier работает с verified model ID, **prefilter с 3 группами + inheritance + памятка активны (v2.1)**. - ✅ §17 enforcement в warn-only mode. -- ✅ Embedding пишется в эпизоды (Base64), pre-warm SessionStart активен. +- ✅ Embedding пишется в эпизоды (только non-prefilter), pre-warm SessionStart активен. - ✅ Schema v4.3 пишется. Парсер handles v1/v2/v3/v4 для read. -- ✅ Self_assessment пишется в Stop-event (с retroactive fallback). -- ✅ /brain-retro: sanity-check (mandatory) + Opus reviewer + опциональный self-retrospect. +- ✅ Self_assessment пишется в Stop-event с retroactive fallback. +- ✅ **Reviewer subagent agent file `.claude/agents/reviewer-agent.md` создан и работает (v2.1)**. +- ✅ /brain-retro: sanity-check (mandatory, с PII filter) + reviewer subagent (с fallback на direct API) + опциональный self-retrospect. - ✅ /self-retrospect skill доступен (opt-in). -- ✅ Daily cost dashboard обновляется. -- ✅ STATUS.md показывает cost + classifier anomaly + self-retrospect. +- ✅ Daily cost dashboard обновляется + tracking subagent vs direct-fallback ratio. +- ✅ STATUS.md показывает cost + classifier anomaly + self-retrospect + subagent/fallback ratio. - ✅ ROLLBACK.md протестирован через `tools/test-rollback.mjs --dry-run`. -- ✅ 7 flag-переключателей работают (smoke per-flag). +- ✅ **9 flag-переключателей работают (v2.1: было 7, +prompt-enrichment + inheritance)**. - ✅ Регрессия: markdownlint / cross-ref-checker / l1-watcher / observer-coverage / chain-map-checker / lychee / gitleaks — GREEN. - ✅ nodes.yaml: `capabilities:` заполнен для всех 84 узлов. +- ✅ `docs/observer/.self-retrospect-counter.json` создан. +- ✅ `docs/observer/sanity-checks/` directory existed. +- ✅ brain-retro SKILL.md description обновлён. -### Mid-bootstrap (~3 месяца после фазы 3) +### Mid-bootstrap (~3 месяца) - ✅ ~500-700 episodes собрано. - ✅ ≥70% episodes имеют review.* заполненный. - ✅ Distribution outcome_reviewed: ≥60% success/soft_success, <10% blocked. - ✅ Mid-bootstrap checkpoint snapshot. +- ✅ **Reviewer subagent stability: ≥90% Task spawns успешны, <10% fallback на direct API.** ### После фазы 4 -- ✅ Дистиллированный regex-классификатор v2.0 в production. -- ✅ A/B тест регекса vs LLM на holdout — accuracy report. -- ✅ Spec результатов дистилляции. -- ✅ Решение по §17: confirmed/amended/снят. ADR-016 status updated. +- ✅ Дистиллированный regex v2.0 в production. +- ✅ A/B тест accuracy report. +- ✅ Spec результатов. +- ✅ Решение по §17. --- ## 17. Связь с другими активными эпиками -- **Биллинг v2 Спек C** — отдельный эпик. Этот overhaul **не блокирует** и **не зависит**. Per user decision (2026-05-24): сначала Спек C, потом стартует этот overhaul. -- **Security go-live** — отдельный эпик. -- **Other epics** — нет зависимостей. +- Биллинг v2 Спек C — отдельный, **не блокирует**. Per user decision (2026-05-24): сначала Спек C, потом overhaul. +- Security go-live — отдельный. +- Other — без зависимостей. -Spec самостоятелен — реализация может стартовать в любой момент. +Spec самостоятелен. --- ## 18. Pre-implementation state inventory -Реальное состояние на 2026-05-25 (после verification, фаза 1 обновит под актуальное). - -### 18.1. Hook files в проекте +### 18.1. Hook files ```text .claude/settings.json hooks: @@ -1287,17 +1168,17 @@ Spec самостоятелен — реализация может старто - UserPromptSubmit: tools/router-prehook.mjs ``` -**Skill-discipline hooks в проекте — НЕТ.** Если есть — то в `~/.claude/settings.json` user-level (вне репо, inventory на фазе 1). +Skill-discipline hooks в проекте — НЕТ. Если есть — то в `~/.claude/settings.json` user-level. -### 18.2. tools/ inventory (relevant subset) +### 18.2. tools/ inventory ```text router-classifier.mjs (260 строк) — regex Layer 1 + Haiku Layer 2 -router-tool-gate.mjs (112 строк) — §17 enforcement текущая база +router-tool-gate.mjs (112 строк) — §17 enforcement база router-prehook.mjs (106 строк) — ENFORCEMENT_TYPES whitelist router-stop-gate.mjs, router-stdin-helper.mjs, router-accuracy-runner.mjs — без изменений observer-stop-hook.mjs (262 строк) — episode write -observer-transcript-parser.mjs — handles v1/v2/v3 read +observer-transcript-parser.mjs — handles v1/v2/v3 observer-routing-detector.mjs — detects user_directed_method observer-classification-map.json — DEPRECATED 2026-05-24 observer-pii-filter.mjs, observer-choice-detector.mjs, observer-chain-detector.mjs, @@ -1311,128 +1192,136 @@ brain-retro-analyzer.mjs — будет расширен status-md-generator.mjs — будет расширен missed-activations.mjs — адаптирован к §17 discipline-metrics.mjs — inventory & decide keep/remove -registry-load.mjs, registry-render.mjs, registry-to-classification-map.mjs — могут потребовать adapt +registry-load.mjs, registry-render.mjs, registry-to-classification-map.mjs — adapt ``` -### 18.3. nodes.yaml структура (актуальная) +### 18.3. nodes.yaml структура -Per-node fields: +Per-node fields: id, name, slug, category, subcategory, status, dormancy_reason, triggers[], boundaries, chain_membership, attributes. -```yaml -- id: "#N" - name: "..." - slug: "..." - category: "..." - subcategory: null | "..." - status: "active" | "dormant" - dormancy_reason: null | "..." - triggers: - - {keyword: "...", weight: 1.0} - - {classification: "...", weight: 1.0} - boundaries: [] - chain_membership: ["L1", ...] - attributes: - tooling_section: "§N.M #N" -``` +Полей `when_to_use` / `routing_triggers` / `description` / `capabilities` — НЕТ. Фаза 2 добавляет `capabilities:`. -**Полей `when_to_use` / `routing_triggers` / `description` / `capabilities` — НЕТ.** Фаза 2 добавляет `capabilities:` per узел. +L1-L16 chains: lines 1591-1713. -L1-L16 chains: lines 1591-1713, структура `chains: {L1: {name, sequence}, ...}`. +### 18.4. Pravila §12 -### 18.4. Pravila §12 — фактическое состояние +Существует, sub-секции 12.1-12.4. -§12 существует, sub-секции 12.1-12.4. §12.3 — SoT для exclusions. §12.4 — explicit hard-rule статус. +### 18.5. Episode JSONL -### 18.5. Episode JSONL distribution +239 lines = 5 v1 + 139 v2 + 95 v3. -Текущий `docs/observer/episodes-2026-05.jsonl`: 239 lines = 5 v1 + 139 v2 + 95 v3. После фазы 3 — v4.* добавятся. - -### 18.6. Memory inventory +### 18.6. Memory Brain-related: - `feedback_superpowers_hard_rule.md` — архивируется. - `feedback_feature_via_writing_plans.md` — архивируется. -- `feedback_brain_unused_tools_not_problem.md` — остаётся, cross-refs обновятся. +- `feedback_brain_unused_tools_not_problem.md` — остаётся. - `feedback_brain_counter_canon.md` — остаётся. - `project_brain_governance_design.md` — остаётся. - `project_observer_*` — остаются. +### 18.7. Existing project agents (v2.1) + +В `.claude/agents/`: normative-sync.md, prod-deploy-validator.md, rls-reviewer.md, pest-parallel-debugger.md. Будет добавлен **reviewer-agent.md** в фазе 3 step 2. + --- ## 19. Accepted trade-offs -Явные компромиссы, осознанно принятые в дизайне. +### 19.A. §17 как a-priori vs эмпирический -### 19.A. §17 как a-priori правило vs эмпирический эксперимент +§17 — safety rail для bootstrap. Pure empirical = «всё через direct» = бесполезно для дистилляции. -**Конфликт:** §1.1 «принуждение skill смещает evidence». §17 — ТОЖЕ принуждение, шире чем §12. +### 19.B. Переходное окно (1 неделя) -**Trade-off:** соглашаемся что эксперимент тестирует **classifier accuracy и chain-suggestion quality**, не «нужен ли skill для X». Чистый empirical без principal rule = «всё через direct», не helpful для дистилляции. +Атомарная фаза 1+2 сложнее. Step-by-step безопаснее. Episodes окна помечаются `bootstrap_transition_week: true`, исключаются из дистилляции. -**Accept:** §17 — safety rail для bootstrap. Pure empirical — отдельная инициатива в будущем если §17 evidence biased. +### 19.C. Sanity-check mandatory -### 19.B. Переходное окно «§12 нет, §17 ещё не включён» (1 неделя) +Optional → skip → bias. Mandatory = 3 минуты раз в 1-2 недели. -**Конфликт:** в эту неделю агент работает без any rule. +### 19.D. Cost без cap -**Trade-off:** атомарная фаза 1+2 сложнее тестировать. Step-by-step безопаснее. - -**Accept:** 1 неделя evidence с пометкой `bootstrap_transition_week: true`. Исключается из дистилляции. - -### 19.C. Sanity-check mandatory, не optional - -**Конфликт:** «один touchpoint» vs «обязательно отвечать». - -**Trade-off:** optional → пользователь скипает → bias накапливается. Mandatory — 3 минуты раз в 1-2 недели, ниже порога friction. - -**Accept:** /brain-retro не завершается без ответов. Flag `sanity-check-mode` доступен для перехода в optional если будет реальная боль. - -### 19.D. Cost ~$120-230/мес без cap - -**Конфликт:** runaway risk. - -**Trade-off:** cap = false-security. Daily dashboard + anomaly WARN ловят runaway в течение часа. - -**Accept:** no cap, но honest daily dashboard. +Cap = false-security. Daily dashboard ловит runaway в час. ### 19.E. Opus reviewer заполняет outcome_reviewed как proxy -**Конфликт:** outcome_reviewed «по идее» от пользователя; per-episode никто не пишет. +Marker `outcome_reviewed_source: 'subagent_opus' | 'direct_opus_fallback' | 'opus_proxy'`. Это лучшее доступное автоматизированно. -**Trade-off:** ждать ручной per-episode review = wait forever. Opus + outcome_inferred + sanity = best available proxy. Marker `outcome_reviewed_source: 'opus_proxy'`. +### 19.F. Self-retrospect opt-in -**Accept:** proxy с explicit sourcing. Не «истина», лучшее что можно автоматизировать. +Auto = $30-120/мес стабильно. Opt-in = пользователь решает. -### 19.F. Self-retrospect opt-in (НЕ auto в /brain-retro) +### 19.G. Reviewer subagent ×6-15 vs direct API (v2.1) -**Конфликт:** «self-retrospect нужен» vs «cost не нулевой». +Цена $240-1200/мес vs $40-80. Trade-off за: cross-episode reading (real cross-context insights), skill invocations (systematic-debugging для failed cases). Качественный выигрыш для тебя читать в /brain-retro отчётах. Для финального regex distillation эффект минимальный (regex не ловит nuance). -**Trade-off:** auto = $30-120/мес стабильно. Opt-in = пользователь решает, threshold-prompt напоминает. +**Принимаем** в пользу качества insights. Если cost оказался невыносим — `reviewer-mode → direct-api`. -**Accept:** opt-in default. Можно forced-on flag'ом. +### 19.H. Памятка classifier — небольшой bias за чистоту данных (v2.1) + +Памятка инструктирует classifier следовать конкретным методологиям (≥3 alternatives, ambiguous → no_skill_found). Это **bias** на «структурированный output», но он именно про **формат**, не про **выбор узла**. Принимаем как worthwhile trade-off. + +### 19.I. Inheritance таймаут 30 минут — эвристика, не наука (v2.1) + +30 минут выбран эвристически (типичный длительный context-switch). Если эвристика плохая — корректируется по факту через анализ inherited episodes в /brain-retro. --- -## 20. Что НЕ делается этим эпиком (non-goals) +## 20. Что НЕ делается этим эпиком -- **НЕ** трогается Pravila §14 (Ruflo dormant). -- **НЕ** трогается Pravila §15 (procedural). -- **НЕ** трогается Pravila §16 кроме minor §16.4. -- **НЕ** трогаются ADR (только cross-ref добавления). -- **НЕ** трогается `db/schema.sql`. -- **НЕ** трогается код Лидерра-портала. -- **НЕ** трогаются другие эпики. -- **НЕ** реализуется automated regex-distillation в фазах 1-3 (only manual в фазе 4). -- **НЕ** меняется outcome_inferred logic (sentiment-based). -- **НЕ** меняется PII-filter — применяется на episode write как сейчас. Anthropic API получает prompts как раньше (см. brainstorming decision F4=a). -- **НЕ** intermediate persistence-режим «классификатор только в офисное время». -- **НЕ** A/B тестируется «§12 vs §17 vs no-rule». -- **НЕ** реализуется UI для review (chat-only через /brain-retro). -- **НЕ** Anthropic Workbench integration — direct API. +- НЕ трогается Pravila §14, §15, §16 (кроме minor §16.4). +- НЕ трогаются ADR (только cross-ref). +- НЕ трогается db/schema.sql. +- НЕ трогается код Лидерра-портала. +- НЕ трогаются другие эпики. +- НЕ реализуется automated regex-distillation в фазах 1-3. +- НЕ меняется outcome_inferred logic. +- НЕ меняется PII-filter applied to episode write — но **добавляется** PII filter на sanity comments (v2.1). +- НЕ intermediate persistence-режим. +- НЕ A/B «§12 vs §17 vs no-rule». +- НЕ реализуется UI для review (chat-only). +- НЕ Anthropic Workbench integration. --- -**Версия spec:** 2.0 от 2026-05-25. -**Предыдущая версия:** v1.0 от 2026-05-24 (содержала 8 фактических ошибок, переписана целиком после критического анализа). -**Следующий шаг:** writing-plans skill для детального плана реализации фаз 1+2+3 с inventory-task на старте фазы 1. +## 21. Changelog v2.0 → v2.1 (новое) + +### Группа 1 — Решения принятые между v2.0 и v2.1 + +| # | Изменение | Где в spec | +|---|---|---| +| 1.1 | Памятка classifier (4 паттерна: brainstorming/discovery-interview/writing-plans/systematic-debugging) | §4.2, §10 (новый flag), §11.2, §12 | +| 1.2 | Reviewer как полноценный Claude Code subagent (tools=[Read,Grep,Glob,Skill], model=opus). Новый файл `.claude/agents/reviewer-agent.md`. | §4.6 (rewrite), §4.7, §10 (расширены значения reviewer-mode), §11.3 step 3.2, §12 (cost rewrite), §14, §16 | +| 1.3 | Inheritance + 3 группы коротких prompt'ов (continuation/acknowledgment/cancellation) + 30-минутный таймаут | §4.1, §4.2, §5 (новые поля), §10 (новый flag), §11.2, §14 (закрыт risk) | + +### Группа 2 — Edge cases + +| # | Изменение | Где | +|---|---|---| +| 2.1 | Reviewer model = opus явно в agent file | `.claude/agents/reviewer-agent.md` frontmatter | +| 2.2 | Reviewer subagent crash → fallback direct API | §4.6, §12, §14 | +| 2.3 | Reviewer context bloat: max 10 соседних эпизодов в system prompt | `.claude/agents/reviewer-agent.md`, §14 | +| 2.4 | Manual override приоритет над inheritance в prefilter | §4.1 | +| 2.5 | Cancellation → state classification clear + previous_task_id_rejected marker | §4.1, §5 | + +### Группа 3 — Мелкие упущения + +| # | Изменение | Где | +|---|---|---| +| 3.1 | brain-retro SKILL.md description update «раз в 1-2 недели» | §11.3 step 3.3 | +| 3.2 | recommended_chain_id может быть null если custom chain | §4.2, §5 | +| 3.3 | Embedding только для non-prefilter эпизодов | §4.3, §11.2 | +| 3.4 | PII filter wraps sanity-check comments | §4.7 step 5, §11.3, §14 | +| 3.5 | requested_node fuzzy matching fallback | §4.1 | +| 3.6 | Anchor word list inline (initial), вынос в config — потом | §4.1 | +| 3.7 | Self-retrospect counter init в фазе 3 step 3.3 | §11.3 step 3.3 | +| 3.8 | Sanity-check answer file schema_version=1 | §5 | + +--- + +**Версия spec:** 2.1 от 2026-05-25. +**Предыдущие версии:** v1.0 от 2026-05-24 (8 фактических ошибок). v2.0 от 2026-05-25 (полная перезапись). +**Следующий шаг:** writing-plans skill для детального плана реализации фаз 1+2+3 + создание `.claude/agents/reviewer-agent.md` в фазе 3 step 3.2.