Period 2026-05-24T00:00Z..2026-05-26T13:18Z (~61h, 317 episodes). Processed 132 unreviewed episodes via brain-retro-batch-reviewer.mjs (Opus 4.7 / ProxyAPI, 293.6s, 0 errors). Coverage 100% (316/316), up from 91% in retro #5. Findings: - rework 10.4% (33/316), stable vs retro #5 (11.4%) - 132 episodes (41.6%) with gap «recommended, picked direct» — but 60-70% turned out to be silent regex-fallback false-positives (fixed in follow-up commit). - rework by group: skill_used 12.0% | direct_no_rec 2.5% | direct_ignored_rec 22.7% — delta 20.2 п.п. - user_chose_from_options: 0% rework / 0% blocked on 55 episodes — brainstorm-pattern is the strongest quality mechanism. - 85% episodes без self_assessment — owner подтвердил «бежал слишком быстро без остановки» (material signal). Artefacts: - docs/observer/notes/2026-05-26-brain-retro-6.md (25KB) - docs/observer/sanity-checks/2026-05-26-brain-retro-6.json - STATUS.md regen (C5 488 episodes, missed_activations=21) - read-counter + self-retrospect-counter bumped (519 since last) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
24 KiB
Brain-retro #6 — full reviewer pass + sanity signal
Дата: 2026-05-26 (~19:10 MSK).
Период: 2026-05-24T00:00Z .. 2026-05-26T13:18Z (~61 часов, 317 эпизодов).
Аналитик: node tools/brain-retro-analyzer.mjs docs/observer/episodes-2026-05.jsonl + tools/brain-retro-batch-reviewer.mjs (limit=200, conc=5, 293.6s wall-clock).
Уровень анализа: полный (analyzer + reviewer + sanity).
Отношение к предыдущему ретро: надстройка над 2026-05-26-brain-retro.md (retro #5 cutoff 2026-05-26T05:09Z) — закрыл 132 непроверенных эпизода (18 errors-retry из retro #5 + 114 новых после 05:09Z).
episodeCount=482(весь май, analyzer dedup),reviewed=316/316=100%(в окне периода),observerErrorCount=0,pending=1(один edge-case без review). Reviewer-проход полный — 0 errors, 0 API сбоев против 18 в retro #5.
Period & context
61 час между retro #5 (~08:20 MSK 26.05) и retro #6 (~19:10 MSK 26.05). Главные события: брейнсторм с вебмастером К1+К2 финализирован (К3-К7 на паузе до фикса baseline-бага LeadRouter), supplier-snapshot-guard выкачен на боевой ~09:55 UTC, enforce-hard-rules holes 1-9 закрыты (1 hotfix 165f1ed9), Phase 2 FK-violation hotfix, билет «изменить баланс через UI» закрыт через админку.
Заказчик попросил /brain-retro после явного указания «хочу с 24.05 но посмотри ревью мы делали частично, прогони тех что не хватает». 132 непроверенных эпизода — это residue retro #5 (18 errors) + всё что копилось после её cutoff.
Macro метрики vs retro #5
| метрика | retro #5 (40h) | retro #6 (61h) | дельта |
|---|---|---|---|
| эпизоды | 202 | 317 | +115 (плотнее на 61h: 5.2 → 5.2 эп/час, одинаково) |
| path_type regulated | 4.5% | 7.3% (23/317) | +2.8 п.п. ↗ (восстановление) |
| skill-инвокации | 10 (5%) | 23 (7.3%) | +2.3 п.п. ↗ |
| reviewer coverage | 91% (184/202) | 100% (316/316) | +9 п.п. (errors 18→0) |
| reviewer rework rate | 11.4% (21/184) | 10.4% (33/316) | −1 п.п. (стабильно высоко) |
| node_quality wrong_node | 9.2% (17/184) | 9.1% (29/316) | стабильно |
| node_quality correct | 30.4% | 32.8% (104/316) | +2.4 п.п. ↗ |
| node_quality disputable | 58.7% | 56.5% (179/316) | −2 п.п. |
| no_self_assessment | 85.0% | 85.0% (270/317) | стабильно ⚠️ |
| observer_error | 0 | 0 | стабильно |
Чтение:
- ↗ Регулированность чуть подросла (4.5% → 7.3%) — это всё ещё дно vs retro #4 (19%), но движение в правильную сторону.
- ↗ Reviewer проход безупречный (errors 18 → 0). Скрипт
brain-retro-batch-reviewer.mjsстабилен после752d80af(self-assessment prompt-source fix). - ⚠️ Rework rate стабильно высокий (~10-11%) — baseline ещё не двинулся.
- ⚠️ no_self_assessment стабильно высокий (85%) — заказчик в sanity-чеке подтвердил «не нормально — я бежал вперёд слишком быстро без остановки». Это материальный сигнал.
Path-type distribution
| path_type | count | % | rework rate |
|---|---|---|---|
| improvised | 294 | 92.7% | 10.6% (31/293 reviewed) |
| regulated | 23 | 7.3% | 9.1% (2/22 reviewed) |
Regulated path даёт modest улучшение (10.6 → 9.1 п.п.). Регулирование помогает, но эффект слабый — это значит что часть «improvised» — это короткие conversation-задачи где регулирование избыточно. Discrimination signal — на больших задачах он сильнее.
Reviewer outcome distribution (316 reviewed)
| outcome_reviewed | count | % |
|---|---|---|
| soft_success | 193 | 61.1% |
| success | 86 | 27.2% |
| rework | 33 | 10.4% |
| blocked | 4 | 1.3% |
success + soft_success = 88.3% — большинство задач закрыто. 10.4% rework + 1.3% blocked = 11.7% задач не на первой попытке.
Reviewer node_quality (316 reviewed)
| node_quality | count | % |
|---|---|---|
| disputable | 179 | 56.6% |
| correct | 104 | 32.9% |
| wrong_node | 29 | 9.2% |
| overkill | 2 | 0.6% |
| underkill | 2 | 0.6% |
Топ нод, которые я игнорировал (alternative_better для wrong_node=29)
| узел | раз пропущен | назначение |
|---|---|---|
| #19 superpowers (writing-plans, brainstorming, TDD…) | 10 | планирование, plan-driven работа |
| #33 claude-md-management | 3 | правка CLAUDE.md (я делал direct Edit) |
| #25 Semgrep | 3 | анализ кода / SAST |
| #18 Pest | 3 | тесты до коммита |
| #11 Pint | 3 | форматирование PHP |
| #66 laravel-backend-patterns | 1 | backend convention check |
| #30 Frontend Design | 1 | UI design decision |
| #31 UPM | 1 | UI material lookup |
| #62 billing-audit | 1 | биллинг-инвариант |
| #34 Sentry MCP | 1 | runtime ошибки |
#19 superpowers — №1 пропуск (10 раз, 34% всех wrong_node). Это значит для планирования/feature-задач я регулярно выбирал direct.
Конкретные эпизоды wrong_node (для Q4 sanity заказчика)
Заказчик попросил «направь меня на конкретные эпизоды». Топ-3 по убыванию rework-импакта:
1. Direct на feature-задаче → 4726 outuput tokens без plan'а
- task_ref:
506004ed-5b89-4922-9bb9-88376c9dbd9e(14:13:09) - Классификация: planning,
recommended_node=#19 - Выбрано:
direct - Outcome: rework
- Reasoning (reviewer): «Agent classified task as planning and recommended #19 but chose 'direct' instead, bypassing the recommended planning node. With 2766/4726 output tokens generated improvisationally on a planning task, the agent should have invoked the planning node rather than answering directly.»
- Сигнал: classifier правильно поставил
recommended_node=#19вprimary_rationale, но controller всё равно пошёл direct. Это разрыв роутинг-цепочки на уровне дисциплины, не классификации.
2. Direct на memory-sync задаче (касающейся MEMORY.md)
- task_ref:
f4c8ef62-1f28-4ee7-a0b9-cc48a98404d7(13:33:00) - Классификация: memory-sync,
recommended_node=#33+ chain#12 - Выбрано:
direct - Outcome: rework
- Reasoning: «Memory-sync workflow was bypassed despite touching MEMORY.md, indicating the proper chain steps were skipped.»
- Сигнал: прямые Edit'ы memory без вызова #33 claude-md-management — повтор старого паттерна (см. CLAUDE.md §5 п.10).
3. Direct на feature-задаче → Globs с таймаутами
- task_ref:
1ff47cd9-c1e0-4277-ad1b-1f7754f0569a(03:10:49) - Классификация: feature,
recommended_node=#19 - Выбрано:
direct - Outcome: rework
- Reasoning: «Agent chose 'direct' and proceeded with exploratory Globs that all timed out. The rationale itself flags #19 as recommended, indicating the direct route was a misroute that should not have been started without the proper feature chain.»
- Сигнал: тот же паттерн что в кейсе 1 — classifier видит #19, controller игнорирует.
Вывод: во всех трёх кейсах classifier правильно идентифицировал нужный узел, но controller (я) выбрал direct игнорируя рекомендацию. Это сигнал для нормативки: routing-gate должен ужесточиться или нужен явный override-механизм с обоснованием.
Reviewer chain_quality (316 reviewed)
| chain_quality | count | % |
|---|---|---|
| n/a | 296 | 93.7% |
| missing_step | 12 | 3.8% |
| correct | 7 | 2.2% |
| extra_step | 1 | 0.3% |
| wrong_order | 0 | — |
12 missing_step — где была пропущена обязательная фаза цепочки (preflight / plan / verification).
Reviewer agent_self_assessment_accuracy (316 reviewed)
| accuracy | count | % |
|---|---|---|
| no_self_assessment | 270 | 85.4% |
| accurate | 38 | 12.0% |
| over_confident | 4 | 1.3% |
| under_confident | 4 | 1.3% |
⚠️ 85% эпизодов без self-assessment — это и есть тот самый «бежал слишком быстро без остановки», который заказчик подтвердил в sanity-чеке. См. кандидат B ниже.
Reviewer error_root_cause (316 reviewed)
| root_cause | count | % |
|---|---|---|
| n/a | 248 | 78.5% |
| wrong_skill | 36 | 11.4% |
| external_failure | 19 | 6.0% |
| wrong_chain_order | 9 | 2.8% |
| wrong_tool | 4 | 1.3% |
wrong_skill — #1 root_cause среди материальных ошибок (36 эпизодов; 11.4% всех reviewed, 51% non-n/a). Это согласуется с wrong_node=29 — пересекается с тем же паттерном «выбрал не тот канал».
Factor matrix — основные оси
Provenance × outcome (период)
| provenance | success | soft_success | rework | blocked | total | rework rate |
|---|---|---|---|---|---|---|
| autonomous (Claude один) | 57 | 167 | 33 | 4 | 261 | 12.6% ⚠️ |
| user_chose_from_options (заказчик выбрал из моих вариантов) | 29 | 26 | 0 | 0 | 55 | 0% ✅ |
| user_directed_method | — | — | — | — | 1 | n/a |
КРИТИЧЕСКИЙ СИГНАЛ: когда заказчик выбирает из предложенных мной вариантов — rework 0%, blocked 0%. Когда я действую автономно — rework 12.6%. Дельта 12.6 п.п. Это значит brainstorm-pattern «3 варианта пользователю» — самый сильный механизм качества за месяц.
Economy level × outcome (период)
| economy | success | soft | rework | blocked | total |
|---|---|---|---|---|---|
| 100 (default) | 84 | 189 | 32 | 4 | 309 (97.5%) |
| 5 | 1 | 1 | — | — | 2 |
| 0 | — | 2 | 1 | — | 3 |
| none | 1 | 1 | — | — | 2 |
Распределение по экономии однородно — почти все ходы на 100% (default).
Path_type × outcome (период)
| path_type | success | soft | rework | blocked | total | rework rate |
|---|---|---|---|---|---|---|
| improvised | 73 | 186 | 31 | 3 | 293 | 10.6% |
| regulated | 13 | 7 | 2 | 1 | 23 | 9.1% |
Regulated path лучше на 1.5 п.п. — слабое преимущество. Discrimination signal: большая часть improvised — короткие conversation-задачи (70 episodes), где regulation излишен.
Discipline by classification
| classification | episodes | trigger match | via skill | % trigger | % skill |
|---|---|---|---|---|---|
| analysis | 21 | 8 | 4 | 38.1% | 19.0% |
| planning | 11 | 2 | 2 | 18.2% | 18.2% |
| bugfix | 16 | 4 | 5 | 25.0% | 31.3% |
| feature | 15 | 2 | 0 | 13.3% | 0% ⚠️ |
⚠️ Feature-задачи: trigger match 13.3%, via skill 0% — ни одна feature-задача не прошла через #19. Это причина 10 wrong_node→#19. Plan-driven работа сломалась.
Causal chains (file-overlap)
62 цепочки эпизод→эпизод через общие правленые файлы. Топ-3:
MEMORY.mdцепочка — внутри ходов брейн-ретро и брейнсторма (8e4bbb0f→9328e4a2→12fb2d88→1c4313a9→bb783ab4→54910715) — нормально, единая задача.resources/js/router/index.ts— Plan 5 frontend Tasks 7-11 финал.SyncSupplierProjectJob.php/Supplier/SyncSupplierProjectsJob.php— supplier-webhook reliability Phase 1+2+3.
Causal chains пока не дают error→fix сигналов — нужен новый матчер «эпизод с rework → следующий эпизод на тех же файлах».
Missed activations
missedActivations.totalMissed в анализе всего месяца = null/keys-only (analyzer-debt: возвращает кortege вместо данных при пустом множестве, см. кандидат C). Внутри периода miss'ы фигурируют через wrong_node=29 и trigger_match гэпы — уже отражены выше.
Sanity-check ответы заказчика
docs/observer/sanity-checks/2026-05-26-brain-retro-6.json:
| вопрос | ответ |
|---|---|
| Главная причина переделок? | «Не знаю — смотри сам, тебе виднее» (передал на проф. суждение) |
| 85% без самопроверки — норма? | «Не нормально — я бежал вперёд слишком быстро без остановки» ⚠️ |
| Blind spot наблюдателя за период? | «Ничего конкретного — наблюдатель ОК» ✅ |
| Direct вместо навыка — пример? | «Сложно сказать — направь меня на конкретные эпизоды» (3 кейса выше) |
Q2 — самый сильный сигнал ретро. Заказчик в явной форме подтвердил то, что показывает агентам self-assessment-accuracy = 85% no_self_assessment.
NB про первый раунд вопросов: первые 2 вопроса я задал на программистском жаргоне («rework», «wrong_skill», «TDD pattern») — заказчик ответил «преформулируя я не програмист» дважды. Перефразировал простым языком на втором раунде. Урок: sanity-questions должны идти на бытовом языке (заказчик — владелец бизнеса, не разработчик; см. memory feedback_plain_language.md).
Reviewer outcome breakdown
| источник | reviewed | % |
|---|---|---|
| direct_api_batch (брain-retro-batch-reviewer.mjs) | 316 | 100% |
| subagent | 0 | — |
| direct_api fallback | 0 | — |
brain-retro-batch-reviewer.mjs остаётся рабочей лошадкой. Reviewer-agent subagent через .claude/agents/reviewer-agent.md ещё не вызывался в продуктовом потоке (см. кандидат A).
Кандидаты на review заказчиком
Кандидат A — заменить batch-reviewer на reviewer-agent subagent (per spec §4.6)
Сейчас: все 316 review'ев сделаны через brain-retro-batch-reviewer.mjs (direct Opus API).
Spec §4.6 говорит: primary reviewer = subagent через Task(subagent_type='reviewer-agent'), batch — это fallback.
Что предлагаю: уточнить процедуру /brain-retro шага 5b — добавить fail-fast флаг «если N>50 эпизодов, использовать batch вместо subagent (для скорости), иначе subagent». Или зафиксировать что batch — основной режим, и обновить spec.
Стоимость решения: правка .claude/skills/brain-retro/SKILL.md шага 5b + либо spec §4.6 § amend.
Опция отказа: оставить как есть — batch работает.
Кандидат B ⚠️ — поднять self-assessment coverage (Q2 sanity сигнал)
Сигнал: заказчик в sanity-чеке подтвердил «бежал вперёд слишком быстро без остановки» на 85% no_self_assessment.
Корень: self-assessment-хук срабатывает не на всех задачах (вероятно фильтрация по типу — conversation/micro исключены, но и многие feature/bugfix проходят без него). После 752d80af хук получает реальный prompt, но скорее всего не докручен по покрытию.
Что предлагаю: написать спек «расширить self-assessment trigger на все classification ∈ {feature, bugfix, refactor, planning, security}» — это половина unknown'ов превратится в self-assessed.
Дополнительно: проверить нет ли тихих сбоев self-assessment-хука (degradedCount=6 за весь май — стоит сверить пересекается ли с no_self_assessment).
Опция отказа: принять 85% no_self_assessment как baseline. Не рекомендую — заказчик прямо сказал «не нормально».
Кандидат C — починить missedActivations в analyzer
Симптом: data.missedActivations возвращает строки "totalMissed", "byNode", "byClassification" вместо данных. Похоже на bug в tools/missed-activations.mjs — функция возвращает ключи объекта вместо самого объекта при пустом результате.
Что предлагаю: написать failing-test → fix → 0 regressions.
Стоимость: ~30 мин TDD.
Опция отказа: оставить — missed activations всё равно фигурируют через wrong_node=29 (косвенно).
Кандидат D — нормативно укрепить «direct на feature/planning требует обоснования»
Сигнал: 10 из 29 wrong_node — это feature/planning с recommended_node=#19, где я выбрал direct. Classifier ВИДИТ узел, controller ИГНОРИРУЕТ.
Что предлагаю: дополнить enforce-hard-rules / Pravila §17 — если classifier_output.task_type ∈ {feature, planning} И recommended_node=#19 → require routing-tag с обоснованием почему direct (и hook'ом).
Это поведенческое правило, не SoT правка — Pravila §17 расширение.
Опция отказа: оставить — ждать новых данных.
Кандидат E — sanity-questions всегда на бытовом языке
Сигнал: 2 из 4 вопросов первого раунда отвергнуты заказчиком как «преформулируя я не програмист». Память feedback_plain_language.md это правило фиксирует, но я её нарушил при формировании sanity-вопросов.
Что предлагаю: добавить в .claude/skills/brain-retro/SKILL.md шаг 5a отметку «вопросы заказчику — простым языком; не «rework / wrong_skill», а «переделки / выбор не того инструмента»» с парой примеров.
Стоимость: правка одного скила, ~10 мин.
Опция отказа: доверить контроллеру каждый раз.
Кандидат F — улучшить classifier на «conversation» vs реальная задача
Сигнал: в period'е 230 эпизодов с task_type=unknown (73%!) — classifier не классифицирует большую часть. 70 — conversation, 7 — micro. Это значит большинство ходов вообще не получают recommended_node, что снимает шанс на правильный routing.
Что предлагаю: в tools/router-classifier.mjs добавить fallback-классификацию по text-signature (например keyword-based «спросить» → question / «исправь» → bugfix / «доделай» → feature). Сейчас классификатор-LLM возвращает unknown слишком часто.
Стоимость: ~1-2 часа на pure-функцию + tests.
Опция отказа: ждать накопления данных, чтобы LLM-classifier обучился через few-shot examples.
Self-retrospect trigger status
docs/observer/.self-retrospect-counter.json — last_run_at: null, episodes_since_last: 202 (на старте retro #5; bump до сих пор не делался автоматически).
Текущая ситуация: counter уже >>50, в retro #5 заказчику было предложено /self-retrospect (пасс) — повторно предлагать не буду, чтобы не утомлять. Если хочется — заказчик помнит про опцию.
Bump после ретры #6: +317 → ~519 episodes_since_last (накопительно). Запишу.
Cost report
~/.claude/runtime/cost-daily.json — не существует на этой машине (как и в retro #5). task_cost-поля в JSONL все по нулям (0/0 input/output tokens по всем 482 эпизодам месяца) — значит хук, который должен писать токены, не пишет. Это технический долг сам по себе — будущий retro не сможет точно отчитаться по стоимости.
Оценка стоимости retro #6 (ProxyAPI Opus 4.7 — $15/M input, $75/M output):
- 132 эпизода × средний review-промпт ~3.5k input tokens (полный episode JSON + reviewer-prompt) → ~460k input tokens.
- Output ~150 tokens × 132 ≈ 20k output tokens.
- input: $15/M × 0.460 = ~$6.90
- output: $75/M × 0.020 = ~$1.50
- Total reviewer-пасса retro #6: ~$8.40
Plus classifier-вызовы и self-assessment этой сессии — не учтены (cost-daily.json пуст). Полная цена ретры (включая мой controller-думать-write) — не отслеживается.
Что НЕ меняется этим retro
- НЕ редактирую
tools/observer-classification-map.json,docs/registry/nodes.yaml,tools/.node-dormancy.json, нормативку, code. - НЕ переключаю router-gate из warn-only в enforce.
- НЕ пишу в
episodes-*.jsonlчерез ручную правку — только через batch-reviewer (review.*+outcome_reviewed+outcome_reviewed_sourceполя добавлены автоматически 132 раза). - НЕ trigger'у auto-memory.
- НЕ предлагаю
/self-retrospectповторно (он уже был предложен в retro #5). - STATUS.md перегенерируется через
node tools/status-md-generator.mjs(шаг 8a процедуры).
Артефакты этого retro
- Эта нота:
docs/observer/notes/2026-05-26-brain-retro-6.md - Sanity-checks ответы:
docs/observer/sanity-checks/2026-05-26-brain-retro-6.json - Episodes (всё инкрементально, in-place 132 review'нуты):
docs/observer/episodes-2026-05.jsonl - Read-counter bump:
docs/observer/.read-counter.json(last_read_at: 2026-05-26T13:03:40.766Z,read_count_last_period: 4) - STATUS.md regen: следующий шаг процедуры.