---
title: Brain governance design — router-only + observer scope B + 4 контролёра
date: 2026-05-19
version: 1.1
status: design (approved by user; v1.1 amendment 2026-05-19 — structured routing_decision + primary_rationale for factor analysis per user request before subagent execution)
author: Дмитрий (заказчик) + Claude (Opus 4.7) via superpowers:brainstorming
related:
  - docs/discovery/2026-05-18-system-audit-brain.md
  - docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md
  - memory/project_brain_governance_design.md
  - memory/feedback_brain_unused_tools_not_problem.md
  - docs/Pravila_raboty_Claude_v1_1.md
  - docs/Plugin_stack_rules_v1.md
  - docs/Tooling_v8_3.md
  - docs/routing-off-phase.md
adr-target: ADR-011 (will be written during planning phase)
extension: docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md (observer factor-analysis, schema v2, 2026-05-19)
---

# Brain governance design — router-only + observer + 4 контролёра

## 0. TL;DR

«Мозг» Лидерры (60 формализованных позиций + 20 ruflo plugins на 18.05.2026 — счётчики канон в [Tooling Прил. Н §0](../../Tooling_v8_3.md)) накачивается быстрее, чем регулируется. SYSTEM-аудит 18.05.2026 + intervention-сессия 19.05.2026 пришли к **router-only** архитектуре регламента: реестр узлов + процедура роутера, **без** каталога «проверенных цепочек», **без** 3-слойного механизма обновления цепочек, **без** forced-choice gate. Каждая задача — свежая сборка пути через роутер. Observer-наблюдатель (scope B, полный пакет с дня 1) пишет evidence в `docs/observer/episodes-YYYY-MM.jsonl` и не вмешивается. 4 механических контролёра (lefthook-jobs + один self-pruning counter) закрывают рецидивирующие проблемы без LLM-стоимости. Поведенческое правило «не использован ≠ проблема» — встроено в дизайн, перевешивает аналитический инстинкт «прорезать неиспользуемое».

## 1. Контекст и проблема

### 1.1. Триггер

SYSTEM-аудит «мозга» 18.05.2026 (snapshot `docs/discovery/2026-05-18-system-audit-brain.md`, режим SYSTEM скила discovery-interview, scope 125 узлов × 5 осей) выявил 5 приоритетов. **Rec1–Rec5 закрыты в commit-серии 18.05** (карта iter8 + ruflo isolation + routing-off-phase.md + PSR_v1 R15 + 12 канонических связок L1–L12). После закрытия — заказчик 19.05.2026 поднял **уровень глубже**: «зарегламентировать узлы и цепочки, выстроить их взаимодействие, так чтобы они реально работали и были максимально эффективны как при решении текущих задач, так и для будущих». Brainstorming-сессия (5+ итераций) пришла к финальному дизайну.

### 1.2. Класс проблемы, который закрываем

| Симптом | Проявление 2026-05 | Корневая причина |
|---|---|---|
| L1-паттерн «плагин включён в settings.json без формализации» | Повтор 3× в 8 дней: UPM/21st (10.05), Sentry/Redis (13.05), Anthropic dev-tooling (18.05) | Нет автоматического детектора расхождений settings.json ↔ Tooling Прил. Н |
| Version drift между 8 нормативными файлами | Tooling v2.11 collision 17.05 (две параллельные сессии заняли один версионный номер) | Нет cross-reference consistency checker |
| Спекулятивное регулирование вперёд использования | Сессия 19.05 — initial recommendation «прорезать неиспользуемое» отвергнута заказчиком | Capability-readiness — осознанная стратегия; регулирование должно её не противоречить |
| Отсутствие evidence-loop | Solo-аналитика и саморефлексия без записи трасс | Нет пассивного журнала «как реально решалась задача» |

### 1.3. Что НЕ является проблемой (зафиксировано в `feedback_brain_unused_tools_not_problem.md`)

Узел в реестре «мозга», который ни разу не использовался на реальной задаче, **не** считается проблемой. Capability-readiness — осознанная стратегия заказчика: иметь инструмент готовым ещё до возникновения потребности; будущие задачи непредсказуемы; оказаться без нужного инструмента в момент задачи дороже, чем держать неиспользуемый. **Это правило перевешивает аналитический инстинкт «прорезать неиспользуемое»** и встраивается в дизайн сигнального статуса (см. §5.4) и в текст ADR-011.

## 2. Цели и не-цели

### 2.1. Цели

1. **Один и только один источник истины маршрутизации** «задача → узел/узлы»: процедура роутера + статический реестр узлов с обязательными атрибутами.
2. **Capability-readiness сохранена** — каждый формализованный узел остаётся доступным, никаких автоматических «зомби»-пометок.
3. **Спекулятивная регламентация устранена структурно** — нет каталога «проверенных цепочек», который бы фиксировал маршруты до их фактического возникновения.
4. **Evidence-loop работает с дня 1** — observer пишет каждую сессию в JSONL + опциональные MD-заметки; `/brain-retro`-скил раз в спринт даёт агрегаты.
5. **4 рецидивирующих класса проблем закрыты механически** — lefthook-jobs + один self-pruning counter, 0 LLM-вызовов в hot path.
6. **Чёткая дисциплина обновления нормативки** — пока новые цепочки не появятся в evidence, никаких записей о них в реестре нет.

