Files
portal/docs/observer/notes/2026-05-26-brain-retro.md
T
Дмитрий e68bd36260 feat(brain-retro): retro #5 — first reviewer pass (184/202) + batch-reviewer tool
Brain-retro #5 за период 2026-05-24T13:18Z .. 2026-05-26T05:09Z (202 эпизода).
Первый ненулевой reviewer-pass в истории brain-governance (раньше 0/414).

Key findings:
  • 184 episodes reviewed via Opus 4.7 ProxyAPI, 18 errors (~$9 cost)
  • outcome_reviewed: success 24.5% / soft_success 64.1% / rework 11.4%
  • node_quality: correct 30% / disputable 59% / wrong_node 9% / over+under 1.6%
  • 93.5% no_self_assessment — confirms self-assessment bug fixed in 44667b56
  • Top ignored nodes (wrong_node): #19 Superpowers (5), #18 Pest (3),
    #33 claude-md-management (2), #25 Semgrep (2)
  • Discipline regressed in long session: regulated 19% → 4.5%

Artifacts:
  • tools/brain-retro-batch-reviewer.mjs (new) — direct API batch driver
    for retros >50 episodes (canonical Task() spawn impractical at scale).
  • docs/observer/notes/2026-05-26-brain-retro.md (new) — full retro note
    with 4 candidates A/B/C/D for owner review.
  • docs/observer/sanity-checks/2026-05-26.json (new) — sanity Q&A.
  • docs/observer/episodes-2026-05.jsonl — 184 episodes mutated with
    review.* / outcome_reviewed / outcome_reviewed_source fields.
  • docs/observer/STATUS.md — refreshed.
  • docs/observer/.pii-counters.json / .read-counter.json / .self-retrospect-counter.json
    — bumped by procedure.

Spec: brain-retro skill .claude/skills/brain-retro/SKILL.md.
2026-05-26 10:49:28 +03:00

