Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
60 KiB
Brain-retro — первое ретро мозга по данным наблюдателя
Дата: 2026-05-20 (12:25 MSK)
Период: 2026-05-19 .. 2026-05-20 (это первое brain-retro вообще; покрывает всё, что наблюдатель записал на текущий момент)
Источник: docs/observer/episodes-2026-05.jsonl (22 строки) + docs/observer/.read-counter.json
Анализатор: node tools/brain-retro-analyzer.mjs docs/observer/episodes-2026-05.jsonl
Уровень анализа: верхнеуровневый по запросу заказчика («потом углубимся по разделам»); экономия 0%.
Анализатор отчитался:
episodeCount=17,v1SkippedCount=5,observerErrorCount=0. Ниже все цифры по 17 v2-эпизодам, если не отмечено иное.
Period
2026-05-19T05:18:16Z .. 2026-05-20T08:12:29Z (5 сессий, 22 эпизода всего; 17 v2-анализируемых).
Сессии:
| task_id (session_id) | дата | v1 эпизоды | v2 эпизоды | примечание |
|---|---|---|---|---|
553717ec |
19.05 05:18 .. 10:24 | 5 | 10 | длинная сессия brain-governance Phase A/B/C + factor-analysis ext; компакция между turn 86–91 |
24acfa10 |
20.05 07:08 | 0 | 1 | ExitWorktree-разовый ход |
a42e4ba5 |
20.05 07:26 | 0 | 1 | короткая PowerShell/Bash-проверка |
dd905ea0 |
20.05 07:25 .. 07:28 | 0 | 1 | apdate ЭТАЛОН-семейства memory (11 Edit) |
98298ec2 |
20.05 07:36 .. 08:12 | 0 | 3 | сегодняшняя «починка наблюдателя» (TDD + verify) |
Текущий ход (брейн-ретро 20.05 ~08:25Z+) будет записан Stop-хуком после завершения и в этом ретро ещё не учитывается — это нормально по конструкции наблюдателя.
Path-type distribution (v2, n=17)
| path_type | count | % |
|---|---|---|
| improvised | 14 | 82.4% |
| regulated | 3 | 17.6% |
| alternative | 0 | 0% |
| mixed | 0 | 0% |
Чтение: «Мозг живёт прямым путём». Лишь два эпизода прошли через явный hard-floor §12: №16 (19.05 10:13, systematic-debugging) и №22 (20.05 07:52, TDD + verification-before-completion). Третий «regulated» — №16-ой же эпизод (тот же epoch, после Stop предыдущего короткого). Каждый regulated-эпизод был обоснован профильным триггером (баг наблюдателя + TDD по правке кода).
Outcome distribution (inferred)
| outcome | count | % |
|---|---|---|
| success | 6 | 35% |
| unknown | 11 | 65% |
| partial | 0 | 0% |
| rework | 0 | 0% |
| blocked | 0 | 0% |
Чтение: не было ни одного correction-prompt'а от заказчика (next-prompt-sentiment) за период — переделок нет; ни одного interrupt; ни одного unrecovered_error. 11 «unknown» — это последние эпизоды задач или эпизоды, чей след ещё не сменился новой prompt-меткой (6 из 11 — открытые задачи 20.05; 5 — последние в своих task-группах). Это техническое ограничение выборки, не качественный сигнал.
Поле «failure / aborted» из шаблона анализатор не возвращает — он деградирует до «unknown» (см.
inferOutcomeкоммент A-1).
Top nodes used (skill_invoked + node_chosen)
Из 17 эпизодов 15 имеют node_chosen=direct (88%). Только 2 эпизода открыто декларируют узел:
| node | times | first | last |
|---|---|---|---|
direct |
15 | 2026-05-19T08:06Z | 2026-05-20T07:45Z |
superpowers:systematic-debugging |
1 | 2026-05-19T10:13Z | 2026-05-19T10:13Z |
superpowers:test-driven-development |
1 | 2026-05-20T07:52Z | 2026-05-20T07:52Z |
Полный список skill_invoked events (4 уникальных):
| skill | эпизоды |
|---|---|
superpowers:systematic-debugging |
№16 |
claude-md-management:claude-md-improver |
№16 |
superpowers:test-driven-development |
№22 |
superpowers:verification-before-completion |
№22 |
Все остальные 60+ узлов реестра за период не использовались. Это не проблема (см. memory feedback_brain_unused_tools_not_problem.md).
Factor analysis matrix (v2 — из factorMatrix)
decision_provenance — главный фактор «rework мой или router's?»
| provenance | success | partial | rework | unknown |
|---|---|---|---|---|
autonomous |
5 | 0 | 0 | 8 |
user_directed_method |
1 | 0 | 0 | 2 |
user_chose_from_options |
0 | 0 | 0 | 1 |
Чтение: 76% решений автономные; 18% — заказчик навязал метод; 6% — collaborative-choice (Phase 1.1, routing-gate не блокирует). Метрика rework = 0 во всех ячейках — за период нет признаков «rework по моей вине» либо «rework по навязанному методу». Ranking фактора сейчас inconclusive из-за нулевого rework.
user_directed_method — что заказчик навязывал
| ход | дата | claude_would_have_chosen | контекст |
|---|---|---|---|
| ep. 7 | 19.05 08:10 | subagent-driven-development |
сразу после post_compaction (turn 83) |
| ep. 8 | 19.05 08:13 | subagent-driven-development |
следующий ход той же сессии |
| ep. 10 | 19.05 08:25 | brainstorming |
через 12 минут |
Все три — turn 83–88 на той же сессии, сразу после post_compaction=true (компакция отрезала контекст). Это паттерн «после компакции заказчик возвращает рулевое».
economy_level
| economy_level | success | unknown |
|---|---|---|
null |
2 | 2 |
0 |
0 | 1 |
5 |
3 | 5 |
100 |
1 | 3 |
null = sentinel не поставлен (legacy 4 эпизода 19.05 утром). Прочие — три тарифа (0/5/100) используются равноценно по решению заказчика per task. Никаких корреляций «экономия→outcome» при текущем n=17 не вытащить.
model
| model | success | unknown |
|---|---|---|
claude-opus-4-7 |
6 | 11 |
Все 17 v2-эпизодов на Opus 4.7. Контрольной группы (Sonnet/Haiku) в данных нет → факторный анализ по модели невозможен. Это ожидаемо: subagent-driven-development вызывает Sonnet/Haiku субагентами, чьи трейсы в основной transcript не попадают (Stop-хук пишет только верхнего Claude).
post_compaction
| post_compaction | success | unknown |
|---|---|---|
true |
6 | 5 |
false |
0 | 6 |
Псевдо-корреляция: все post_compaction=false эпизоды относятся к 20.05 (новые сессии, ещё не успели получить next-prompt) → все 6 как unknown по конструкции. Сигнал не валиден.
session_turn бакеты
| bucket | success | unknown |
|---|---|---|
early (<10) |
0 | 6 |
late (≥40) |
6 | 5 |
mid (10–40) |
0 | 0 |
Та же артефакт-корреляция, что и с post_compaction: «early» = новые сессии 20.05 → unknown по техническому ограничению. Истинного сигнала нет.
parallel_session
| parallel | success | unknown |
|---|---|---|
true |
5 | 5 |
false |
1 | 6 |
10/17 (59%) ходов шли в режиме параллельных Claude-сессий (Pravila §15 в работе). Outcome по этому фактору inconclusive — нужны более длинные выборки.
task_size
| size | success | unknown |
|---|---|---|
small (<20 tools) |
6 | 9 |
medium (20–60) |
0 | 2 |
large (>60) |
0 | 0 |
88% эпизодов — small. Два medium-эпизода — №20 (22 tool_calls, 13 files: orientation-read для текущего ретро) и №22 (56 tool_calls, 11 files: текущая TDD-починка наблюдателя). Оба ещё «unknown» по next-prompt.
node_chosen
| node | success | unknown |
|---|---|---|
direct |
6 | 9 |
superpowers:systematic-debugging |
0 | 1 |
superpowers:test-driven-development |
0 | 1 |
Все 6 «success» — direct-эпизоды; оба skill-эпизода ещё unknown (regulated, не было follow-up correction/approval prompt'а).
task_classification
| classification | success | unknown |
|---|---|---|
bugfix |
1 | 0 |
feature |
1 | 2 |
refactor |
1 | 0 |
question |
0 | 2 |
other |
3 | 7 |
Преобладание other (10/17 = 59%) — индикатор того, что классификатор парсера часто не находит явной семантики prompt'а. Это не проблема алгоритма — это просто стиль работы за период (короткие нейтральные ходы по правке нормативки и memory).
Episodes → tasks (из tasks анализатора)
11 групп. «turns that are rework» определены как эпизоды, чей _inferredOutcome === 'rework'. Таких 0 в этом периоде.
| task_ref | эпизодов | turns-rework |
|---|---|---|
553717ec…#1 |
1 | 0 |
553717ec…#2 |
2 | 0 |
553717ec…#3 |
1 | 0 |
553717ec…#4 |
3 | 0 |
553717ec…#5 |
1 | 0 |
553717ec…#6 |
1 | 0 |
553717ec…#7 |
2 | 0 |
24acfa10…#8 |
1 | 0 |
a42e4ba5…#9 |
1 | 0 |
dd905ea0…#10 |
1 | 0 |
98298ec2…#11 |
3 | 0 |
Causal-chain candidates (из causalChains)
0 цепочек (анализатор вернул пустой массив).
Это здоровый сигнал: hot-file фильтр (CLAUDE.md / MEMORY.md / STATUS.md / episodes-*.jsonl / memory/*.md) корректно отсекает ложные «А упал на X-файле — через 6 эпизодов Б трогает X-файл». Реальных error→fix цепочек по не-горячим файлам наблюдатель не нашёл, что согласуется с low-error профилем периода (3 error-event'а — все рутинные «tool_result is_error», ни одного unrecovered_error).
Observer health
| метрика | значение | оценка |
|---|---|---|
observerErrorCount |
0 | ✅ зелено — наблюдатель не падал тихо |
v1SkippedCount |
5 | ℹ️ legacy: schema v2 раскатан с 2026-05-19T08:06Z; 5 ранее-утренних эпизодов 19.05 (05:18–06:57) — v1 без environment/prompt_signal/decision_provenance, анализатор их корректно отфильтровал |
retry events |
4 (в 2 эпизодах) | в норме — №6 (1 retry), №14 (2 retry); все восстановлены |
error events |
3 (в 3 эпизодах) | рутинные tool_result is_error; ни одного unrecovered_error (outcome не blocked) |
time_burn events |
1 (19m45s в №22) | большой TDD-эпизод, ожидаемо |
interrupt events |
0 | нет прерываний |
parse_gap events |
0 | парсер не сообщал о пропусках |
confusion_marker events |
0 | парсер не пишет такого вида события за период (ожидаемо; маркеры — поведенческое наблюдение, не tool-event) |
Canonical chains L1–L12 hit rate (предварительно)
Канонические связки описаны в docs/routing-off-phase.md (PSR_v1 R15, Rec4 SYSTEM-аудита). Полная сверка с L1–L12 — задача углубления. Верхнеуровневая оценка:
- Явных L-цепочек 0, так как 88% эпизодов —
direct/improvised, без декларации canonical chain вprimary_rationale.boundaries_appliedилиtriggers_matched. - Возможный L-кандидат в эпизоде №16 (19.05 10:13): связка
superpowers:systematic-debugging→claude-md-management:claude-md-improver— это похоже на «debug-чейн с фиксацией learning'а в CLAUDE.md» (близко к L-связке runtime-debug + infrastructure-edit, но точная маркировка L? — задача углубления). - Возможный L-кандидат в эпизоде №22 (20.05 07:52):
superpowers:test-driven-development→superpowers:verification-before-completion— это классический TDD-чейн (близок к канонической связке для feature-кода).
| chain (предварит.) | times | notes |
|---|---|---|
| TDD → verification | 1 | ep.22 (текущий) |
| systematic-debugging → claude-md-improver | 1 | ep.16 |
| Все остальные L1–L12 | 0 | за период не видно |
Пометка для углубления: считать canonical-chain hit rate не по
skill_invoked-парам (это сильный сигнал, но узкий), а по сочетаниюtriggers_matched+boundaries_appliedperrouting-off-phase.md. Сейчасtriggers_matchedиboundaries_appliedпусты во всех эпизодах — этоprimary_rationaleещё пишется парсером в «минимальном» режиме.
Improvised chains (path_type=improvised, repeated ≥2)
Конкретных повторяющихся «node-set»-цепочек не вижу — большинство improvised-эпизодов либо однотонные (один Edit/Read/Bash-набор по разным memory-файлам), либо изолированы. Зато виден повторяющийся pattern по предметной области:
| pattern (тематический) | эпизодов | candidate L13+? |
|---|---|---|
Self-repair наблюдателя (правки tools/observer-* или docs/observer/*) |
8 из 17 (47%) | нет — это техдолг bootstrap, не повторяющийся бизнес-чейн |
Sync memory/*.md после изменений (особенно project_state.md/reference_github.md) |
3 | нет — это часть «§4.6 self-review» (Pravila) |
Правка CLAUDE.md-секций после нормативных bumps |
2 | нет — закрывается обязательным каналом claude-md-management |
chain_divergence cases
Нет данных — primary_rationale.candidates_considered пуст во всех 17 эпизодах, парсер пока не пишет «рассматриваемые альтернативы». В разделе для углубления — улучшить парсер, чтобы вытаскивать candidate-узлы из текста хода (если такие декларации были в reasoning).
Top error classes
| error class | count | recovery pattern |
|---|---|---|
tool_result reported is_error (рутинный) |
3 | retry внутри хода, без эскалации; outcome не blocked |
unrecovered_error |
0 | — |
interrupt |
0 | — |
Тип-распределение — все три «error»-event'а одинаковые («tool_result reported is_error»). Это значит, что парсер не различает классы ошибок ниже этого уровня (известное ограничение — A-1 fix в inferOutcome).
confusion_marker hot-spots
Нет данных. confusion_marker — это event, который должен писаться парсером при обнаружении паттернов сомнения в reasoning Claude. За период парсер не зарегистрировал ни одного → либо подобного не было, либо паттерн распознавания пуст (см. Кандидаты ниже).
Candidates for owner review
Все кандидаты ниже — предложения, не действия. Заказчик решает, какое (если вообще) применить.
Candidate 1: «Self-repair наблюдателя» — 47% периода, в норме для bootstrap-фазы
- Тип: наблюдение, не изменение нормативки.
- Evidence: 8 из 17 эпизодов трогали
tools/observer-*илиdocs/observer/*(эпизоды 6, 13, 14, 16, 20, 22 + два косвенно). Episodes-2026-05.jsonl touched в эпизодах 14, 20. Самый «толстый» — №22: 56 tool_calls, 11 файлов, 19m45s — TDD-починка парсера/STOP-хука/PII-фильтра/coverage-checker. - Чтение: мозг сейчас в фазе самовосстановления (brain governance Phase A/B/C закрыта 19.05 + factor-analysis extension + phase 1.1 — это всё out-of-feature work, инструментальный долг). После того как Phase C завершит «стабилизацию» (lefthook jobs 11–15 работают, observer-of-observer 54w self-prune, STATUS.md generator) — % должен опуститься.
- Suggested action: не вмешиваться. На следующем ретро сравнить % «self-repair» эпизодов; если останется ≥40% при больших n — это будет сигнал к делегации (например, выделить наблюдатель в фоновый daemon, чтобы не отъедал tool-budget основного Claude).
- Cost / risk: 0 сейчас; ~0 на следующем ретро.
Candidate 2: «Direct path 88%» — здоровый низкий уровень regulated/skill-инвокаций, но требует контроля
- Тип: наблюдение + предложение по парсеру.
- Evidence: только 2/17 эпизодов проходят через hard-floor §12 (
primary_rationale.hard_floor.invoked=true). Остальные 15 —direct. При этом из 15 ни один не упомянулboundaries_appliedилиtriggers_matched(пустые массивы во всех 17 эпизодах). - Гипотеза: парсер пока не вытаскивает «незакрытые» triggers/boundaries — он пишет только явные
skill_invokedevents. Это значит, что мы не видим, сколько раз §12.2 карта могла бы trigger'нуть skill, но Claude пошёл direct. Без этого нельзя различить «direct правильно (не было триггера)» и «direct неправильно (был триггер, проигнорирован)». - Suggested action: в углублённой фазе обсудить расширение парсера так, чтобы он подсвечивал «потенциальные триггеры» (например, факт чтения
superpowers/skills/<x>/SKILL.mdбез последующегоskill_invoked, или Bash-команд, типаgitleaks/pest/vitest, не обёрнутых вverification-before-completion). Это превратит «не видим, шёл ли мозг мимо карты» в реальную метрику. - Cost / risk: парсер изменения ≈ 1 рабочий день; риск ложных alert'ов — мерится по follow-up ретро.
Candidate 3: Паттерн «post_compaction → user_directed_method 3×»
- Тип: наблюдение + кандидат на memory-фидбэк.
- Evidence: 3 из 3 эпизодов с
user_directed_method— на turn 83, 84, 87 одной сессии сразу после post_compaction=true (компакция была между turn 82 и 83). Заказчик навязал:subagent-driven-development(×2) иbrainstorming(×1). - Чтение: post-compaction Claude теряет «свежее» направление из последних 5–10 ходов; заказчик это компенсирует, явно указывая метод. Это не bug, это компенсация известного quirk.
- Suggested action: возможный новый memory-факт типа
feedback_post_compaction_router_recovery.md— «после<context_compaction>-маркера ход N+1 часто требует явной маршрутизации заказчиком; не сопротивляться»; либо расширить уже существующееfeedback_post_compaction_loss.md(если есть). Решает заказчик. - Cost / risk: 1 memory-файл / 10 строк; риск нулевой.
Candidate 4: 5 v1-эпизодов 19.05 утра — archive или конверсия
- Тип: инфраструктурное предложение.
- Evidence: эпизоды 1–5 в JSONL (05:18–06:57) — без
schema_version. Анализатор тихо их пропускает (v1SkippedCount=5). Они есть в файле, но не участвуют в факторном анализе. - Чтение: schema v2 раскатан с 08:06 (после первой утренней работы); до этого парсер записал v1-сырьё (path_type, outcome, primary_rationale, events — без
environmentиdecision_provenance). Один из них (эпизод 5, 06:32) — большой (Read:17, Grep:14, Glob:5— это явно дебаггер где-то). - Suggested action: возможный конвертер v1→v2 с заполнением неизвестных полей null (как делает анализатор) либо архивный suffix-файл (
episodes-2026-05.v1-archive.jsonl). Сейчас оба варианта живы в одном файле без помех. - Cost / risk: 0 если оставить; ~2 часа если делать конвертер.
Candidate 5: confusion_marker / parse_gap / unrecovered_error — все по 0 за период
- Тип: валидационное замечание парсера.
- Evidence: в JSONL 17 v2-эпизодов; ни в одном нет
confusion_marker,parse_gap,unrecovered_error,interrupt. Толькоtool_summary/error(3) /retry(2 ep'а) /hook_fired/skill_invoked/Stop/time_burn. - Чтение: возможны 2 объяснения: (a) парсер ещё не реализовал распознавание этих 4 kind'ов (или реализовал, но их паттерны были слишком строгие за период); (b) период действительно был чистым.
- Suggested action: в углублённой фазе провести «red-team тест» парсера на синтетических примерах:
- Намеренная неисправимая ошибка → должен записаться
unrecovered_error; - Намеренная фраза «не уверен» / «может быть» в reasoning → должен записаться
confusion_marker; - Намеренный пропуск (assistant сообщение с пустым tool_use_id) → должен записаться
parse_gap; - Пользовательский
[ESC]→ должен записатьсяinterrupt.
- Намеренная неисправимая ошибка → должен записаться
- Cost / risk: небольшое (5–10 синтетических transcript-фикстур); риск нулевой.
Candidate 6: candidates_considered / triggers_matched / boundaries_applied всегда пусты
- Тип: наблюдение по полноте
primary_rationale. - Evidence: во всех 17 v2-эпизодах эти три массива —
[]. Толькоnode_chosenиtask_classificationзаполнены. - Чтение: парсер пишет только финальное решение, не аргументацию. Это известный gap (см. spec §6 «routing_decision события»).
- Suggested action: в углублённой фазе спроектировать парсер-расширение, которое:
- Извлекает declared triggers из preamble assistant-сообщения (например, «триггеры: TDD на код / debug-задача»);
- Извлекает candidates_considered из текстов вида «варианты: brainstorming / subagent-driven» или AskUserQuestion-options;
- Извлекает boundaries_applied из явных упоминаний ADR/Pravila §N.
- Cost / risk: среднее; есть риск false-positives — закрывается тестами на zachrest-фикстурах.
Candidate 7: NLP-фактор «task_classification=other 59%»
- Тип: наблюдение по классификатору.
- Evidence: 10 из 17 (59%) —
other.bugfix1,refactor2,feature3,question2, остальныеother. - Чтение: классификатор парсера задаёт grobые корзины. «Other» становится свалкой для «короткие memory-edit'ы», «диалоговые ответы», «нормативные правки», «обновление эталона», «проверка состояния» и т.п.
- Suggested action: в углублённой фазе подумать о расширении classifier-словаря (например, добавить
docs-edit,memory-sync,state-check,regulatory-bump). Это уменьшит «other»-bucket и сделает факторный анализ острее. - Cost / risk: 1 рабочий день парсер-правок; риск ошибок классификации — мерится по retro.
Informational metrics (NOT alerts)
- Узлов реестра использовано как минимум 1 раз за период: 4 (
superpowers:systematic-debugging,superpowers:test-driven-development,superpowers:verification-before-completion,claude-md-management:claude-md-improver) из 60+ формализованных позиций (канон счётчиков —docs/Tooling_v8_3.md§0). - Узлов реестра не использовано ни разу: ~56+ из 60+. Это не проблема per
feedback_brain_unused_tools_not_problem(память). Capability-readiness — осознанная стратегия заказчика. - Hot-files (по
task_size.files, с дедупом):CLAUDE.md(3 раза),project_brain_governance_design.md(3),reference_github.md(3),episodes-2026-05.jsonl(2),2026-05-19-observer-factor-analysis-design.md(2),tools/observer-transcript-parser.mjs(2), tools/observer-transcript-parser.test.mjs (2). Остальные 30+ файлов — один раз. - Самый длинный эпизод: №22 (20.05 07:52 → 08:12, 19m45s, 56 tool_calls, 11 файлов, TDD-починка наблюдателя, regulated path).
- Самый короткий эпизод: №2 (19.05 06:07–06:08, 1m, 0 tool_calls — диалоговый ответ).
Что не делалось в этом ретро (явные ограничения)
- Не сверял с
docs/routing-off-phase.mdL1–L12 канонические связки — пометил для углубления. - Не читал v1-эпизоды для извлечения качественных уроков — анализатор их пропускает по конструкции, но сами факты в них есть (особенно ep.5 — большой Read+Grep дебаг-эпизод 19.05 06:32).
- Не оценивал latency хуков — данные есть (
hook_fired.counts), но требуют отдельной агрегации с переводом в миллисекунды (нет timestamp'ов on per-hook basis в JSONL). - Не запускал других контролёров C1–C5 для cross-check'а (l1-watcher / cross-ref-checker / observer-of-observer / coverage-checker) — это lefthook-jobs 11–15, не /brain-retro responsibility.
- Не правил никакую нормативку — read-only, как требует procedure step 7.
- Не делал predictions — данных n=17 категорически мало для статистически значимых выводов; всё, что я выше отметил как «корреляция» — это либо артефакт выборки, либо описательное наблюдение.
Подпись и провенанс ретро
Анализатор — tools/brain-retro-analyzer.mjs (commit e6d6bab в текущем checkout).
Шаблон — .claude/skills/brain-retro/references/aggregation-template.md.
Read-counter — обновлён до last_read_at=2026-05-20T11:25:00+03:00, read_count_last_period=1.
Эта нота — read-only вывод; никакая нормативная правка не выполнена.
АДДЕНДУМ — углубления по 5 разделам (по запросу заказчика, экономия 5%)
Закрытие 5 явных gaps, отмеченных в верхнеуровневом отчёте. Read-only, никаких правок нормативки. Данные собраны 2026-05-20 ≈11:35 MSK.
A. L1–L12/L13 классификация двух regulated-эпизодов
Источник истины — docs/routing-off-phase.md v1.2 (20.05.2026, 12 канонических + L13 finance-tooling).
Эпизод №16 (2026-05-19T10:13Z, 19m, regulated, opus-4-7):
skill_invoked:superpowers:systematic-debugging+claude-md-management:claude-md-improver.- Файлы:
tools/observer-transcript-parser.{mjs,test.mjs}+CLAUDE.md+ transcript-jsonl сессии. - Сверка с L1–L13:
- L8 (
systematic-debugging + Sentry + Redis) — частично:systematic-debuggingбыл invoked, но Sentry/Redis MCP не использовались (баг был в локальном tool-коде, не в production runtime). - L12 (
claude-md-management + revise-claude-md) — частично:claude-md-improverinvoked. Это один из двух entry-skill'ов L12./claude-md-management:revise-claude-mdв этом эпизоде не вызывался (improver делал targeted update CLAUDE.md, не capture session-learnings).
- L8 (
- Вердикт: эпизод не маппится 1:1 на каноническую L-связку. Это гибрид Pravila §12.2 hard-floor (systematic-debugging при unexpected behavior) + §5 п.10 обязательного канала (правка CLAUDE.md только через claude-md-management). Оба правила вне off-phase routing → L1–L13 не покрывают такую цепочку by design (off-phase routing не дублирует Pravila §12.2/§5 п.10 hard-rules — это явно в routing-off-phase §11.5 «Hard-rules перевешивают routing-аид»).
Эпизод №22 (2026-05-20T07:52Z, 19m45s, regulated, opus-4-7):
skill_invoked:superpowers:test-driven-development+superpowers:verification-before-completion.- Файлы: 11
tools/observer-*+.gitleaks.toml(test-fixture seam с false-positive). - Сверка с L1–L13: ни одна L-связка off-phase routing не покрывает «TDD + verification». L1–L13 — это off-phase инструменты (#31–#63), TDD/verify — это Pravila §12.2 hard-floor (Superpowers). Тоже не дублируется в routing-аиде.
- Вердикт: чистый Pravila §12.2 hard-floor двух skill'ов в одной задаче («TDD на любой код» + «verification перед claim 'готово'»). L-маркировка неприменима.
Сводный вывод по A: Из 17 v2-эпизодов 0 канонических L-связок off-phase сработало. Все 2 regulated-эпизода прошли через Pravila §12.2 hard-floor (skill из обязательной карты §12.2), не через каноническую цепочку L1–L13. Это здоровый сигнал: за период не было задач, попадающих в off-phase кейсы (ML-эпик, security-аудит, финансы, BPMN, ADR — ни одного). Все turn'ы — самообслуживание наблюдателя и правки нормативки/memory.
| chain | times | вердикт |
|---|---|---|
| L1 discovery→brainstorm→writing-plans→subagent-driven | 0 | за период не было фич, требующих full discovery loop |
| L2 discovery (SYSTEM) + audit-portal | 0 | не был audit-режим |
| L3 process-analysis ↔ process-modeling | 0 | не было процесс-задач |
| L4 mermaid ← adr-kit/process-modeling/operations | 0 | не было новых диаграмм |
| L5 adr-kit + architecture-patterns + deptrac | 0 | не было новых ADR |
| L6 security слой 4 узла | 0 | не было security-эпиков |
| L7 openapi-mcp + api-docs + Boost | 0 | не было API-интеграций |
| L8 systematic-debugging + Sentry + Redis | 0 (но partial в ep.16) | debug по локальному tool-коду; Sentry pending Б-1 |
| L9 CCPM + product-management + GitHub MCP | 0 | не было новых эпиков |
| L10 promptfoo + Data Scientist + claude-api | 0 | не было LLM-фич |
| L11 skill-creator + hookify + plugin-dev | 0 | не было новых скилов/хуков |
| L12 claude-md-management + revise-claude-md | 0 (partial в ep.16) | improver, не revise |
| L13 billing-audit + Pest + Boost + Sentry/Redis → ru-tax | 0 | finance-tooling узлы введены только 20.05 |
B. Уроки из 5 v1-эпизодов 19.05 утра (05:18–06:57)
Анализатор пропускает v1 (нет schema_version=2), но фактический контент в JSONL
есть. Сводка (по содержанию эпизодов 1–5 из episodes-2026-05.jsonl):
| ep | старт | длит. | path | outcome | task_class | tool-нагрузка | сигнал |
|---|---|---|---|---|---|---|---|
| 1 | 05:18:16 | 47m 39s ⚠️ | improvised | success | refactor | AskUserQuestion×5, TodoWrite×2 | «refactor planning через множественные ветки выбора с заказчиком». Самый длинный эпизод всего периода. |
| 2 | 06:07:06 | 1m 15s | improvised | success | other | 0 tool_calls | диалоговый турн (ответ без действий). |
| 3 | 06:10:13 | 5m 58s | improvised | success | other | Write×1, Bash×2, Edit×3, TodoWrite×1, 1 error | мелкая правка с одной recovered ошибкой. |
| 4 | 06:20:40 | 2m 28s | improvised | success | other | Bash×2, Read×1, Edit×2 | чистая short-edit задача. |
| 5 | 06:32:15 | 24m 47s ⚠️ | improvised | success | bugfix | Read×17, Grep×14, Glob×5, ToolSearch×1, TodoWrite×4, Write×1 | debug-эпизод через интенсивную навигацию без skill_invoked. |
Качественные уроки:
-
Ep.1 (47m, refactor planning) — массовое использование AskUserQuestion (5 раз за один турн). Это classic-паттерн «дерево вариантов с заказчиком» без
superpowers:brainstormingskill'а — Pravila §16 (brain governance) с обязательным routing-gate был ещё не enforced на этот момент (Phase A/B/C закрыты commit'ами2ef4ac4/4382de3/a70d5a4именно 19.05). Поэтому §12.2 ещё не флагировал «brainstorm-задачу без skill'а». Не violation по правилам на момент турна. -
Ep.5 (24m, bugfix через 17 Read + 14 Grep + 5 Glob) — самый показательный урок: классический debug-эпизод (поиск по огромному файловому surface) прошёл
direct, безsuperpowers:systematic-debugging. Сейчас (после раскатки v2 schema + Stop-хук routing-gate с 08:06 того же дня) такой эпизод флагировался бы какdecision_provenance.kind=autonomous+node_chosen=directпри bugfix-классификации → именно тот сигнал, который Phase B/C поднимала. В v1 мы видим факт без сигнала. -
Ep.2 (1m, 0 tool_calls) — короткий диалоговый turn'а полезен как baseline minimum для калибровки «что значит epizod с 0 tools»: это просто текстовый ответ. Это согласуется с фактом, что парсер пишет эпизод на каждый Stop, не только на «значимые» (важно для статистики покрытия).
-
Все v1 outcome=success написаны парсером напрямую, не inferred next-prompt sentiment'ом (как делает анализатор для v2). Это значит: v1 outcome ненадёжен для сравнения с v2 — там «success» это «не упал», а в v2 «success» это «next prompt был approval/new_task». Разные семантики.
-
Историческая важность: ep.1 + ep.5 показывают, что brain governance был реальным улучшением, а не косметикой — два паттерна (5×AskUserQuestion без brainstorm + bugfix без systematic-debugging) теперь видимы в v2-данных.
Кандидат-наблюдение (НЕ действие): не конвертировать v1→v2 ретроактивно — это
введёт ложные decision_provenance=autonomous метки в данные периода, когда
routing-gate ещё не работал. Лучше оставить v1 как v1SkippedCount=5 для
прозрачности bootstrap-эпохи.
C. Latency-замер: tool round-trip из транскрипта 553717ec
Источник: ~/.claude/projects/.../553717ec-bf55-43dc-8b9c-b9812711023a.jsonl
(22 400 строк, 68.7 МБ; вся сессия 19.05 — 5h+, 24-25 турнов).
Метод: для каждого tool_use_id в assistant.content нашёл соответствующий
tool_result в следующих user.content блоках; разница timestamp = round-trip
latency (включает hook overhead + network + tool execution + Claude reply parsing).
Outliers ≥600 000ms отброшены. N=2857 tool-roundtrip'ов по 14 разным tools.
| tool | n | p50 (ms) | p90 (ms) | p95 (ms) | p99 (ms) | max (ms) | чтение |
|---|---|---|---|---|---|---|---|
| Bash | 932 | 2491 | 13 489 | 17 251 | 48 746 | 114 335 | включает время самих команд (compose/pest/lefthook) |
| Read | 586 | 444 | 736 | 876 | 11 873 | 11 873 | IO-only, близко к hook floor |
| Edit | 554 | 1401 | 1516 | 1674 | 5173 | 48 927 | +1s vs Read — тяжёлый PostToolUse-pipeline |
| TodoWrite | 237 | 400 | 459 | 526 | 602 | 731 | in-memory list-state, тоньше всех — почти чистый hook floor |
| Write | 125 | 1400 | 1661 | 5401 | 31 531 | 31 531 | тот же PostToolUse-pipeline что Edit |
| Grep | 119 | 492 | 605 | 998 | 2914 | 2914 | ripgrep IO + parse |
| Agent | 107 | 135 883 | 213 723 | 263 840 | 387 336 | 387 336 | время субагентов, не hook overhead |
| AskUserQuestion | 69 | 50 064 | 323 325 | 534 449 | 534 449 | 534 449 | время реакции заказчика |
| Skill | 52 | 485 | 825 | 875 | 941 | 941 | скил-load |
| Glob | 32 | 12 690 | 20 265 | 20 265 | 20 265 | 20 265 | неожиданно медленно (большие patterns?) |
| ToolSearch | 27 | 394 | 457 | 457 | 518 | 518 | in-memory схема-резолв |
| PowerShell | 9 | 2365 | 2600 | 2600 | 2600 | 2600 | время команды PS |
| EnterPlanMode | 4 | 436 | 436 | 436 | 436 | 436 | вход в plan-mode |
| ExitPlanMode | 4 | 92 988 | 92 988 | 92 988 | 92 988 | 92 988 | время согласования плана заказчиком |
| ALL | 2857 | 1317 | 13 515 | 50 064 | 204 784 | 534 449 | overall |
Выводы по latency:
- Hook floor ≈ 400–500ms — это p50 для «легчайших» tools (TodoWrite 400, ToolSearch
394, EnterPlanMode 436, Read 444, Grep 492, Skill 485). Эти tools делают минимум
работы своих, поэтому 400–500ms — это network round-trip (~150ms) + hook chain
(~250–350ms). Конкретнее: CLAUDE.md шапка v2.17 упоминала «B4 latency-замер хуков
закрыт (~34 мс median/хук)» (memory
feedback_superpowers_hard_rule.md); при ~6–8 хуков на tool × 34ms ≈ 200ms — совпадает с порядком оценки. - Edit/Write — самые «дорогие» легковесные tools (p50 ~1400ms), то есть +~1s
к hook floor TodoWrite (400ms). Этот +1s — это PostToolUse-цепочка для
write-операций:
markdownlint --fix(если .md),gitleaks protect --staged(если staged), плюс возможно l1-watcher (если settings.json/Tooling). Это информативно, не алерт. - Bash p50 = 2.5s, p99 = 49s — нормально для команд с собственной работой (composer/pest/lefthook). Hook overhead — лишь ~500ms из этого.
- Glob p50 = 12.7s — аномалия: ripgrep-glob делается быстро (msec); 12s
на p50 указывает на тяжёлые patterns (
**/*через большие subagent-каталоги в~/.claude/projects/). См. кандидат C-1 ниже. - AskUserQuestion / ExitPlanMode — медианы 50s и 93s — это реальное время реакции заказчика, не hook'и. Это полезная метрика UX-задержки: за период ~7% времени Claude тратится в ожидании ответа заказчика.
Кандидат C-1 (НЕ действие): Glob с p50=12.7s — посмотреть, не запускается ли
Glob на огромных subagent-логах ~/.claude/projects/.../subagents/*/*.jsonl
(их там 100+). При следующем углублении — отфильтровать patterns по
содержанию и проверить.
Кандидат C-2 (НЕ действие): Edit p99 = 48s, max 48.9s — один эпизод где PostToolUse-цепочка зависла (вероятно gitleaks при огромном diff). Точечная investigation потенциально полезна, но n=1, можем ждать повторения.
D. N=17 — план «когда меряем фактор-анализ серьёзно»
Текущий лимит: 17 v2-эпизодов недостаточно для статистически значимых
заключений. «Корреляции» в верхнеуровневом отчёте (post_compaction / session_turn /
parallel_session) — артефакты выборки.
Минимально достаточно для serious factor-analysis:
| фактор | минимальная выборка для p<0.05 (одна ячейка матрицы) | оценка времени накопления |
|---|---|---|
decision_provenance (3 значения × 4 outcome) |
n≥120 эпизодов (≥10 в каждой ячейке) | при текущем темпе ~17 эп/неделя — ~7 недель |
economy_level (4 × 4) |
n≥160 | ~9 недель |
model (нужно ≥2 модели, сейчас только Opus) |
требует Sonnet/Haiku-эпизодов | возникнет с subagent-driven-development в claude_would_have_chosen |
post_compaction (2 × 4) |
n≥80 | ~5 недель |
parallel_session (2 × 4) |
n≥80 | ~5 недель |
node_chosen (тонкий хвост) |
n≥300 | ~17 недель |
Практическая рекомендация: следующее brain-retro имеет смысл проводить не раньше чем через 4–6 недель (или ~80–100 v2-эпизодов). До этого аккумулировать данные. Если заказчик хочет интервалы — еженедельные «лёгкие» ретро (только Observer health + path-type + L-chains) без полной матрицы.
Текущее накопление 1× /brain-retro — это baseline-замер, не factor-analysis.
E. Cross-check контролёров C1–C5 — все GREEN
Запущено вручную параллельно (lefthook jobs 11–15 + post-commit job 14):
| контролёр | команда | exit | результат |
|---|---|---|---|
| C1 l1-watcher (job 11) | node tools/l1-watcher.mjs |
0 | OK — 0 drift (settings.json ↔ Tooling Прил. Н sync) |
| C2 cross-ref-checker (job 12) | node tools/cross-ref-checker.mjs |
0 | OK — 0 drift in 4 files (Pravila / PSR_v1 / Tooling / CLAUDE.md / MEMORY.md cross-refs) |
| C3 observer-of-observer (job 13) | node tools/observer-of-observer.mjs check |
0 | OK — last read 0 week(s) ago (я только что обновил read-counter; 54-week pre-prune защита не сработает) |
| C4 status-md (post-commit) | node tools/status-md-generator.mjs |
0 | пересоздал docs/observer/STATUS.md (новый timestamp 2026-05-20T08:31:22.723Z) |
| C5 observer-coverage (job 15) | node tools/observer-coverage-checker.mjs |
0 | OK — 24 episode(s) this month · Stop-hook + post-commit OK |
Расхождение с anal'изером: C5 сейчас видит 24 эпизода, мой анализатор (запущенный в начале ретро) обработал 22. Дельта = 2 — это эпизоды, которые Stop-хук записал ЗА ВРЕМЯ выполнения брейн-ретро (моя текущая сессия 98298ec2, turns 1–2 после начала ретро). Не дрейф: это нормально (наблюдатель пишет в реальном времени).
STATUS.md обновлён и показывает все 5 контролёров ✅. Если бы один из них flag'нул — после следующего git commit (post-commit hook job 14) STATUS.md auto-обновился бы; обходного канала не нужно.
Кандидат E-1 (НЕ действие): rerun node tools/brain-retro-analyzer.mjs docs/observer/episodes-2026-05.jsonl через несколько турнов / в конце сессии —
факторная матрица станет на 1–2 эпизода полнее. Имеет смысл встроить в
сам /brain-retro skill «final pass перед save» — кандидат для углублённой
итерации скила.
Итог по углублениям
| # | Раздел | Status | Главное наблюдение |
|---|---|---|---|
| A | L1–L12/L13 hit rate | ✅ verified | 0 канонических связок отработало; оба regulated-эпизода — чисто Pravila §12.2 hard-floor |
| B | v1-эпизоды (5 шт.) | ✅ verified | brain governance enforcement добавляет видимость — два showcased паттерна (ep.1 без brainstorm, ep.5 без systematic-debugging) теперь были бы флагированы |
| C | latency-замер | ✅ verified | hook floor ≈ 400–500ms; Edit/Write +~1s; Bash p50=2.5s; Glob аномально 12.7s (потенциальная investigation) |
| D | N=17 → план серьёзного анализа | ✅ verified | следующее полное ретро через ~5–7 недель (80–100 v2-эпизодов) |
| E | C1–C5 cross-check | ✅ verified | все 5 контролёров GREEN, STATUS.md обновлён, расхождение «22 vs 24» — Stop-хук пишет в реальном времени |
Файлы, тронутые в этом углублении: только docs/observer/notes/2026-05-20-brain-retro.md
(этот же файл, аддендум) + docs/observer/.read-counter.json (на step 4 базовой части) +
docs/observer/STATUS.md (через C4 status-md generator). Никаких изменений в нормативке,
коде, тестах.
АДДЕНДУМ B — пре-имплементационные верификации (по запросу заказчика, экономия 5%)
Закрытие 3 actionable «не верифицировал» из ответа-обзора 19 пунктов «что улучшить в наблюдателе». Read-only verification над реальными артефактами; никакого кода не правил; никакая нормативка не тронута.
B1. message.usage в Claude Code transcript — присутствует, формат подтверждён
Метод: grep -c '"usage"' + sample первых 3 occurrences по реальному transcript
~/.claude/projects/.../553717ec-bf55-43dc-8b9c-b9812711023a.jsonl (сессия 19.05, 22 400 строк, 68.7 МБ).
Результат:
-
6 372 occurrences в одной сессии.
-
Формат фиксированный (наблюдался идентичный во всех 3 samples):
"usage": { "input_tokens": 2, "cache_creation_input_tokens": 107333, "cache_read_input_tokens": 32087, "output_tokens": 4518, "server_tool_use": { "web_search_requests": 0, "web_fetch_requests": 0 } }
Импликации для рекомендации #2 «token-usage capture»:
- Все 4 поля, которые я предлагал захватывать (
input_tokens/output_tokens/cache_read_input_tokens/cache_creation_input_tokens) — подтверждены присутствующими. Реализация безопасна. - Bonus-фактор обнаружен:
server_tool_use.web_search_requests+server_tool_use.web_fetch_requests— счётчики использования server-side инструментов (WebSearch / WebFetch). Можно добавить вtask_costкак доп. фактор «использовал ли web-инструменты».
Уточнённая спецификация #2:
export function extractTokenUsage(turn) {
let input=0, output=0, cache_read=0, cache_creation=0, web_search=0, web_fetch=0;
for (const e of turn) {
const u = e?.message?.usage;
if (!u) continue;
input += u.input_tokens || 0;
output += u.output_tokens || 0;
cache_read += u.cache_read_input_tokens || 0;
cache_creation += u.cache_creation_input_tokens || 0;
web_search += u?.server_tool_use?.web_search_requests || 0;
web_fetch += u?.server_tool_use?.web_fetch_requests || 0;
}
return {
input_tokens: input,
output_tokens: output,
cache_read_input_tokens: cache_read,
cache_creation_input_tokens: cache_creation,
web_search_requests: web_search,
web_fetch_requests: web_fetch,
};
}
B2. attachment.type структура — hook_success подтверждён, hook_error 0 occur
Метод: grep по "attachment":{...} + по полям type / hookName.
Результат:
- 11 685 occurrences
"attachment"в той же сессии. - Виды type, встреченные:
hook_success✅ +hook_additional_context+deferred_tools_delta+queue-operation. hook_error= 0 occurrences во всей сессии 5h+.- Структура
hook_success:
"attachment": {
"type": "hook_success",
"hookName": "SessionStart:startup",
"toolUseID": "12a033f0-...",
"hookEvent": "SessionStart",
"content": "",
"stdout": "{ ... }"
}
Импликации для парсера (parser.mjs:295-300):
- Код парсера корректен — он матчит на
attachment.type === 'hook_success' || 'hook_error'.hook_successприходит;hook_errorимеет 0 occurrences, потому что хуки физически не падали за период. Парсер пишетerrors: 0вhook_firedevent — это здоровый сигнал, не bug. - Уточнение к будущей правке per-hook timing: в
attachment.hook_successнет полейstarted_at/ended_at— per-hook timing не извлекаем из transcript напрямую. Требуется инструментация самих хуков (записывать timestamp вstdoutили внешний log). Это vendoring или fork хука, нетривиально. Рекомендация: оставить per-hook timing out-of-scope для текущего раунда; ограничиться tool-round-trip latency (как делал в C-аддендуме первой части ноты через timestamp diff междуtool_useиtool_result). - Дополнительные attachment-типы (
hook_additional_context/deferred_tools_delta/queue-operation) — НЕ обрабатываются парсером, и это OK: они информационные, не connect'ятся к hook execution.
Дополнительная находка: attachment.toolUseID присутствует в hook_success —
связывает hook с конкретным tool_use. Если эта связь сохранится и в hook_error
(когда таковой появится), можно атрибутировать ошибку хука к конкретному tool, не
только к hook-name. Это future capability, не текущая правка.
B3. tools/observer-*.test.mjs — 232/232 GREEN
Метод: cd app && npx vitest run --config vitest.config.tools.mjs --reporter=verbose.
Раннер найден в app/vitest.config.tools.mjs:
include: ['../tools/*.test.mjs'],
exclude: ['../tools/ruflo-*.test.mjs', '../tools/subagent-prompt-prefix.test.mjs'],
Результат:
Test Files 13 passed (13)
Tests 232 passed (232)
Start at 11:49:45
Duration 1.21s (transform 1.11s, setup 0ms, import 1.82s, tests 350ms, environment 4ms)
13 тестовых файлов:
| Файл | Покрывает |
|---|---|
brain-dashboard-core.test.mjs |
Brain Dashboard UI logic (19 тестов) |
brain-retro-analyzer.test.mjs |
Анализатор этого скила (15) |
cross-ref-checker.test.mjs |
C2 контролёр (14) |
l1-watcher.test.mjs |
C1 контролёр (12) |
observer-coverage-checker.test.mjs |
C5 контролёр (8) |
observer-of-observer.test.mjs |
C3 контролёр (5) |
observer-pii-filter.test.mjs |
PII фильтр (15) |
observer-routing-detector.test.mjs |
Routing-gate детектор (8) |
observer-stop-hook.test.mjs |
Stop-hook + appendEpisode + routingGateDecision (18) |
observer-transcript-parser.test.mjs |
Парсер транскрипта — главный (53) |
status-md-generator.test.mjs |
C4 генератор (5) |
| + 2 ещё через include glob | ~60 (subtotal до 232) |
Импликации:
- Текущая observer-инфраструктура стабильна: 232 теста за 1.21 сек, 0 регрессий.
- Любая правка из рекомендаций #1–#19 имеет прочную регрессионную сеть — добавлять тесты на расширения, не трогая существующие.
- Раннер закрепляется как канонический способ запуска tools-тестов:
cd app && npx vitest run --config vitest.config.tools.mjs.
Кандидат B3-1 (новая микро-правка): добавить в корневой package.json одну строку:
"test:tools": "cd app && npx vitest run --config vitest.config.tools.mjs"
Это отдельная микро-правка, не часть рекомендаций #1–#19; стоимость 1 минута;
ROI — улучшение DX (тесты tools/* найти теперь сложно без чтения source-кода
конфига).
Сводка по верификациям
| # | Что проверял | Результат | Влияние на рекомендации |
|---|---|---|---|
| B1 | message.usage структура |
✅ 6372 occur, формат подтверждён + bonus server_tool_use фактор |
#2 token-usage capture — реализуема, спека уточнена с web_search/web_fetch |
| B2 | attachment.type='hook_success'/hook_error |
✅ hook_success есть; hook_error 0 occur (хуки не падают) | парсер корректен; per-hook timing требует инструментации хуков (out of scope) |
| B3 | tools/observer-*.test.mjs запуск |
✅ 232/232 GREEN за 1.21s | прочная регрессионная сеть; новые правки безопасны |
0 регрессий, 0 правок кода/нормативки. Готов реализовать рекомендации #1–#19 (любые) — заказчик решает, какие применить и в каком порядке.