### 2.2. Не-цели (явно отвергнуто)

| Что НЕ делаем | Почему |
|---|---|
| Кэш «проверенных цепочек» (history-based: «эта цепочка проверена на задаче #1234, использовать впредь») | Спекулятивная регламентация — корневая причина churn'а нормативки. Removed in router-only refinement (turn 8 brainstorming). NB: канонические связки L1–L12 в `docs/routing-off-phase.md` — это рекомендации общего вида («узлы X+Y часто работают вместе»), не record-based кэш; этот спек их сохраняет и расширяет через `/brain-retro` см. §5.5 |
| 3-слойный механизм обновления цепочек (topology+context records / flag-on-intake / forced-choice gate) | Moot после router-only — нет каталога, нечего обновлять |
| Forced-choice gate (роутер обязан явно отказаться от каждого узла) | Same — нет каталога, граничные узлы оцениваются роутером ad-hoc по реестру |
| Стейлнес-контролёр (отдельный детектор устаревания цепочек) | Removed — после router-only его две оставшиеся функции (ADR-eval раз в полгода, memory drift) — разовые задачи для `audit-portal` или ручного прохода, отдельной инфраструктуры не требуют |
| Контролёр содержания решений (auto-judge выбранного узла) | Перевес аналитики над инстинктом заказчика; capability-readiness ⇒ не машинно-судить выбор |
| Per-step nanny (контроль каждого шага решения) | Дорого, мешает; observer уже даёт post-hoc evidence |
| Smart preflight conflict-detector (per-task semantic) | LLM-стоимость в hot path; конфликты ловятся lefthook'ом на коммите |
| Echo-chamber red-team (внутренний оппонент) | Дублирует существующий `superpowers:requesting-code-review` |
| Runtime-cost мониторинг | Off-scope; экономия-режим заказчика регулирует cost вне этой архитектуры |
| Decision-size классификатор | Subjective, нагрузка без ценности |
| Авто-апдейты нормативки observer-ом | Observer **только пишет**, не вмешивается; апдейты — ручное действие заказчика через `/brain-retro` |

## 3. Архитектурный обзор

```
┌──────────────────────────────────────────────────────────────────────────┐
│                              User task                                    │
└────────────────────────────────────┬─────────────────────────────────────┘
                                     │
                          ┌──────────▼──────────┐
                          │   ROUTER procedure  │  (см. §4)
                          │   — статический     │
                          │   реестр узлов      │
                          │   — правила выбора  │
                          │   — Pravila §12/§14/│
                          │     §15 hard-floor  │
                          └──────────┬──────────┘
                                     │ (выбор узла/узлов)
                                     ▼
                          ┌─────────────────────┐
                          │  Execution by Claude│
                          │   + skills/plugins  │
                          └──────────┬──────────┘
                                     │
                  ┌──────────────────┴──────────────────┐
                  │ Stop-hook (observer write only)     │
                  │ → docs/observer/episodes-YYYY-MM    │
                  │   .jsonl + optional notes/*.md      │
                  └──────────────────┬──────────────────┘
                                     │
                ┌────────────────────┴────────────────────┐
                │   /brain-retro skill (раз в спринт)     │
                │   агрегаты + кандидаты на корректировку │
                │   ← ручное решение заказчика            │
                └─────────────────────────────────────────┘

Параллельно (механические контролёры, см. §5):
  C1 L1-watcher        — lefthook job + weekly cron
  C2 Cross-ref consist — lefthook job
  C3 Observer-of-obs   — lefthook job + 54-week self-prune
  C4 Сигнальный статус — ежедневно обновляемая STATUS.md
```

## 4. Роутер — только реестр + процедура (без кэша цепочек)

### 4.1. Реестр узлов (Single Source of Truth)

**Канон**: [Tooling Прил. Н](../../Tooling_v8_3.md) §4.X + §0 (счётчики). Реестр уже существует; этот дизайн **не вводит новый реестр**, а формализует обязательные атрибуты записи и процедуру выбора.

**Обязательные атрибуты узла** (для каждой строки #1–#60 в Tooling Прил. Н):

| Атрибут | Описание | Пример |
|---|---|---|
| `id` | Уникальный номер #1–#60+ | `#55` |
| `name` | Каноническое имя | `discovery-interview` |
| `kind` | Тип: `plugin` / `skill` / `mcp` / `hook` / `vendored-skill` / `composer-dep` / `npm-dep` / `agent` | `skill (project)` |
| `phase` | `0` / `1` / `2` / `3` / `off-phase` | `off-phase` |
| `subcategory` | Off-phase подкатегория (если applicable) | `discovery-tooling` |
| `triggers` | Условные слова/задачи, по которым роутер выбирает узел | `«интервью», «discovery», «JTBD», «ориентация по системе»` |
| `boundaries` | Границы с соседями + ADR-cross-ref | `ADR-009 vs process-analysis #53` |
| `dormant` | Boolean — узел отключён, артефакты сохранены | `false` (для ruflo — `true` per Pravila §14.9) |
| `last-touched` | Дата последней правки записи в Tooling | `2026-05-18` |

**Граница**: эти атрибуты — формализуемая структура существующего реестра. Никакого `last-used-on-real-task` атрибута в реестре **нет** (см. §2.2 не-цель «контролёр содержания решений» + §6 поведенческое правило).

### 4.2. Процедура роутера

Каждая задача — **свежая сборка** через следующие шаги (роутер — это процедура, исполняемая Claude'ом при чтении промпта; никакого отдельного daemon-а нет):

```
1. ПРОВЕРКА HARD-FLOOR (Pravila §12 / §14 / §15)
   - Содержит ли промпт queen/королева? → Pravila §14 (dormant сейчас per §14.9)
   - Задача из карты §12.2? → Skill инвокируется ПЕРВЫМ (hard-rule)
   - Будет ли правка нормативки из 8-list? → §15.2 pre-flight sync обязателен
   - Параллельные сессии с git/субагенты? → §15.1 Sonnet/Opus only

2. КЛАССИФИКАЦИЯ ЗАДАЧИ
   - Phase-active (0/1/2/3) или off-phase?
   - Тип: TDD / debug / brainstorm / writing-plan / verification / discovery /
     migration / commit / review / UI-feature / arch-decision / refactor / ...

3. ВЫБОР УЗЛА(ОВ) ПО ТРИГГЕРАМ
   - Прогон по реестру (Tooling §4.X + routing-off-phase.md для off-phase)
   - Если ≥2 узла подходят — применить ADR-границы (boundaries атрибут)
   - Если конфликт остаётся — применить PSR_v1 R15.3 (приоритет специфичности)

4. ПРОВЕРКА КАНОНИЧЕСКИХ СВЯЗОК (если применимо)
   - Если паттерн совпадает с L1–L12 в docs/routing-off-phase.md §4 →
     вызвать связку
   - Если нет — комбинация ad-hoc; observer запишет (см. §5)

5. ИСПОЛНЕНИЕ
   - Skill инвокирован (если §12), или узел применён по триггеру
   - Граничные случаи документируются в комментариях или в observer-логе
```

**Принципиально**: шаги 3–4 **не консультируются** с каким-либо кэшем «эта цепочка проверена / эта не проверена». Каждый раз — свежий проход по реестру + ADR-границам.

### 4.3. Что роутер делает с «не использованными» узлами

**Ничего особенного.** Узел оценивается по триггерам и границам так же, как любой другой. Если задача подходит под триггер #50 Jupyter MCP (DEFERRED), но узел `dormant=true` или `phase=DEFERRED` — роутер сообщает: «узел подходит, но в текущем окружении не активирован; задача DEFER до выполнения предусловия».

Это **не** «зомби-флаг» — это просто корректная отчётность о состоянии возможности.

### 4.4. Дельта vs текущее состояние

Сейчас процедура роутера **не задокументирована явно** — она существует имплицитно в Pravila §12/§14/§15 + PSR_v1 R0–R15 + Tooling §3 + routing-off-phase.md. Дельта дизайна:

- **Новый файл**: `docs/router-procedure.md` v1.0 — фиксирует процедуру §4.2 в одном месте.
- **Tooling Прил. Н**: каждая строка #1–#60+ дополнена 9 атрибутами §4.1 (где их нет). Это **большая нормативная правка**; будет планироваться в writing-plans phase.
- **PSR_v1 R15** уже содержит routing-таблицу для off-phase — extends, not replaces.

## 5. Observer scope B — пакет с дня 1

### 5.1. Граница

Observer **только пишет evidence, не вмешивается**. Никаких автоматических апдейтов нормативки. Никаких блокировок Stop-events. Никаких алертов в hot path — только append в JSONL + опциональная MD-заметка.

### 5.2. Stop-hook

**Триггер**: end-of-session (Claude Code Stop-event hook, точка регистрации — `~/.claude/settings.json` или `.claude/settings.json` проекта).

**Action**: append одной JSONL-строки в `docs/observer/episodes-YYYY-MM.jsonl` (rotation помесячно — простое именование, никакой инфраструктуры).

**5 обязательных полей** (v1.1 — factor analysis amendment 2026-05-19):

| Поле | Тип | Описание |
|---|---|---|
| `task_id` | string | Уникальный ID сессии (UUID или git-friendly slug) |
| `timestamps` | `{started_at, ended_at}` ISO-8601 | Начало и конец сессии (для time-burn анализа) |
| `path_type` | enum: `regulated` / `improvised` / `alternative` / `mixed` | Пошёл ли роутер по канонической связке L1–L12, импровизировал, ушёл альтернативой или смешанно |
| `outcome` | enum: `success` / `partial` / `failure` / `aborted` | Итог сессии |
| `primary_rationale` | structured object (см. §5.2.1) | **Главное решение роутера на эпизод** — структурированные факторы выбора первичного узла. Дублирует первое `routing_decision` событие в `events[]` для быстрых агрегатов без чтения массива. |

**Структурированные события** (опционально, массив `events[]`):

| Тип | Описание |
|---|---|
| `routing_decision` | **Структурированный факт выбора узла** — 7 полей (см. §5.2.1). Записывается один раз на каждое решение роутера в сессии (если цепочка из N узлов — N событий с возрастающим `step`). Это основа факторного анализа. |
| `hook_fired` | Сработал хук (skill-marker, skill-check, state-guard, postcompact, verifier, economy-mode, security-guidance, ruflo-* — текущая 6+ компонентная архитектура) |
| `chain_divergence` | Роутер пошёл не по канонической связке, хотя совпадение триггеров было. Поля: `expected_chain` (L1–L12 ID), `chosen_nodes[]`, `reason_summary`. Дополняет (не подменяет) `routing_decision` на этом же шаге. |
| `skill_invoked` | Инвокирован skill — поля `skill_id` + `reason` (free-text). Для факторного анализа выбора skill'а — используется отдельный `routing_decision` события с тем же `step`. |
| `error` | Возникла ошибка — записать `class` (например `quirk:72`) + `recovery_action` |
| `confusion_marker` | Заказчик/Claude пометил место как «запутано» (вручную через TODO-метку в промпте) |
| `time_burn` | Большой блок времени потрачен на одну операцию (порог: >5 минут на single tool-call) |

#### §5.2.1. Структура `routing_decision` и `primary_rationale`

Оба объекта используют **одинаковую схему 7 полей** — `primary_rationale` это **копия первого `routing_decision`** в эпизоде, поднятая на уровень эпизода для дешёвой агрегации.

| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| `step` | int | yes (для events) / нет в primary_rationale | Номер решения в эпизоде (1, 2, 3 ...). Для primary_rationale — всегда 1. |
| `node_chosen` | string (`#NN` или `<name>`) | yes | Выбранный узел из Tooling Прил. Н §4.X. |
| `triggers_matched` | array of string | yes | Список триггеров из реестра, которые сработали (например `["discovery", "интервью", "JTBD"]`). Empty `[]` допустим если решение принято исключительно по hard-floor. |
| `candidates_considered` | array of `{node_id, dropped_because}` | yes | Узлы, которые роутер рассмотрел и отбросил. Каждый элемент содержит ID отброшенного узла и **строку причины** (ADR-ref / specificity / hard-floor / manual). Empty `[]` если альтернатив не было. |
| `boundaries_applied` | array of string | yes | ADR-ссылки или PSR_v1 R-ссылки, применённые для разруливания (например `["ADR-009", "PSR_v1 R15.3"]`). Empty `[]` если границ не применялось. |
| `hard_floor` | `{invoked: bool, rules: string[]}` | yes | Информация о hard-floor §12/§14/§15. Если применилось — `invoked: true` и в `rules` перечислены сработавшие правила (например `["Pravila §12"]`). |
| `task_classification` | string | yes | Категория задачи на момент решения (`discovery` / `brainstorm` / `writing-plan` / `TDD` / `debug` / `arch-decision` / `refactor` / `docs` / `sync` / `migration` / `commit` / `review` / `other`). |

**Пример** (запись эпизода с цепочкой из 2 узлов):

```json
{
  "task_id": "2026-05-19-brain-governance-plan",
  "timestamps": {"started_at": "2026-05-19T04:00:00+03:00", "ended_at": "2026-05-19T04:35:00+03:00"},
  "path_type": "regulated",
  "outcome": "success",
  "primary_rationale": {
    "step": 1,
    "node_chosen": "superpowers:brainstorming",
    "triggers_matched": ["brainstorm", "design"],
    "candidates_considered": [
      {"node_id": "superpowers:writing-plans", "dropped_because": "specificity: brainstorm предшествует writing-plans"}
    ],
    "boundaries_applied": ["PSR_v1 R15.3"],
    "hard_floor": {"invoked": true, "rules": ["Pravila §12"]},
    "task_classification": "brainstorm"
  },
  "events": [
    {"kind": "routing_decision", "step": 1, "node_chosen": "superpowers:brainstorming", "triggers_matched": ["brainstorm", "design"], "candidates_considered": [...], "boundaries_applied": ["PSR_v1 R15.3"], "hard_floor": {"invoked": true, "rules": ["Pravila §12"]}, "task_classification": "brainstorm"},
    {"kind": "routing_decision", "step": 2, "node_chosen": "superpowers:writing-plans", "triggers_matched": ["writing-plans"], "candidates_considered": [], "boundaries_applied": [], "hard_floor": {"invoked": true, "rules": ["Pravila §12"]}, "task_classification": "writing-plan"},
    {"kind": "skill_invoked", "skill_id": "superpowers:writing-plans", "reason": "terminal skill brainstorming-flow"}
  ]
}
```

**Граница**: `primary_rationale` НЕ дублирует все шаги цепочки — только **первое** решение. Полная цепочка читается через `events[].kind=="routing_decision"`. Это даёт два уровня агрегации:

1. **Дешёвая верхнеуровневая** (читай только `primary_rationale` каждого эпизода): «какой узел чаще всего открывает сессию», «какие факторы доминируют в первом решении».
2. **Глубокая факторная** (читай все `routing_decision` событий): «какие пары факторов чаще всего разруливают конкретные конфликты», «какие ADR-границы выходят на первый план».

### 5.3. Опциональные MD-заметки

**Путь**: `docs/observer/notes/YYYY-MM-DD-<slug>.md`. Создаются **только если у сессии есть качественная история, которая не помещается в JSONL**: длинный narrative разбора, скриншот ошибки, цепочка из 5+ узлов с границами и т.д.

Никакого автогенерата — заметка создаётся вручную (Claude или заказчиком) по итогам сессии, если она того стоит. Большинство сессий — только JSONL, без MD.

### 5.4. ПДн-фильтр

**Обязательный pre-write через gitleaks** (или его аналог — простая regex-фильтрация телефонов/email/токенов перед записью в JSONL).

| Pattern | Replacement |
|---|---|
| `\+7\d{10}` | `+7XXXXXXXXXX` |
| `[\w.-]+@[\w.-]+` | `***@***` |
| API-токены (gitleaks ruleset) | `[REDACTED:<rule>]` |

Реализация — встроена в Stop-hook script (одна regex-passes pass перед write).

### 5.5. `/brain-retro` скил

**Периодичность**: раз в спринт (вручную, по команде заказчика «брейн-ретро» или эквивалент).

**Action**:

1. Читает все `episodes-YYYY-MM.jsonl` за последний период (с момента предыдущего ретро).
2. Агрегирует:
   - Распределение `path_type` (% regulated / improvised / alternative / mixed).
   - Топ-узлы (использованные ≥ N раз).
   - Топ-связки L1–L12 (использованы) + новые связки (path_type=improvised, повторившиеся ≥2 раз).
   - Top `error` classes + recovery-патерны.
   - `chain_divergence` cases — где роутер ушёл с канонической связки.
   - **Факторная матрица** (v1.1+ amendment): по каждому узле в `routing_decision` событиях — частоты по 5 осям факторов:
     - `triggers_matched` → какие триггеры чаще всего ведут к этому узлу
     - `candidates_considered.dropped_because` → какие альтернативы чаще всего отбрасываются и по какой причине
     - `boundaries_applied` → какие ADR-границы / R-rules чаще всего разруливают
     - `hard_floor.rules` → как часто узел вынуждается hard-floor §12/§14/§15
     - `task_classification` → в каких классах задач узел доминирует
     Output — таблица «узел × фактор × частота» + cross-tab «фактор × фактор» для каждой пары факторов (например «ADR-009 ↔ triggers_matched=['discovery']» — 8 раз).
3. Возвращает **кандидатов на корректировку нормативки**:
   - Новая связка L13+ (если improvised повторился ≥2 раз с success).
   - Граница X ↔ Y нуждается в ADR-уточнении (если chain_divergence повторился).
   - Новый ADR (если confusion_marker повторился).
4. **Заказчик решает вручную** — никаких автоматических правок Tooling/Pravila/PSR_v1.

**Граница**: `/brain-retro` — **читатель** observer-логов. Не пишет в логи. Не правит нормативку. Только агрегирует и предлагает.

## 6. 4 контролёра первой волны

Все 4 — **механические**, без LLM-вызовов в hot path. 0 расход $ per execution. 3 из 4 — lefthook pre-commit jobs (на коммите); 1 — self-pruning counter (на каждое чтение observer-файлов).

### 6.1. C1 — L1-watcher (детектор неформализованных плагинов)

**Что закрывает**: трижды повторившийся L1-паттерн — UPM/21st 10.05 + Sentry/Redis 13.05 + Anthropic dev-tooling 18.05. «Плагин включён в settings.json user-level или project-level без формализации в Tooling Прил. Н».

**Реализация**:

- **Lefthook job** `l1-watcher-on-settings-change` — триггер: правка `~/.claude/settings.json` или `.claude/settings.json` (детект — diff содержит изменения в `enabledPlugins[]`).
- **Action**: diff'нуть `enabledPlugins` ↔ список имён в Tooling Прил. Н §4.X (regex `^#\d+\s+([\w-]+)` + список плагинов в `.mcp.json` `mcpServers` keys). Если плагин в settings.json есть, но в Tooling нет — **fail commit** с сообщением «Plugin `<name>` enabled in settings.json but not formalized in Tooling Прил. Н. Run `/claude-md-management:claude-md-improver` to formalize.».
- **Weekly cron** (если у заказчика нет частых правок settings.json): GitHub Actions schedule `0 9 * * 1` (понедельник 9:00 МСК) — тот же diff в read-only режиме, отчёт в `docs/observer/notes/YYYY-MM-DD-l1-watcher-weekly.md`.

**0 LLM-вызовов**, 0 расход $. Regex + diff.

### 6.2. C2 — Cross-ref consistency (детектор version drift)

**Что закрывает**: version drift между 8 нормативными файлами (Tooling v2.11 collision 17.05). Когда CLAUDE.md `§0 cross-refs row` пишет «Pravila v1.29», а фактическая шапка Pravila — v1.30, или Tooling v2.15 vs фактическая v2.16, или PSR_v1 v3.14 vs v3.15.

**Реализация**:

- **Lefthook job** `cross-ref-consistency` — триггер: любая правка одного из 8 нормативных файлов (Pravila / CLAUDE.md / Tooling / PSR_v1 / MEMORY.md / Открытые_вопросы / docs/adr/* / db/schema.sql).
- **Action**: regex-extract версий из шапок каждого файла; regex-extract упоминаний версий в `§0 cross-refs` других файлов. Сравнить попарно. Если расхождение — **fail commit** с сообщением `Version drift detected: <file-A> §0 references <file-B> v<X>, but <file-B> header is v<Y>. Update §0 cross-refs.`.
- **Стиль реализации**: `adr-judge`-like — pure regex, 0 LLM-вызовов. Возможна реализация на bash + grep + sed; либо короткий node-скрипт.

**0 LLM-вызовов**, 0 расход $. Detects ровно тот класс инцидентов, который уже произошёл и заказчик не хочет повторять.

### 6.3. C3 — Observer-of-observer (счётчик чтений + 54-недельный self-prune)

**Что закрывает**: риск, что observer-инфраструктура (Stop-hook + JSONL + MD notes) сама уйдёт в no-op, если никто никогда не читает evidence. Если 54 недели подряд никто не открывал ни один `episodes-YYYY-MM.jsonl` и не вызывал `/brain-retro` — это сигнал, что observer стал ритуалом, а не инструментом.

**Реализация**:

- **Счётчик**: `docs/observer/.read-counter.json` — простой JSON `{"last_read_at": "ISO-8601", "read_count_last_period": N}`.
- **Hook на чтение**: lefthook job `observer-of-observer` слушает Read-tool calls на путях `docs/observer/episodes-*.jsonl` или `docs/observer/notes/*.md` — обновляет `last_read_at` на now.
- **Self-prune trigger**: lefthook pre-commit job проверяет: `now - last_read_at > 54 weeks` → **warn** (не fail) на коммите с сообщением «Observer infrastructure not read for >54 weeks. Consider self-pruning: archive `docs/observer/` to memory, remove Stop-hook, simplify governance.».

**Почему 54 недели (≈1 год)**:

- Заказчик 19.05.2026 явно поднял 4 недели → 54 недели. Аргумент: redco-данные observer-а должны иметь время накопить ценность для **редких** ретроспектив (раз в полгода-год — это нормальный ритм для меньших проектов).
- Уход в no-op за месяц тишины — нерелевантный сигнал (нормальный отпуск/спринт-без-ретро); за год тишины — это уже системный сигнал.

**Самоочистка** означает: контролёр сам предлагает себя удалить, если evidence-loop не используется. Это **anti-зомби-инфраструктура** механизм.

**0 LLM-вызовов**, 0 расход $. JSON read/write + date math.

### 6.4. C4 — Сигнальный статус (`docs/observer/STATUS.md`)

**Что закрывает**: отсутствие единого дашборда — сейчас сигнал размазан по lefthook-выходам, observer-логам, нормативке. Заказчик хочет приборную панель.

**Реализация**:

- **Файл**: `docs/observer/STATUS.md` — ежедневно (или per-commit) обновляемая markdown-табличка.
- **Содержание**: агрегирует сигнал из C1 + C2 + C3 + observer-логов.

Пример структуры:

```markdown
# Brain Status (auto-generated)

Last updated: 2026-05-19T10:00:00+03:00

| Контролёр | Состояние | Детали |
|---|---|---|
| C1 L1-watcher | ✅ | settings.json ↔ Tooling: 0 drift. Last weekly cron: 2026-05-18 (PASS) |
| C2 Cross-ref consistency | ✅ | 8 normative files: 0 version drift |
| C3 Observer-of-observer | ⚠️ | Last read: 2026-05-19 (today). Counter: 1 read this week. Self-prune: 53w remaining |
| C4 Сигнальный статус | ✅ | This file (self-reference) |
| Observer evidence | ✅ | 47 episodes this month, 0 PII matches, 0 write failures |

## Метрики (информационные, не алерты)

- Узлы, использованные за последние 30 дней: 18 / 60 (30%)
- Узлы, ни разу не использованные на реальной задаче: 32 / 60 — **это не проблема** (capability-readiness, см. [feedback](../../memory/feedback_brain_unused_tools_not_problem.md))
- Канонические связки L1–L12 за месяц: L3 — 12 раз, L7 — 8 раз, L1 — 5 раз, ...
- Improvised chains за месяц: 3 (кандидаты для `/brain-retro`)

## Алерт-индикаторы

✅ — норма
⚠️ — внимание (не блокирует)
🔴 — действие требуется
```

**Критически**: метрика «N раз использован» — **информационная**, не алерт. Никаких ✅/⚠️/🔴 на основе usage-count (per `feedback_brain_unused_tools_not_problem.md` §3 «как применять»).

**Генерация**: lefthook post-commit hook или daily cron — собирает из C1+C2+C3+observer-логов, пишет STATUS.md. Pure shell/regex/jq.

**0 LLM-вызовов**, 0 расход $.

## 7. Поведенческое правило: «не использован ≠ проблема»

**Уже зафиксировано** в `memory/feedback_brain_unused_tools_not_problem.md`. В этом spec — встраивание в дизайн:

1. **Реестр узлов (§4.1)** — не содержит `last-used-on-real-task` атрибута.
2. **Сигнальный статус (§6.4)** — N-раз-использован показывается как информация, не алерт.
3. **`/brain-retro` (§5.5)** — не выдаёт «кандидатов на удаление по причине неиспользования».
4. **ADR-011** — будет содержать явный bullet «Capability-readiness is intentional; unused ≠ candidate for removal».

**Исключения** (явно прописаны в feedback-памяти):

- **deprecated upstream-пакеты или физически сломанные инструменты** — это «не работает», не «не использован»; флажить можно и нужно (отдельная категория, lefthook-job `npm audit` + `composer outdated` уже это делают).
- **Правило относится к узлам мозга** (плагины Claude Code, скилы, MCP-серверы, контролёры). Для **продуктового кода Лидерры** dead Vue-компонент / неиспользуемый Laravel-сервис / dead route — там dead code = долг (knip + Larastan + lefthook уже это ловят).

## 8. Граничные случаи и интеграционные риски

### 8.1. HK1 pre-check (Pravila ADR-010)

Дизайн **вводит новый Stop-hook** для observer-а (§5.2). **Обязателен HK1 pre-check** перед его регистрацией:

- Прочитать `~/.claude/settings.json` `hooks.Stop[]` (если уже есть).
- Проверить коллизию с 6-компонентной economy/skill-discipline хук-архитектурой (skill-marker / skill-check / state-guard / postcompact / verifier / economy-mode).
- Если Stop-event уже занят — реализовать как **append-only chain**, не overwrite. Реализация — либо одной точкой входа, которая внутренне зовёт все Stop-handlers (skill-marker hook уже это делает), либо отдельный slot с явным `name` (Claude Code 2.x поддерживает массив hooks per event).

Это **обязательное условие** успешной реализации; нарушение → blocks Pravila ADR-010 hard-rule.

### 8.2. Pravila §15.2 pre-flight sync

Большинство правок этого дизайна затронут **8 нормативных файлов**:

- `docs/Tooling_v8_3.md` (Прил. Н §4.X — добавление 9 атрибутов на 60+ строк, новая запись router-procedure)
- `docs/Pravila_raboty_Claude_v1_1.md` (§13.X или §16 — добавление параграфа про observer и контролёры)
- `docs/Plugin_stack_rules_v1.md` (R15 или новый R16 — обновление routing apparatus)
- `CLAUDE.md` (§3.6 или §3.7 — cross-ref на новый router-procedure.md)
- `docs/adr/ADR-011-brain-governance.md` (новый)
- Возможно `docs/Открытые_вопросы_v8_3.md` (если возникнут открытые вопросы по реализации)
- `MEMORY.md` (project-memory указатели обновятся автоматически)
- `db/schema.sql` — **не затронут** (это не БД-задача).

**Каждая правка обязана начинаться с `git fetch origin && git log HEAD..origin/main --oneline` per §15.2.**

### 8.3. Worktree-constraint для CLAUDE.md

Если реализация в изолированном worktree (рекомендуется для атомарности) — **CLAUDE.md правится прямым Edit** (worktree-эксцепшн §5 п.10; `claude-md-management` плагин не наводится на worktree-копию CLAUDE.md; прецеденты: A11/C10/discovery v2.10–v2.13).

### 8.4. ruflo dormant — взаимодействие с дизайном

Дизайн **полностью совместим** с ruflo-dormant статусом (§14.9 Pravila). Router-only архитектура не зависит от ruflo daemon; observer Stop-hook независим от ruflo PreToolUse-хуков. ruflo может быть реактивирован позже без правки этого дизайна — он встанет одним из узлов реестра §4.1 с `dormant=true → false`.

### 8.5. Параллельные сессии (Pravila §15)

Контролёр C2 (cross-ref consistency) **closes** второй класс инцидентов параллельных сессий — version drift. Первый класс (субагент-угон-ветки) уже закрыт `tools/subagent-prompt-prefix.mjs` + git-safety-checklist в `subagent-driven-development` wrapper. **Этот дизайн дополняет**, не подменяет §15.

### 8.6. Размер observer-логов

**Риск**: `episodes-YYYY-MM.jsonl` растёт без bound. **Митигатор**: помесячное rotation именования (новый файл каждый месяц); один файл ≈ 30–100 сессий ≈ 50–200KB JSON; за год ≈ 12 файлов ≈ <3MB. **Архив**: после 12 месяцев — `docs/observer/archive/episodes-YYYY.tar.gz`; ручная задача.

### 8.7. ПДн в observer-логах

**Митигатор**: gitleaks-like pre-write filter (§5.4). **Дополнительная защита**: каталог `docs/observer/` под git с `lefthook pre-push` job — gitleaks full-history scan (уже в pre-push для всего репо).

### 8.8. Что если контролёр сам сломается

- **C1** failure → lefthook fails commit (видимый сигнал; не молчит).
- **C2** failure → same.
- **C3** failure → STATUS.md показывает 🔴; lefthook warn (не блокирует).
- **C4** failure → STATUS.md устаревает; видно через C3 (если STATUS.md не обновлялся — это «evidence not consumed», self-prune watchdog поймает через 54 недели).

«Кто наблюдает за наблюдателями» закрыт C3.

## 9. План имплементации (high-level — для следующей фазы writing-plans)

**Этот spec НЕ имплементационный план.** Writing-plans skill после approval создаст детальный план. High-level ожидаемая раскладка:

| Этап | Артефакты | Размер |
|---|---|---|
| 1. ADR-011 + router-procedure.md | 2 новых документа | ~300 строк |
| 2. Tooling Прил. Н — 9 атрибутов на 60 строк | Большая правка | ~600 строк изменений |
| 3. Pravila §16 (или §15.4 sub-section) | Параграф об observer + контролёрах | ~150 строк |
| 4. PSR_v1 R16 (или R15 extension) | Routing apparatus update | ~100 строк |
| 5. `docs/observer/` инфраструктура | README + .read-counter.json seed + STATUS.md template + Stop-hook script + ПДн-filter | ~5 файлов, ~400 строк |
| 6. 4 lefthook-jobs | YAML + 4 shell/node scripts | ~150 строк |
| 7. `/brain-retro` skill | `.claude/skills/brain-retro/SKILL.md` + reader script | ~200 строк |
| 8. HK1 pre-check pass | Manual + dry-run hook collision check | — |
| 9. Smoke test + verification | Запустить sample task, проверить write в JSONL, проверить C1–C4 trigger | — |
| 10. CLAUDE.md sync + 8-file pre-flight sync | Через `/claude-md-management:claude-md-improver` (или прямой Edit в worktree) | — |

**Все правки** обязаны проходить через Pravila §15.2 pre-flight sync.

## 10. Verification критерии (для verification-before-completion skill)

После имплементации, перед claim «brain governance done»:

1. ✅ `docs/router-procedure.md` v1.0 существует и описывает процедуру §4.2 буквально.
2. ✅ Tooling Прил. Н §4.X — каждая строка #1–#60+ содержит 9 атрибутов §4.1 (sample-check: 5 случайных строк).
3. ✅ `docs/observer/` существует; Stop-hook зарегистрирован; smoke test — фейк-сессия завершается записью в `episodes-YYYY-MM.jsonl`; запись содержит 4 обязательных поля; ПДн-фильтр срабатывает на тестовой строке `+79991234567`.
4. ✅ C1 — lefthook fail на тест-коммите, где settings.json содержит несуществующий в Tooling плагин; pass на чистом коммите.
5. ✅ C2 — lefthook fail на тест-коммите с deliberate version drift; pass на чистом.
6. ✅ C3 — `.read-counter.json` существует; обновляется на Read-tool call; lefthook warn срабатывает если timestamp подделан на «56 недель назад».
7. ✅ C4 — `docs/observer/STATUS.md` существует, обновляется на post-commit, содержит все 4 контролёра + информационные метрики.
8. ✅ `/brain-retro` skill инвокируется (минимум `Skill` tool принимает имя); smoke — на пустом `episodes-*.jsonl` возвращает «no data yet, expected after first sessions».
9. ✅ ADR-011 written, status `Accepted`.
10. ✅ 8-file pre-flight sync прошёл перед каждой правкой нормативки (verified в git log).
11. ✅ HK1 pre-check выполнен; Stop-hook не overwrites 6-компонентную архитектуру.
12. ✅ Поведенческое правило `feedback_brain_unused_tools_not_problem.md` упомянуто в ADR-011, STATUS.md, `/brain-retro` (для самих будущих сессий).
13. ✅ Regression: Pest, Vitest, Larastan, lefthook full-stage — 0 регрессий относительно baseline на ветке начала работ.

## 11. Открытые вопросы (для уточнения в writing-plans / реализации)

| # | Вопрос | Default / предположение |
|---|---|---|
| O1 | Stop-hook реализуется как python-script или node-script? | Node (consistency с другими hooks в `tools/`) |
| O2 | ПДн-фильтр — встроить gitleaks-call или regex inline? | Regex inline (быстрее, gitleaks остаётся для git-history) |
| O3 | `/brain-retro` инвокируется заказчиком вручную или есть auto-trigger «N сессий накопилось»? | Вручную (явный контроль заказчика) |
| O4 | C1 watcher cron — GitHub Actions или local Windows Task Scheduler? | GitHub Actions (отчёт виден всем, не зависит от состояния Windows-машины) |
| O5 | STATUS.md обновляется per-commit или daily cron? | Per-commit (свежее данные, lefthook post-commit hook) |
| O6 | Где жить router-procedure.md — в `docs/` корне или в `docs/governance/`? | `docs/router-procedure.md` (плоско, в корне — как routing-off-phase.md) |
| O7 | ADR-011 или ADR-012? | Следующий свободный (на 2026-05-19 — ADR-011, проверить ls docs/adr/) |

## 12. Cross-refs

- `docs/discovery/2026-05-18-system-audit-brain.md` — origin trigger (SYSTEM-аудит).
- `memory/project_brain_governance_design.md` — короткая memory-сводка дизайна.
- `memory/feedback_brain_unused_tools_not_problem.md` — поведенческое правило (встроено).
- `docs/Pravila_raboty_Claude_v1_1.md` §12 / §14 / §15 — hard-floor для роутера §4.2 шаг 1.
- `docs/Plugin_stack_rules_v1.md` R15 — off-phase routing, extends not replaces.
- `docs/Tooling_v8_3.md` Прил. Н §0 + §4.X — реестр узлов SoT.
- `docs/routing-off-phase.md` v1.0+ — routing-таблица off-phase + L1–L12 связки.
- `docs/adr/ADR-010-anthropic-dev-tooling.md` — HK1 hard-rule pre-check.
- `docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md` — §15 hard-rule context.

---

**Status after this spec**: awaiting written-spec user review (brainstorming flow step 8). После approval → transition to `superpowers:writing-plans` (terminal skill brainstorming-а). Никакая имплементация **не начнётся** до approval и не до плана.