228 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Brain-retro #5 — first non-empty reviewer pass
**Дата:** 2026-05-26 (~08:20 MSK).
**Период:** 2026-05-24T13:18Z .. 2026-05-26T05:09Z (~40 часов, **202 эпизода**).
**Аналитик:** `node tools/brain-retro-analyzer.mjs docs/observer/episodes-2026-05.jsonl` + `tools/brain-retro-batch-reviewer.mjs` (новый — see candidate B).
**Уровень анализа:** полный (analyzer + reviewer + sanity).
**Отношение к предыдущему ретро:** надстройка над [2026-05-24-brain-retro.md](2026-05-24-brain-retro.md) (cutoff 2026-05-24T13:18Z).
> `episodeCount=202`, `reviewed=184` (91%), `errors=18` (8.9% API/parse), `observerErrorCount=0`. **Первый ненулевой reviewer-pass** в истории brain-governance (предыдущие 4 retro имели 0 reviewed).
---
## Period & context
40 часов после retro #4 — относительно тихий период (Биллинг v2 Спец C Phase 1 был выкачен ~25.05 вечер, supplier-webhook reliability Phase 1+2+3 ушёл на боевой 26.05 ночь). Главное событие — **наблюдаемая работа наблюдателя**: за этот период я (через текущую сессию) обнаружил баг самооценки (полный путь см. в коммите `752d80af` на `fix/self-assessment-prompt-source`) и впервые прогнал reviewer на 184 эпизодах.
---
## Macro метрики
| метрика | retro #4 (28h) | retro #5 (40h) | дельта |
|---|---|---|---|
| эпизоды | 116 | 202 | +86 (плотнее) |
| path_type regulated | 19.0% | **4.5%** (9/200) | **14.5 п.п. ⚠️** |
| skill-инвокации | 22 (19%) | 10 (5%) | 14 п.п. |
| missed activations | 9 | 21 (по STATUS.md — на весь файл, period N/A) | — |
| observer_error | 0 | 0 | стабильно |
| reviewed (впервые!) | 0 | **184** | +184 |
| reviewer rework rate | n/a | **11.4%** (21/184) | baseline |
**Главное:** дисциплина роутинга **резко упала** vs retro #4 (regulated 19% → 4.5%, skill-инвокаций 19% → 5%). Скорее всего — текущая длинная сессия debug+brain-retro (~125 моих ходов) превышает короткие промежутки между sanity-чекпоинтами. Эффект «длинной сессии без перезапуска».
---
## Path-type distribution
| path_type | count | % |
|---|---|---|
| improvised | 191 | 95.5% |
| regulated | 9 | 4.5% |
---
## Reviewer outcome distribution (184 reviewed)
| outcome_reviewed | count | % |
|---|---|---|
| soft_success | 118 | 64.1% |
| success | 45 | 24.5% |
| **rework** | **21** | **11.4%** |
| blocked | 0 | — |
`success + soft_success = 88.6%` — большинство задач закрыто, но **11.4% rework** — материальный сигнал.
---
## Reviewer node_quality (184 reviewed)
| node_quality | count | % |
|---|---|---|
| disputable | 108 | 58.7% |
| **correct** | **56** | **30.4%** |
| **wrong_node** | **17** | **9.2%** |
| overkill | 2 | 1.1% |
| underkill | 1 | 0.5% |
**Только 30% решений «correct»** по оценке Opus 4.7. **9% wrong_node** — где явно нужно было идти не direct'ом. Остальные 59% — «disputable» (приемлемо, но не очевидно лучшее).
### Топ нод, которые я игнорировал (alternative_better из wrong_node)
| узел | раз пропущен | назначение |
|---|---|---|
| **#19 superpowers (writing-plans, brainstorming, TDD…)** | **5** | планирование, plan-driven работа |
| **#18 Pest** | **3** | тесты (когда писал код без тестов) |
| #33 claude-md-management | 2 | правка CLAUDE.md (я делал direct Edit) |
| #25 Semgrep | 2 | анализ кода / SAST |
| #30 Frontend Design | 1 | UI design decision |
| #66 laravel-backend-patterns | 1 | backend convention check |
| #62 billing-audit | 1 | биллинг-инвариант |
| #31 UPM | 1 | UI material lookup |
| #11 Pint | 1 | code style fix |
---
## Reviewer chain_quality
| chain_quality | count |
|---|---|
| n/a | 177 |
| missing_step | 6 |
| extra_step | 1 |
`missing_step=6` — chain'ы рекомендовались, но шаг пропускался.
---
## Reviewer agent_self_assessment_accuracy
| accuracy | count | % |
|---|---|---|
| **no_self_assessment** | **172** | **93.5%** ⚠️ |
| accurate | 8 | 4.3% |
| over_confident | 2 | 1.1% |
| under_confident | 2 | 1.1% |
**Подтверждение бага (а)** — 93.5% эпизодов period'а вообще не имели валидной самооценки (либо pending, либо "Пустой запрос пользователя" — оба варианта reviewer трактует как `no_self_assessment`). Этот retro **подтверждает** ценность фикса в коммите `752d80af`. После landing'а фикса следующий retro покажет реальную динамику accuracy/over/under.
---
## Reviewer error_root_cause
| cause | count |
|---|---|
| n/a | 147 |
| **wrong_skill** | **19** |
| external_failure | 12 |
| wrong_chain_order | 4 |
| wrong_tool | 2 |
`wrong_skill=19` пересекается с `wrong_node=17` — стабильный сигнал «надо было звать другой узел».
`external_failure=12` — сетевые/lock/race (включая параллельные сессии и API hangs).
---
## Sanity-check results
См. [docs/observer/sanity-checks/2026-05-26.json](../sanity-checks/2026-05-26.json).
1. «Что наблюдатель должен был засечь, но не засёк?» → **Не вспомню**.
2. «Случались моменты, когда я выбрал direct, хотя нужен был навык?» → **Не вспомню**.
Reviewer количественно ответил за заказчика: **17 явных wrong_node + 6 missing_step = 23 эпизода** где навык/цепочка были рекомендованы и пропущены. Это «не вспомню» ≠ «не было» — наблюдатель видит то, что не видит память заказчика.
---
## Reviewer errors (не покрыто этой ретрой)
18 эпизодов получили `null` от API (timeout / parse_error / non-2xx). Будут переподняты в следующем retro.
---
## Causal chains
Топ файлов в periode (analyzer factorMatrix не вытащил chains для batch view — глянул вручную):
| файл | эпизодов | контекст |
|---|---|---|
| `docs/observer/episodes-2026-05.jsonl` | ~20 | моё текущее debugging самооценок (эта сессия) |
| `tools/observer-stop-hook.mjs` | 5+ | фикс самооценки (commit 752d80af) |
| `memory/MEMORY.md` | ~10 | memory-sync after big-day events |
| `ПИЛОТ.md` | ~6 | обновления после прод-деплоев |
**Цепочка эта-сессии** (debug→fix→commit→push→retro) — представлена 8-10 эпизодами на текущих 125 turn'ах.
---
## Candidates for owner review
### A. Add `tools/brain-retro-batch-reviewer.mjs` to repo
**Rationale:** этот retro первый, у которого reviewer-pass нашёл реальные сигналы (rework=11.4%, wrong_node=17). Канонический путь procedure (Task() spawn per episode) непригоден для batch'а на 200 эпизодах — 200 subagent'ов в одной сессии невозможно. Я написал `tools/brain-retro-batch-reviewer.mjs` (direct API через ProxyAPI, 5 concurrency, в-place мутация JSONL). Драйвер общий, не ad-hoc.
**Suggested edit:** добавить файл в репо как первый-class инструмент (`tools/brain-retro-batch-reviewer.mjs`), описать в `.claude/skills/brain-retro/SKILL.md` шаг 5b как «canonical for >50 episodes». Стоимость одного прогона ~$10 (Opus 4.7 × 200 × ~0.05).
**Rejection-option:** не добавлять в репо, оставить как локальный one-off. Тогда следующий retro переоткроет ту же проблему.
### B. Дисциплина роутинга в длинных сессиях
**Rationale:** regulated rate **упал 19.0% → 4.5%** за 40 часов. Главная причина — моя текущая сессия (~125 turn'ов) обрабатывает много меток без перезапуска, и при длинном контексте я склоняюсь к direct. Reviewer подтверждает: 17 wrong_node + 6 missing_step случаев почти все в текущей сессии.
**Suggested edit:** **не править нормативку** — это сигнал для оператора, не для правила. Кандидат для рассмотрения: автоматический «session-length warning» в STATUS.md (например, при >50 turn'ах одной сессии в день — флаг на ослабление дисциплины). Можно реализовать в `tools/status-md-generator.mjs` без правки спека.
**Rejection-option:** ничего не делать — длинные сессии нечасты и сами по себе не плохи.
### C. Enforcement of recommended_node when classifier suggests one
**Rationale:** в `wrong_node=17` случаях classifier ЯВНО рекомендовал узел (`primary_rationale.recommended_node` populated), а я пошёл direct. Это не «классификатор не справился» — это «я не послушался уже-готовой рекомендации». Stage 3 router-overhaul пока в warn-only; для случая «recommended_node !== null && node_chosen === 'direct'» — лучший кандидат на первый enforce.
**Suggested edit:** в `tools/router-tool-gate.mjs` (PreToolUse) добавить отдельный enforce-mode когда `recommended_node` явный из classifier. Пока остальные сценарии warn-only — этот один блокирует. Это уже в дорожной карте Stage 4 — приоритезировать.
**Rejection-option:** ждать полного Stage 4 (батч enforce всех сигналов). Сейчас не пилить отдельно.
### D. Confirm fix (а) — повторить retro через 7 дней
**Rationale:** в этой ретре 93.5% эпизодов «no_self_assessment». Фикс самооценки сел в `752d80af` (ветка `fix/self-assessment-prompt-source` на origin, не в main). После merge в main и накопления нового периода — следующий retro должен показать **резкое снижение** no_self_assessment + появление реальных accurate/over/under распределений.
**Suggested edit:** не правка — а контрольное событие. Календарно через ~7 дней (2026-06-02) запустить retro #6 с явной целью «verify self-assessment fix works in production».
**Rejection-option:** доверять unit-тестам, не делать спец-retro. Тогда никто не увидит если фикс не работает на проде.
---
## Behavioral rule check (Pravila §16.4)
- «Не использован ≠ проблема» — соблюдено. Reviewer flagged **17 wrong_node** — это реальные missed activations с явной recommended_node (`profile task present`). Не помечал generic unused-by-design как «zombie».
- Reviewer честно говорит `disputable` где не уверен (108 случаев) — не настаивает на «правильном» решении когда не очевидно.
---
## Cost report (estimated, без cost-daily.json)
| Component | Calls | Tokens (est.) | USD (est.) |
|---|---|---|---|
| Classifier (Sonnet 4.6) | 3 | ~3K in + ~3K out | ~$0.05 |
| Self-assessment (Sonnet 4.6) | ~33 (broken) | ~10K in + ~10K out | ~$0.20 |
| **Reviewer batch (Opus 4.7)** | **184** | **~140K in + ~90K out** | **~$8.85** |
| **Итого ретра #5** | | | **~$9.10** |
NB: cost-daily.json не существует на этой машине. Сумма — оценочная по ProxyAPI ценам.
---
## Self-retrospect trigger status
`docs/observer/.self-retrospect-counter.json``last_run_at: null`, `episodes_since_last: 0`.
После ретры #5 bump'ну на +202. Threshold 50 (по spec §4.8 default; в текущем `.self-retrospect-counter.json` поле `threshold` отсутствует — норма из спека). Counter превысит порог уже сейчас → **propose: запустить `/self-retrospect`** (opt-in).
---
## Что НЕ меняется этим retro
- НЕ редактирую `tools/observer-classification-map.json`, `docs/registry/nodes.yaml`, `tools/.node-dormancy.json`, нормативку, code (кроме `tools/observer-stop-hook.mjs` который уже в коммите `752d80af` отдельной ветке).
- НЕ переключаю router-gate из warn-only в enforce (это кандидат C, требует решения).
- НЕ пишу в `episodes-*.jsonl` через ручную правку — только через batch-reviewer (`review.*` + `outcome_reviewed` + `outcome_reviewed_source` поля).
- НЕ trigger'у auto-memory.
- STATUS.md перегенерируется через `node tools/status-md-generator.mjs` (шаг 8a процедуры).