docs: brain-plugin дизайн v6 + план Фазы 1 + handoff сессии

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-15 09:51:17 +03:00
parent 80aa729404
commit 3a422a00c3
3 changed files with 659 additions and 0 deletions
@@ -0,0 +1,372 @@
# Brain Plugin — Фаза 1: Config Seam — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: superpowers:executing-plans (инлайн под стеной — субагенты стена запрещает, VA-4). Steps — checkbox (`- [ ]`).
**Goal:** Вынести каждое жёсткое «знание про Лидерру» из движка в единый файл-настройку `.claude/brain.local.md`, с безопасными дефолтами (fail-safe §5.1 спека), не меняя текущее поведение в `claude-brain` (обратная совместимость — дефолт = нынешнее лидерровское значение).
**Architecture:** Новый чистый модуль `tools/brain-config.mjs` читает `.claude/brain.local.md` (YAML-frontmatter) и отдаёт типизированные значения с fail-safe-направлениями. Каждый config-seam файл (§3.3 спека) меняется минимально: захардкоженная константа → параметр со значением по умолчанию из `brain-config`. Поведение `claude-brain` не меняется (дефолты = текущие пути/списки). TDD на каждый ключ + на каждое fail-safe-направление.
**Tech Stack:** Node.js ESM (`.mjs`, стиль `tools/`), vitest (`tools/`-свод), YAML-парсинг (минимальный — frontmatter `key: value` + списки).
**Спек:** `docs/superpowers/specs/2026-06-15-brain-as-plugin-design-v5.md` (канон) — §3.3 config-seam, §5 ключи, §5.1 fail-safe, §6 группы.
**Предусловие исполнения под стеной:** этот план перед инлайн-исполнением должен быть (1) опломбирован (`freeze-gate`) с блоком ` ```steps-json``` ` (op/object/ref), опирающимся на (2) опечатанный артефакт-спек. Сами шаги ниже — file-op (`Write`/`Edit`/`Bash`), `Task` запрещён (VA-4). Пломбировка — owner-involved шаг до Этапа 1.
---
## File Structure
- Create: `tools/brain-config.mjs` — чтение/валидация настройки + fail-safe дефолты. Одна ответственность.
- Create: `tools/brain-config.test.mjs` — TDD загрузчика + всех fail-safe-направлений.
- Create: `.claude/brain.local.md` — настройка `claude-brain` как консьюмера (дефолты = текущие лидерровские значения, чтобы поведение не изменилось).
- Modify (по одному, минимально): config-seam файлы §3.3 — `cross-ref-checker.mjs`, `enforce-normative-content-rules.mjs`, `l1-watcher.mjs`, `shell-content-rules.mjs`, `registry-load.mjs` (и потребители), `observer-stop-hook.mjs`/`status-md-generator.mjs`/`cost-stop-hook.mjs` (state_dir), `mcp-tool-classifier.mjs`, `commit-message-scanner.mjs`, `router-classifier.mjs`, `brain-retro-opus-reviewer.mjs`.
---
## Task 1: Config loader `brain-config.mjs`
**Files:** Create `tools/brain-config.mjs`, `tools/brain-config.test.mjs`
- [ ] **Step 1: Failing test — парсинг frontmatter + дефолты**
```javascript
import { describe, it, expect } from 'vitest';
import { parseBrainConfig, resolveConfig } from './brain-config.mjs';
describe('parseBrainConfig', () => {
it('читает YAML-frontmatter ключи', () => {
const md = '---\nconfig_version: 1\nregistry_path: docs/registry/nodes.yaml\nnormative_files:\n - docs/Pravila_raboty_Claude_v1_1.md\n---\nтело';
const c = parseBrainConfig(md);
expect(c.config_version).toBe(1);
expect(c.registry_path).toBe('docs/registry/nodes.yaml');
expect(c.normative_files).toEqual(['docs/Pravila_raboty_Claude_v1_1.md']);
});
it('нет файла/пусто → пустой объект (дефолты применит resolveConfig)', () => {
expect(parseBrainConfig('')).toEqual({});
expect(parseBrainConfig(null)).toEqual({});
});
});
```
- [ ] **Step 2: Run — verify FAIL**
Run: `npx vitest run --root . tools/brain-config.test.mjs`
Expected: FAIL «parseBrainConfig is not a function».
- [ ] **Step 3: Implement `brain-config.mjs`**
```javascript
#!/usr/bin/env node
/** brain-config — единый источник проектной настройки мозга (.claude/brain.local.md).
* Чистый парсер + resolveConfig с fail-safe дефолтами (спек §5.1). */
import fsDefault from 'node:fs';
const FM_RE = /^---\n([\s\S]*?)\n---/;
/** Минимальный YAML-frontmatter: `key: value` + список ` - item`. Без зависимостей. */
export function parseBrainConfig(md) {
const m = FM_RE.exec(String(md || ''));
if (!m) return {};
const out = {}; let curKey = null;
for (const line of m[1].split('\n')) {
const item = /^\s+-\s+(.*)$/.exec(line);
if (item && curKey) { (out[curKey] ||= []).push(item[1].trim()); continue; }
const kv = /^([A-Za-z_]+):\s*(.*)$/.exec(line);
if (!kv) continue;
const [, k, v] = kv;
if (v === '') { out[k] = []; curKey = k; }
else { out[k] = /^\d+$/.test(v) ? Number(v) : v; curKey = null; }
}
return out;
}
```
- [ ] **Step 4: Run — verify PASS**
Run: `npx vitest run --root . tools/brain-config.test.mjs`
Expected: PASS (оба теста parseBrainConfig).
- [ ] **Step 5: Commit**
```bash
git add tools/brain-config.mjs tools/brain-config.test.mjs
git commit -m "feat(brain-config): чистый парсер brain.local.md (Фаза 1 Задача 1)"
```
---
## Task 2: `resolveConfig` + fail-safe направления (спек §5.1)
**Files:** Modify `tools/brain-config.mjs`, `tools/brain-config.test.mjs`
- [ ] **Step 1: Failing test — fail-safe направления**
```javascript
describe('resolveConfig fail-safe (§5.1)', () => {
it('state_dir отсутствует → безопасный дефолт', () => {
expect(resolveConfig({}).state_dir).toBe('.claude/brain-state');
});
it('project_url_whitelist пуст → fail-closed маркер (внешка закрыта)', () => {
const r = resolveConfig({});
expect(r.project_url_whitelist).toEqual([]);
expect(r.project_url_whitelist_failClosed).toBe(true);
});
it('normative_files пуст → [] (legitimate), флаг warnIfGroupOn', () => {
expect(resolveConfig({}).normative_files).toEqual([]);
});
it('classifier_context пуст → generic-строка', () => {
expect(resolveConfig({}).classifier_context).toMatch(/generic|общий/i);
});
});
```
- [ ] **Step 2: Run — verify FAIL**
Run: `npx vitest run --root . tools/brain-config.test.mjs`
Expected: FAIL «resolveConfig is not a function».
- [ ] **Step 3: Implement `resolveConfig`**
```javascript
const DEFAULTS = {
state_dir: '.claude/brain-state',
evidence_archive: 'brain-state',
normative_files: [],
registry_path: '',
project_url_whitelist: [],
classifier_context: 'generic project (no profile configured)',
economy_default: '100',
};
/** Применить дефолты + fail-safe направления (§5.1). Чистая. */
export function resolveConfig(raw) {
const c = { ...DEFAULTS, ...(raw || {}) };
// project_url_whitelist: пусто → fail-CLOSED (внешка закрыта), не «пускать всё».
c.project_url_whitelist_failClosed = !(Array.isArray(c.project_url_whitelist) && c.project_url_whitelist.length > 0);
return c;
}
/** I/O-обёртка: прочитать .claude/brain.local.md проекта (fail-safe: нет файла → дефолты). */
export function loadConfig(root = '.', fsImpl = fsDefault) {
let md = '';
try { md = fsImpl.readFileSync(`${root}/.claude/brain.local.md`, 'utf8'); } catch {}
return resolveConfig(parseBrainConfig(md));
}
```
- [ ] **Step 4: Run — verify PASS**
Run: `npx vitest run --root . tools/brain-config.test.mjs`
Expected: PASS (все fail-safe тесты).
- [ ] **Step 5: Commit**
```bash
git add tools/brain-config.mjs tools/brain-config.test.mjs
git commit -m "feat(brain-config): resolveConfig + fail-safe направления §5.1 (Фаза 1 Задача 2)"
```
---
## Task 3: `.claude/brain.local.md` для claude-brain (дефолты = текущие значения)
**Files:** Create `.claude/brain.local.md`
> NB: запись в `.claude/` гейтится стеной как настройка/секрет (не authoring-канал) — этот шаг под пломбированным планом (op:Write, ref на §5 спека) ИЛИ owner-прогон. Зафиксировать в steps-json при пломбировке.
- [ ] **Step 1: Создать файл-настройку**
```markdown
---
config_version: 1
registry_path: docs/registry/nodes.yaml
state_dir: docs/observer
normative_files:
- docs/Pravila_raboty_Claude_v1_1.md
- docs/Plugin_stack_rules_v1.md
- docs/Tooling_v8_3.md
project_url_whitelist:
- liderra.ru
- github.com/liderra
classifier_context: CRM-проект «Лидерра» (Laravel 13 + Vue 3 + Vuetify 3)
enabled_hook_groups:
- core-discipline
- router-mentor
- normative
---
Настройка мозга для самого `claude-brain` (dogfood-консьюмер). Значения = текущие
лидерровские дефолты, чтобы Фаза 1 не меняла поведение. `state_dir: docs/observer`
сохраняет нынешнее расположение журнала; перенос на `.claude/brain-state` — Фаза 3.
```
- [ ] **Step 2: Verify — загрузчик читает файл**
Run: `node -e "import('./tools/brain-config.mjs').then(m=>console.log(JSON.stringify(m.loadConfig('.'))))"`
Expected: вывод с `registry_path`, `normative_files` (3), `project_url_whitelist` (2), `classifier_context`.
- [ ] **Step 3: Commit**
```bash
git add .claude/brain.local.md
git commit -m "feat(brain-config): brain.local.md для claude-brain — дефолты=текущие (Фаза 1 Задача 3)"
```
---
## Task 4: Вынести `normative_files` (backward-compat)
**Files:** Modify `tools/cross-ref-checker.mjs`, `tools/enforce-normative-content-rules.mjs`, `tools/l1-watcher.mjs`, `tools/shell-content-rules.mjs` + их тесты
Паттерн (на примере `cross-ref-checker.mjs:6-16` — карта `FILES`): захардкоженный список путей квинтета → функция принимает `normativeFiles` параметром, дефолт = текущая константа (backward-compat).
- [ ] **Step 1: Failing test — функция принимает normativeFiles, дефолт = текущий**
```javascript
// tools/cross-ref-checker.test.mjs — добавить
it('принимает normativeFiles из настройки, дефолт = квинтет', () => {
const custom = checkCrossRefs({ normativeFiles: ['docs/Foo.md'] });
expect(custom).toBeDefined(); // работает на произвольном списке
const def = checkCrossRefs({}); // дефолт = текущие 3 файла
expect(def).toBeDefined();
});
```
- [ ] **Step 2: Run — verify FAIL**
Run: `npx vitest run --root . tools/cross-ref-checker.test.mjs`
Expected: FAIL (функция игнорирует `normativeFiles`).
- [ ] **Step 3: Implement — параметр со значением по умолчанию**
В `cross-ref-checker.mjs`: вынести захардкоженную карту в `const DEFAULT_NORMATIVE = {...}` (текущие пути), принять `{ normativeFiles = DEFAULT_NORMATIVE } = {}`. Повторить паттерн для `enforce-normative-content-rules.mjs` (regex 15-16/33/69 → строить из списка), `l1-watcher.mjs:57`, `shell-content-rules.mjs:32-34`. Везде дефолт = текущее значение.
- [ ] **Step 4: Run — verify PASS + регрессия не сломана**
Run: `npx vitest run --root . tools/cross-ref-checker.test.mjs tools/enforce-normative-content-rules.test.mjs tools/shell-content-rules.test.mjs tools/l1-watcher.test.mjs`
Expected: PASS (новые + все существующие — дефолт сохранил поведение).
- [ ] **Step 5: Commit**
```bash
git add tools/cross-ref-checker.mjs tools/enforce-normative-content-rules.mjs tools/l1-watcher.mjs tools/shell-content-rules.mjs tools/*.test.mjs
git commit -m "feat(brain-config): normative_files из настройки, дефолт=квинтет (Фаза 1 Задача 4)"
```
---
## Task 5: Вынести `registry_path`, `state_dir` (backward-compat)
**Files:** Modify `tools/registry-load.mjs` (+ потребители), `tools/observer-stop-hook.mjs`, `tools/status-md-generator.mjs`, `tools/cost-stop-hook.mjs` + тесты
- [ ] **Step 1: Failing test — registry_path/state_dir параметризуемы, дефолт текущий**
```javascript
// registry-load.test.mjs
it('loadRegistry принимает registryPath, дефолт = docs/registry/nodes.yaml', () => {
expect(() => loadRegistry({})).not.toThrow(); // дефолт
});
// cost-stop-hook.test.mjs — fail-safe §5.1
it('runUpdate с битым state_dir → fallback + warn, не тихий no-op', () => {
const r = runUpdate({ episodes: [], dateISO: '2026-06-15', stateDir: '' });
expect(r.warnedFallback).toBe(true);
});
```
- [ ] **Step 2: Run — verify FAIL**
Run: `npx vitest run --root . tools/registry-load.test.mjs tools/cost-stop-hook.test.mjs`
Expected: FAIL.
- [ ] **Step 3: Implement**
`registry-load.mjs:13` уже имеет `DEFAULT_REGISTRY_PATH` — принять `registryPath = DEFAULT_REGISTRY_PATH` параметром, протянуть в потребители. `state_dir`: в `observer-stop-hook`/`status-md-generator`/`cost-stop-hook` заменить захардкоженный `docs/observer` на параметр `stateDir`, дефолт `docs/observer`; при пустом/небитом → fallback `.claude/brain-state` + `warnedFallback:true` (спек §5.1), **не** тихий no-op.
- [ ] **Step 4: Run — verify PASS + регрессия**
Run: `npx vitest run --root . tools/registry-load.test.mjs tools/cost-stop-hook.test.mjs tools/observer-stop-hook.test.mjs tools/status-md-generator.test.mjs`
Expected: PASS.
- [ ] **Step 5: Commit**
```bash
git add tools/registry-load.mjs tools/observer-stop-hook.mjs tools/status-md-generator.mjs tools/cost-stop-hook.mjs tools/*.test.mjs
git commit -m "feat(brain-config): registry_path + state_dir из настройки + fail-safe (Фаза 1 Задача 5)"
```
---
## Task 6: Вынести `project_url_whitelist` (fail-CLOSED) + `classifier_context`
**Files:** Modify `tools/mcp-tool-classifier.mjs`, `tools/commit-message-scanner.mjs`, `tools/router-classifier.mjs`, `tools/brain-retro-opus-reviewer.mjs` + тесты
- [ ] **Step 1: Failing test — whitelist fail-CLOSED, classifier_context инъекция**
```javascript
// mcp-tool-classifier.test.mjs
it('пустой whitelist → внешний URL блокируется (fail-closed §5.1)', () => {
expect(classifyMcpTool('mcp__playwright__browser_navigate',
{ url: 'https://example.com/x' }, { urlWhitelist: [] }).decision).toBe('block');
});
it('whitelist из настройки пускает свой домен', () => {
expect(classifyMcpTool('mcp__playwright__browser_navigate',
{ url: 'https://liderra.ru/x' }, { urlWhitelist: ['liderra.ru'] }).decision).toBe('allow');
});
// router-classifier.test.mjs
it('classifier_context инъектируется в system-prompt', () => {
const sys = buildClassifierSystem({ classifierContext: 'ТестПроект XYZ' });
expect(sys).toMatch(/ТестПроект XYZ/);
});
```
- [ ] **Step 2: Run — verify FAIL**
Run: `npx vitest run --root . tools/mcp-tool-classifier.test.mjs tools/router-classifier.test.mjs`
Expected: FAIL.
- [ ] **Step 3: Implement**
`mcp-tool-classifier.mjs` (63-67/118) + `commit-message-scanner.mjs` (13-15): захардкоженные whitelist'ы → параметр `urlWhitelist`, дефолт `[]`**fail-CLOSED** (пусто → блок внешнего). Для backward-compat в `claude-brain` whitelist приходит из `brain.local.md` (`liderra.ru`, `github.com/liderra`). `router-classifier.mjs` (296/228) + `brain-retro-opus-reviewer.mjs` (69): вынести проектную строку в параметр `classifierContext`, дефолт = generic; в `claude-brain` приходит из настройки.
- [ ] **Step 4: Run — verify PASS + регрессия**
Run: `npx vitest run --root . tools/mcp-tool-classifier.test.mjs tools/commit-message-scanner.test.mjs tools/router-classifier.test.mjs tools/brain-retro-opus-reviewer.test.mjs`
Expected: PASS (внимание: существующие тесты, ждущие `liderra.ru`, теперь передают whitelist явно).
- [ ] **Step 5: Commit**
```bash
git add tools/mcp-tool-classifier.mjs tools/commit-message-scanner.mjs tools/router-classifier.mjs tools/brain-retro-opus-reviewer.mjs tools/*.test.mjs
git commit -m "feat(brain-config): project_url_whitelist (fail-closed) + classifier_context (Фаза 1 Задача 6)"
```
---
## Task 7: Полный регресс + wiring загрузчика в хуки
**Files:** Modify зарегистрированные хуки-обёртки (читают `loadConfig` в `main()`), full vitest
- [ ] **Step 1: Прокинуть `loadConfig()` в `main()` хуков**
В `main()` каждого затронутого хука (`enforce-normative-content-rules`, `enforce-mcp-classification`, `observer-stop-hook`, `cost-stop-hook`, `cross-ref-checker` CLI, `router-classifier`): вызвать `loadConfig(repoRoot)` и передать значения в чистые функции. Чистые функции не знают про I/O — настройку читает обёртка.
- [ ] **Step 2: Полный регресс tools/-свода**
Run: `npx vitest run --root . tools/`
Expected: PASS весь свод (~3931+ тестов; backward-compat дефолты сохранили поведение `claude-brain`).
- [ ] **Step 3: Commit**
```bash
git add tools/*.mjs
git commit -m "feat(brain-config): wiring loadConfig в хуки + полный регресс (Фаза 1 Задача 7)"
```
---
## Self-Review (выполнено при написании)
- **Покрытие спека:** Задачи 4–6 закрывают все 5 ключей §3.3 (+3 новых); Задача 2 закрывает fail-safe §5.1 (state_dir fallback, project_url_whitelist fail-closed); Задача 1/3 — загрузчик + настройка консьюмера; Задача 7 — wiring + регресс. §6 группы (`enabled_hook_groups`) читаются в Фазе 2 (упаковка) — здесь только хранятся в настройке.
- **Заглушки:** код-шаги несут реальный код (парсер, resolveConfig, тесты); extraction-шаги дают паттерн + точные файлы:строки из §3.3 спека. Команды vitest — точные (через рабочий `npx vitest run --root .`).
- **Согласованность:** `parseBrainConfig`/`resolveConfig`/`loadConfig` — единые имена через все задачи; `urlWhitelist`/`classifierContext`/`stateDir`/`registryPath`/`normativeFiles` — единые имена параметров; дефолт всюду = текущее лидерровское значение (backward-compat инвариант).
- **Стена:** план помечен под пломбировку (steps-json + sealed артефакт-спек, Task запрещён); шаг записи в `.claude/brain.local.md` — под планом/owner (гейтится как настройка).
@@ -0,0 +1,206 @@
# Дизайн: «Мозг как плагин Claude Code» — раздача и обновление управляющего слоя (v6)
**Дата:** 2026-06-15
**Статус:** Draft (брейншторм согласован; + находки Фазы 0 + инвентарь документации движка + сверка со split-дизайном)
**Репозиторий:** `claude-brain` (дом разработки управляющего слоя, ADR-020)
**Заменяет:** v1–v5. v6 добавляет **§3.4 Документация движка** (включая пользовательскую инструкцию `router-mentor-wall-GUIDE.md` — найдено в Фазе 0) и **§15 Отношение к claude-brain-split** (мой плагин-дизайн — ступень ПОСЛЕ существующего split-дизайна, не дубль). После прохождения судьи — свести версии в один файл.
---
## 1. Контекст и проблема
Управляющий слой Claude («мозг») сегодня — 100+ `tools/*.mjs` (хуки `enforce-*`, роутер `router-*`, наблюдатель `observer-*`, ретро `brain-retro-*`, реестр `registry-*`, стоимость `cost-*`, стена `supreme-gate`/`plan-lock`/`freeze-gate`/`judge-*`/`mentor-*`), агенты `.claude/agents/`, реестр `docs/registry/`, **документация движка** `docs/superpowers/` (§3.4), квинтет, `CLAUDE.md`. Подключено через `.claude/settings.json` и захардкоженные пути.
Задачи: (1) раздать мозг в другие проекты; (2) обновлять у консьюмеров без поломки их настроек/начинки. Прошлый installer демонтируется. **Корень боли:** движок и проект в одних папках; движок жёстко «знает про Лидерру» (Фаза 0, §3.3).
---
## 2. Цели и не-цели
**Цели:** чистая граница движок/начинка; движок = родной плагин; безопасное обновление; «обучение» проекта одним файлом; гранулярность групп; правила параллельной разработки; сохранность журнала; fail-safe настройки (§5.1); **движок несёт свою документацию** (§3.4).
**Не-цели (YAGNI):** не строим marketplace-инфру под несуществующие проекты; не пишем синхронизатор дрейфа; не реактивируем `ruflo-*`; не мигрируем Лидерру (§11); **не дублируем claude-brain-split** — он отдельная ступень (§15).
---
## 3. Архитектура: три слоя
| Слой | Что | Где | При обновлении |
|---|---|---|---|
| **1. Движок** | хуки/роутер/наблюдатель/ретро/стена/реестр/стоимость, универсальные агенты/скилы, **документация движка** (§3.4) | плагин (кэш) | **обновляется** `claude plugin update` |
| **2. Настройка** | нормативка/защита/реестр/модель/экономия/группы/домены/профиль/хранилище улик | `.claude/brain.local.md` | **не трогается** |
| **3. Начинка** | `nodes.yaml`, квинтет, `CLAUDE.md`, проектные агенты, журнал | проект / ветка `brain-state` | **не трогается** |
### 3.1. Граница «репозиторий ≠ плагин»
Плагин = объявленный в манифесте набор файлов движка. Репозиторий может хранить и другое (квинтет Лидерры по ADR-020, dev-доки Лидерры) — вне поставки плагина: `claude-brain ⊇ плагин(движок+его документация) + не-плагинный контент`.
### 3.2. Инвентарь по слоям (Фаза 0, факт)
| Категория | Слой | Примеры |
|---|---|---|
| Движок — стена | 1 | `enforce-supreme-gate`, `plan-lock`, `freeze-gate`, `seal-orchestration`, `judge-*`, `mentor-*`, `step-pointer`, `receipt-sign`, `path-normalization`, `bash-tokenizer`, `enforce-floor*` |
| Движок — роутер/наблюдатель/ретро/стоимость | 1 | `router-gate-decide`, `router-embedding`, `observer-stop-hook`, `brain-retro-*`, `cost-*`, `discipline-metrics`, `system-health` |
| Движок — реестр (библиотеки) | 1 | `registry-load`, `registry-render`, `registry-to-classification-map`, `node-graph`, `project-graph` |
| Движок — универсальные агенты | 1 | `reviewer-agent` |
| Движок — документация | 1 | см. §3.4 |
| Настройка (вынести) | 2 | см. §3.3 |
| Начинка — данные реестра | 3 | `docs/registry/nodes.yaml` |
| Начинка — проектные агенты | 3 | `normative-sync`, Лидерра-агенты |
| Начинка — нормативка | 3 | `CLAUDE.md`, квинтет |
| Изменяемое состояние | 3 | эфемерное + долговечные улики — §7 |
| Dormant (вне плагина) | — | `ruflo-*` |
### 3.3. Config-seam (Фаза 0, по целевому ключу)
| Ключ | Захардкожено в |
|---|---|
| `normative_files` | `cross-ref-checker`, `enforce-normative-content-rules` (15-16/33/69), `l1-watcher` (57), `registry-render`, `observer-transcript-parser` (371-372), `shell-content-rules` (32-34) |
| `registry_path` | `registry-load` (DEFAULT), `registry-render`, `registry-to-classification-map`, `node-graph`, `project-graph`, `observer-coverage-checker`, `brain-retro-analyzer`, `test-rollback` |
| `state_dir` | `observer-stop-hook`, `-of-observer`, `-retrofill-chain-ref`, `-coverage-checker`, `status-md-generator`, `shadow-replay`, `cost-stop-hook`, `brain-retro-batch-reviewer`, `brain-dashboard-server`, `project-graph`, `test-rollback` |
| **`project_url_whitelist`** 🆕 | `mcp-tool-classifier` (63-67/118), `commit-message-scanner` (13-15) |
| **`classifier_context`** 🆕 | `router-classifier` (296/228), `brain-retro-opus-reviewer` (69) |
| косметика (Pravila §-ссылки) | `subagent-prompt-prefix`, `missed-activations`, `observer-pii-filter`, `enforce-branch-switch`, `discipline-metrics`, `ruflo-queen-hook` |
### 3.4. Документация движка (Фаза 0, находка — «отмечено»)
Движок несёт собственную документацию в `docs/superpowers/` и `docs/adr/`. Она — **часть поставки плагина (слой 1)**, не Лидерра-контент. Категории:
- **Пользовательская инструкция (как работает / как пользоваться):** `docs/superpowers/router-mentor-wall-GUIDE.md` — шпаргалка по стене «роутер-наставник»: церемония (спека→печать→план→печать→шаги→авто-завершение), частые ошибки (устаревший указатель, авторская запись, floor-safe планы), **проверка состояния** (`echo X` → «разговорный режим»/«ожидался шаг N»/выполнилось), **только-владельцу** (вкл/выкл стены `"hooks": {}` + перезапуск, снятие застрявшей печати), **escape-процедура** (`FLOOR-ESCAPE: <canonicalAction>`), git через `approve_git_operation`, «что под капотом». **NB:** GUIDE покрывает **стену**; остальной мозг (наблюдатель/экономия/роутер-тулинг) для пользователя рассыпан по CLAUDE.md §3 + `router-procedure.md` + `routing-off-phase.md`. Единого «руководства по всему мозгу» нет — **кандидат-пробел** (§13).
- **Runbook'и (операции):** `2026-06-11-router-mentor-activation-runbook.md`, `2026-06-09-sealed-plan-daily-cycle-walkthrough.md`, `2026-06-09-phase8-deployment-runbook.md`, `2026-06-10-phase8-settings-paste-block.md`, активация A1/A6/A7.
- **Dev design-спеки:** Машины 1–7 (`router-mentor-machine-{1..7}`), seal/gate (`sealed-plan-production`, `gate1-and-se2`, `seal-race-mentor-then-judge`), floor (`machine-5-floor`, `floor-escape-signing`), `supreme-gate-post-advance`, two-level-negotiation, print-sanity, shadow-replay, mentor-skill-resolve.
- **ADR движка (governance):** ADR-011 (brain-governance), ADR-016 (universal skill-coverage), ADR-020 (split). **ADR off-phase-тулинга** (003-010, 012-015, 017, 019) — пограничные: описывают выбор инструментов Лидерры → ближе к контенту, но живут в `claude-brain` по split-дизайну (корзина A).
- **Процедура/роутинг:** `router-procedure.md`, `routing-off-phase.md`.
**Импликация для упаковки:** плагин обязан **поставлять документацию движка** (минимум — пользовательскую инструкцию + runbook'и; dev-спеки/ADR — опционально или в dev-варианте плагина). Я в §3.2 (v5) инвентаризировал только КОД `tools/` — документация была пропущена; v6 это закрывает. Это новая под-категория слоя 1.
---
## 4. Упаковка плагина
Манифест объявляет состав движка (hooks/agents/skills/commands **+ docs**); пути → `${CLAUDE_PLUGIN_ROOT}`; `claude-brain` — локальный marketplace; включение — `enabledPlugins`.
**Тяжёлая часть:** (1) вынести config-seam §3.3 в настройку; (2) path-rewrite `${CLAUDE_PLUGIN_ROOT}`; (3) инлайн `node -e` хуки в `settings.json` → вынести в хук-файлы; (4) **отобрать документацию движка (§3.4) в поставку** и почистить в ней Лидерра-специфику примеров.
---
## 5. Слой 2: настройка `.claude/brain.local.md`
YAML-frontmatter + markdown.
- `config_version`; `normative_files`; `protected_paths`; `registry_path`; `state_dir` (дефолт `.claude/brain-state/`); `evidence_archive` (дефолт `brain-state`, §7б); **`project_url_whitelist`** 🆕; **`classifier_context`** 🆕; `model`; `economy_default`; `enabled_hook_groups` (§6).
### 5.1. Принцип fail-safe настройки
**Отсутствующий/невалидный ключ НЕ отключает молча безопасность/деньги/защиту.** Каждый ключ имеет безопасное направление отказа + громкий warn на старте сессии.
| Ключ | При отсутствии/невалидности | Направление |
|---|---|---|
| `state_dir` | дефолт `.claude/brain-state/`; не пишется → fallback + **громкий warn**; наблюдатель/стоимость пишут в fallback, **не** выключаются | safe default + fail-loud |
| `evidence_archive` | дефолт `brain-state` (§7б); опт-аут только явный | safe default |
| `project_url_whitelist` | **fail-CLOSED**: пусто → внешка блокируется (не «пускать всё») + warn | fail-closed (security) |
| `normative_files` | пусто = легитимно; группа `normative` включена при пустом списке → warn | explicit-empty + warn |
| `registry_path` | пусто = легитимно (registry-зависимости off осознанно) | explicit-empty |
| `classifier_context` | пусто → generic-формулировка (деградация качества, не безопасности) | safe degrade |
**Cost:** `cost-stop-hook` — трекер (не лимитёр), но **не должен молча переставать считать** при плохом `state_dir` (правило выше). Если добавится бюджетное ограничение — оно **fail-CLOSED** (невозможно прочитать расход → консервативно блокировать дорогое).
---
## 6. Гранулярность: группы сторожей (Фаза 0)
- **`core-discipline`** — `enforce-domain-skill-discipline`, `enforce-verify-gate`, `enforce-todowrite-skill-verifier`, `enforce-read-path-deny`, `enforce-mcp-classification` (→ `project_url_whitelist`), `enforce-coverage-verify`.
- **`router-mentor`** — `enforce-floor`, `enforce-supreme-gate`, `enforce-snapshot`, `enforce-criterion-gate`, `askuser-cosmetic-detector`, `enforce-mentor-then-judge` (→ `mentor-on-plan-write`+`judge-gate`), `enforce-skill-journaler`, `enforce-askuser-answer-parser`, `enforce-floor-escape-consume`, `observer-stop-hook`, `cost-stop-hook`, `floor-manifest-check`, `router-embedding-warmup`.
- **`normative`** — `enforce-normative-content-rules` (→ `normative_files`) + инлайн-напоминание `db/schema.sql`.
**Уточнения discovery:** (1) `registry` — НЕ группа хуков, а библиотечная зависимость router-mentor/observer/normative. (2) Множество v4-хуков присутствует, но НЕ подключено (`enforce-llm-judge-*`, `enforce-powershell-gate`, `enforce-router-gate`, `enforce-safe-baseline-metering`, `enforce-parallel-session-lock`, `enforce-branch-switch`, `enforce-rationalization-audit`, `enforce-prompt-injection`, `enforce-decomposition-detector`, `enforce-self-debrief-detector`, `enforce-subagent-return-scanner`, `enforce-memory-coverage`, `enforce-override-monitor`) — упаковка различает «подключено по умолчанию» vs «opt-in». (3) Инлайн `node -e` хуки — §4.
Greenfield: `core-discipline``router-mentor`). Лидерра — все.
---
## 7. Изменяемое состояние — два вида
### (а) Эфемерное — теряется безопасно
`runtime/`, `STATUS.md`, счётчики → `state_dir` (`.claude/brain-state/`), **гитигнор**. Потеря безопасна; убирает коллизии параллельной работы.
### (б) Долговечные улики — сохранность по умолчанию
`episodes-*.jsonl` — доказательная база, не воспроизводится. **Персист по умолчанию; молчаливая потеря невозможна.** Дефолт — git-ref `brain-state` (Stop-хук append-only через git-плумбинг без checkout → активный worktree не трогается; не вливается в код → нет коллизий; union, без rebase). Есть remote → пуш → переживает clone; нет → локальная ветка + громкий warn. Опт-аут только явный (`evidence_archive: none` + подтверждение).
---
## 8. Обновление и миграция настройки
`claude plugin update` меняет только кэш движка; `settings.json`/`CLAUDE.md`/`nodes.yaml`/журнал не трогаются. `config_version` + хук на старте сверяет версию → «настройка устарела, запусти `/brain-migrate`». `/brain-migrate` дописывает недостающие ключи с безопасными дефолтами (§5.1).
---
## 9. Жизненный цикл
1. Собрать плагин. 2. Поставить в `claude-brain`, заменить зоопарк (dogfood). 3. Улучшения — в **worktree**. 4. Тесты (vitest `tools/` ~3931 + новые). 5. Влить в `main` = релиз → `claude plugin update` → тест на реальных задачах. 6. Накат в новый проект/Лидерру (плагин + `brain.local.md`). Первый внешний накат — greenfield.
---
## 10. Параллельная разработка и интеграция
1. **worktree, не копии** (общая история; затирание только на одних строках, git остановится). 2. Эфемерное вне git; улики — изолированная ветка `brain-state`, union, без rebase. 3. Последовательное слияние с тестовым гейтом (A → тесты → влить; B → rebase → тесты → влить). Центральные списки — малые ручные точки; генерируемое — на сборке, не коммитить. Одно улучшение = один worktree.
---
## 11. Лидерра и прочие консьюмеры (поздний, опциональный шаг)
Не входит в эту работу. **Текущая модель Лидерры — «снимок»** (split-дизайн D1: замороженная рабочая копия + квинтет-снимок, односторонний ручной перенос из `claude-brain`), НЕ плагин. Плагин-консьюмерство Лидерры — **будущая эволюция** поверх снимка (§15). Когда дойдём: Лидерра включит плагин + `brain.local.md` (все группы); начинка остаётся у неё; квинтет — в `claude-brain` (ADR-020), вне поставки плагина.
---
## 12. Риски
- **Объём discovery** — Фаза 0: ~31 движковый файл связан с Лидеррой по 5 ключам; greenfield-накат вскроет пропуски.
- **Документация — пропускалась в инвентаре** (закрыто §3.4); риск забыть поставить пользовательскую инструкцию с плагином → консьюмер не знает, как пользоваться.
- **Рекурсия dogfood** — разработка в worktree.
- **Манифест как точка слияния** — известная малая ручная точка.
- **Потеря улик** — молча невозможна (дефолт `brain-state`); остаток: greenfield-без-remote + clone-с-нуля (предупреждён) либо явный `none`.
- **Тихое отключение безопасности/денег** — закрыто §5.1.
- **Запись в `brain-state`** — git-плумбинг без checkout, нетривиально; тесты fail-safe.
- **Стена блокирует спайк** — Задача 4 под стеной не исполнима; owner-прогон/песочница.
- **Баг наставника (known).** split-handoff §H4: наставник зацикливается (NO-GO с рекомендацией = плану; требует несуществующий `GATE`-op; путает путь как «исходный репо»). Это объясняет трение v1→v6. Починка — отдельная задача в `claude-brain` (см. §13).
---
## 13. Открытые вопросы (для плана)
1. Полный per-file инвентарь слоя 1 (в плане Фазы 1).
2. Финал ключей `brain.local.md` (+3 новых §3.3) и направления fail-safe (§5.1) под тесты.
3. Где держать локальный marketplace-источник.
4. Нужен ли `claude-brain` свой минимальный `nodes.yaml`/нормативка как консьюмеру.
5. Реализация `brain-state`: git-плумбинг vs служебный worktree; расписание; без remote.
6. Инлайн `node -e` хуки — в хук-файлы движка или в settings-шаблон консьюмера?
7. Судьба неподключённых v4-хуков — opt-in / отдельная группа / не поставлять?
8. **Документация:** какой минимум документации движка едет в плагин (только пользовательская инструкция + runbook'и, или и dev-спеки/ADR)? Чистка Лидерра-примеров в GUIDE.
9. **Пробел: нет единого «руководства по всему мозгу»** (GUIDE только про стену) — написать сводный user-manual (стена + наблюдатель + экономия + роутер-тулинг)?
10. **Баг наставника (§12 H4)** — починить (засчитывать `ls claude-brain/...` как gate; принимать нарративную паузу вместо несуществующего GATE-op).
11. **Стена (meta):** нет канала *правки* напечатанного артефакта (только новая версия/escape) — породило v1→v6; кандидат на доработку.
---
## 14. Фазы реализации
- **Фаза 0 — Discovery.** Задачи 1–3 (инвентарь кода/config-seam/группы) + инвентарь документации (§3.4) **выполнены**. Задача 4 (смоук) — owner-gated, отложена.
- **Фаза 1 — Config seam.** Чтение `brain.local.md` + fail-safe (§5.1); вынос §3.3 по ключу под тестами. Инлайн-исполнима пломбированным планом (`2026-06-15-brain-plugin-phase1-config-seam.md`).
- **Фаза 2 — Plugin packaging.** Манифест (+docs §3.4) + path-rewrite; группы §6; инлайн-хуки §4; `/brain-migrate` + `config_version`.
- **Фаза 3 — Persist улик.** `brain-state` (§7б) + тесты fail-safe.
- **Фаза 4 — Dogfood.** Плагин в `claude-brain`, замена зоопарка, тесты + реальные задачи.
- **Фаза 5 — Greenfield rollout.** Накат в новый проект, проверка границы.
---
## 15. Отношение к claude-brain-split (сверено в Фазе 0)
В репозитории уже есть `claude-brain-split-design` (v5) + `status-handoff` (оба 2026-06-15). Это **другая ступень**, не дубль этого дизайна:
| | claude-brain-split (существующий) | brain-as-plugin (этот) |
|---|---|---|
| Про что | разделить общий репо на `claude-brain` (дом разработки) + Лидерру (продукт + замороженная копия) | сделать движок раздаваемым плагином в *другие* проекты |
| Модель связи | **снимок** (односторонний ручной перенос квинтета) | плагин (`claude plugin update`) |
| Статус | почти готов (claude-brain автономен, 3931 тест зелёный, прун закоммичен `3aeedb8a`; хвост — копия specs, память, `CLAUDE.md`) | дизайн + план Фаз 0–1 |
**Последовательность:** split создал отдельный репозиторий → плагин делает его движок устанавливаемым в чужие проекты. **Совместимость:** квинтет в `claude-brain` (split D1) = канонический Лидерра-контент со снимок-штампом, в плагин не едет (совпадает с §3.1/§11); текущая Лидерра-связь = снимок, плагин — будущая эволюция (§11). Этот дизайн **не отменяет и не переписывает** split — он его продолжение.
@@ -0,0 +1,81 @@
# Brain-as-plugin — handoff сессии (закрытие 2026-06-15)
**Кодовая фраза стены:** «роутер-наставник». **Канон дизайна:** `2026-06-15-brain-as-plugin-design-v6.md`. **Канон плана:** `2026-06-15-brain-plugin-phase1-config-seam.md`. Этот файл — снимок прогресса + остатки по поиску + драфты памяти + промт для следующей сессии.
## 1. Что сделано
- **Дизайн «Мозг как плагин Claude Code» — spec v6** (через `brainstorming`). Трёхслойная модель: **движок** (плагин, обновляется `claude plugin update`) / **настройка** (`.claude/brain.local.md`, не трогается) / **начинка** (проект). Механизм раздачи = родной плагин Claude Code (не самодельный installer — он демонтируется). Жизненный цикл: собрать плагин → dogfood в `claude-brain` → улучшения в worktree → тесты → релиз в main → накат в новый проект.
- **План Фазы 1 (config seam) — готов** (через `writing-plans`). 7 TDD-задач: загрузчик `brain-config.mjs` → fail-safe `resolveConfig``brain.local.md` → вынос ключей по одному (backward-compat: дефолт = текущее лидерровское значение) → wiring + регресс.
- **Фаза 0 (discovery) выполнена** — инвентарь ниже.
## 2. Находки Фазы 0 (config-seam — что движок жёстко знает про Лидерру)
| Ключ настройки | Файлы |
|---|---|
| `normative_files` | cross-ref-checker, enforce-normative-content-rules(15-16/33/69), l1-watcher(57), registry-render, observer-transcript-parser(371-372), shell-content-rules(32-34) |
| `registry_path` | registry-load(DEFAULT), registry-render, registry-to-classification-map, node-graph, project-graph, observer-coverage-checker, brain-retro-analyzer, test-rollback |
| `state_dir` | observer-stop-hook, -of-observer, -retrofill-chain-ref, -coverage-checker, status-md-generator, shadow-replay, cost-stop-hook, brain-retro-batch-reviewer, brain-dashboard-server, project-graph, test-rollback |
| `project_url_whitelist` 🆕 | mcp-tool-classifier(63-67/118), commit-message-scanner(13-15) |
| `classifier_context` 🆕 | router-classifier(296/228), brain-retro-opus-reviewer(69) |
- **3 новых ключа** (не было в спеке до discovery): `project_url_whitelist`, `classifier_context` (+ шаблон промпта судьи).
- **Группы хуков** (зарегистрированные в settings.json): `core-discipline` / `router-mentor` / `normative`. `registry` — НЕ группа хуков, а библиотечная зависимость. Множество v4-хуков присутствует, но НЕ подключено (llm-judge, powershell-gate, router-gate, safe-baseline, parallel-session-lock, branch-switch, rationalization-audit, prompt-injection, decomposition, self-debrief, subagent-return, memory-coverage, override-monitor).
- **Документация движка** (§3.4 v6): пользовательская инструкция = `router-mentor-wall-GUIDE.md`; runbook'и; dev-спеки (Машины 17, seal/gate/floor); ADR (011/016/020 + tooling). Плагин обязан везти документацию.
- **Пользовательская инструкция найдена:** `router-mentor-wall-GUIDE.md` — «как работает / как пользоваться» стеной. Покрывает только стену; единого «руководства по всему мозгу» нет.
- **Сверка со split-дизайном:** `claude-brain-split` (v5, почти готов) ≠ дубль. Split разделил репо (модель «снимок»); plugin делает движок раздаваемым (следующая ступень). Совместимы.
- **fail-safe настройки (spec §5.1):** отсутствующий ключ не отключает молча безопасность/деньги/защиту (`state_dir` → fallback+warn; `project_url_whitelist` → fail-CLOSED).
## 3. Остатки по поиску (для следующей сессии) {#remainders}
1. **Полный per-file инвентарь слоя 1** — discovery дал config-seam (~31 файл) и грубую раскладку; точный список каждого `tools/*.mjs` по слою 1/2/3 не закрыт (греп был обрезан на 120+140 строках; косметические Pravila §-ссылки не каталогизированы пофайлно).
2. **Задача 4 (плагин-смоук) — owner-gated, НЕ сделана.** Под стеной не исполнима: `plugin-dev:plugin-structure` skill — не «семя» (стена завернёт), создание файлов плагина гейтится. Нужен owner-прогон/песочница ИЛИ escape. Это блокирует Фазу 2 (формат манифеста).
3. **Судьба неподключённых v4-хуков** — opt-in в плагине / отдельная группа / не поставлять? (§13.7 v6).
4. **Инлайн `node -e` хуки** в settings.json (CLAUDE.md-warn, markdownlint-fix, schema.sql-reminder) — вынести в хук-файлы или в settings-шаблон консьюмера? (§13.6).
5. **Минимум документации в поставке** плагина + чистка Лидерра-примеров в GUIDE (§13.8).
6. **Пробел: нет единого user-manual по всему мозгу** (GUIDE только про стену) — кандидат написать (§13.9).
7. **Баг наставника** (split-handoff §H4, spec v6 §12): зацикливается NO-GO; путает путь как «исходный репо»; требует несуществующий `GATE`-op. Чинить в `claude-brain` (§13.10).
8. **Meta: нет канала in-place правки артефакта** под стеной → породило цепочку spec v1→v6 + plan-v1→v2. Кандидат на доработку стены (§13.11).
9. **Уборка версий:** spec v1v5 заменены v6; plan Фазы 0 v1 заменён реальностью discovery. Свести в один файл — нужен escape (удаление под стеной).
## 4. Драфты memory-записей (залить в memory-store следующей сессией штатно)
> Запись в `~/.claude/.../memory/` гейтится (escape или `claude-md-management`-церемония). Ниже — готовые записи; следующая сессия их персистит + добавит строки в MEMORY.md.
- **project_brain_as_plugin.md** (type: project) — «Эпик: упаковка движка мозга в плагин Claude Code. Канон — spec v6 + план Фазы 1. Трёхслойная модель (движок/настройка/начинка). Фаза 0 discovery done; Фазы 1–5 впереди; Задача 4 спайк owner-gated. Не дубль claude-brain-split (это следующая ступень).»
- **feedback_brain_config_seam_keys.md** (type: reference) — «5 config-seam ключей + 3 новых (project_url_whitelist, classifier_context). Список файлов — spec v6 §3.3.»
- **feedback_wall_user_manual.md** (type: reference) — «Пользовательская инструкция к стене = docs/superpowers/router-mentor-wall-GUIDE.md (церемония/ошибки/проверка состояния/owner-контроли/escape/git). Покрывает только стену.»
- **feedback_wall_no_inplace_artifact_edit.md** (type: feedback) — «Под стеной нет канала правки напечатанного spec/plan — только новая версия (authoring) или escape. Замечание судьи → пиши сразу новую версию, не Edit. Why: isAuthoringWrite пускает только НОВЫЙ файл в specs/plans. How: планируй версии vN заранее.»
- **feedback_subagents_forbidden_under_wall.md** (type: feedback) — «Субагенты (Task) под стеной запрещены (plan-steps-parse VA-4: op:Task throw). Исполнять планы инлайн (executing-plans), не subagent-driven. Why: шаг-Task не пломбируется. How: инлайн + пломбированный план.»
## 5. Скилл-цепочка для следующей сессии {#skillchain}
1. **`using-superpowers`** — всегда первым (авто на старте).
2. Для **продолжения дизайна** остатков (§3 п.5/6/9 — manual, packaging-решения) → **`brainstorming`** (если новые требования) → **`writing-plans`**.
3. Для **исполнения Фазы 1** (config seam) → **`executing-plans`** ИНЛАЙН (НЕ `subagent-driven-development` — субагенты под стеной запрещены, VA-4). Предусловие: план опломбировать (steps-json + опечатанный артефакт-спек + owner-seal — см. GUIDE). TDD-шаги — через **`test-driven-development`**.
4. Для **записи в память/нормативку****`claude-md-management`** (объявить в skills-json пломбированного плана + вызвать) ИЛИ owner escape.
5. Баг наставника (§3 п.7) → **`systematic-debugging`**.
## 6. Промт для следующей сессии (копировать целиком)
```
Продолжаем эпик «Мозг как плагин Claude Code» в проекте claude-brain. Кодовая фраза стены — «роутер-наставник», работаем ПО ПРАВИЛАМ (authoring-канал для новых .md в docs/superpowers/{specs,plans}; escape/память — только с моего разрешения; субагенты под стеной запрещены — инлайн).
Сначала прочитай (разговорный режим, чтение свободно):
- docs/superpowers/specs/2026-06-15-brain-as-plugin-design-v6.md (канон дизайна)
- docs/superpowers/plans/2026-06-15-brain-plugin-phase1-config-seam.md (план Фазы 1)
- docs/superpowers/specs/2026-06-15-brain-as-plugin-session-handoff.md (этот handoff: находки, остатки §3, драфты памяти §4, скилл-цепочка §5)
- docs/superpowers/router-mentor-wall-GUIDE.md (как работать под стеной)
Скилл-цепочка (см. handoff §5): using-superpowers → (brainstorming → writing-plans для дизайна) → executing-plans ИНЛАЙН + test-driven-development для Фазы 1 → claude-md-management для памяти → systematic-debugging для бага наставника.
Сделай в начале:
1. Залей драфты памяти (handoff §4) в memory-store + строки в MEMORY.md (через claude-md-management или мой escape — спроси).
2. Спроси меня, что берём дальше из остатков (handoff §3): Фаза 1 (нужна пломбировка — моё участие) / сводный user-manual по мозгу / починка бага наставника / уборка версий (нужен escape) / Задача 4 спайк (owner-gated).
Не пломбируй и не коммить без моего клика. Все находки фиксируй в authoring-доки, в память — только по правилам.
```
## 7. По правилам — напоминания
- Новые `.md` в `specs/`/`plans/` — стена пускает свободно (authoring). Правка существующего / память / settings / код — гейтится.
- Канон: spec **v6**, plan Фазы 1. Старые версии (spec v1–v5) — заменены, уборка под escape отложена.
- Коммит этой сессии не делался (под стеной — твой терминал/escape). Все артефакты на диске.