# Brain-retro #10 — 2026-05-28 (вечер)

**Период:** с retro #9 (2026-05-28T07:47:21Z = 10:47 МСК) по 2026-05-28T13:31Z (16:31 МСК)
**Эпизодов:** 27 (после filter; в файле за период 29, 27 ушли в reviewer — limit)
**Observer errors:** 0
**Тип сессии:** router-hooks Phase 4 closure + Phase 5 closure + текущий /brain-retro

---

## 1. Path-type breakdown

| Path type | Count | % |
|---|---|---|
| improvised | 26 | 96.3 |
| regulated | 1 | 3.7 |

Очень высокий improvised — фактически вся сессия. Один regulated — момент когда триггернулась Pravila §15 (subagent-driven-development).

## 2. node_chosen distribution

| Node | Count | % |
|---|---|---|
| direct | 25 | 92.6 |
| superpowers:writing-plans | 1 | 3.7 |
| graphify | 1 | 3.7 |

## 3. recommended_node distribution

| Recommended | Count | % |
|---|---|---|
| null | 27 | 100 |

Классификатор не дал ни одной рекомендации — все 27 ушли с `recommended_node: null`. Картина согласована с (2): я почти везде шёл direct, классификатор не возражал.

## 4. GAP «рекомендован но взял direct»

**0 эпизодов** — нечего флагать. recommended_node везде null.

## 5. outcome × node_chosen group (reviewer-определённый outcome)

| Group | Count | Rework |
|---|---|---|
| skill_used (writing-plans + graphify) | 2 | 1 (graphify на "да давай") |
| direct_no_rec (рекомендации не было → direct) | 25 | 3 |

После reviewer'а: 8 success / 15 soft_success / 4 rework. Rework-rate всего ~15% — но 4 из 4 reworks trace к коротким ambiguous-prompt'ам, см. §13.

## 6. classifier_output source

| Source | Count | % |
|---|---|---|
| prefilter | 16 | 59.3 |
| regex | 6 | 22.2 |
| llm | 4 | 14.8 |
| cache | 1 | 3.7 |

Класс — здоров. LLM-fallback срабатывал только когда prefilter+regex не справились. Никаких NULL — всё классифицировано.

## 7. Per-classification (trigger-match + via-skill)

| Classification | n | trigger-match% | via-skill% |
|---|---|---|---|
| other | 22 | 5 | 9 |
| question | 5 | 20 | 0 |
| analysis | 1 | 0 | 0 |
| memory-sync | 1 | 0 | 0 |

Большинство — `other`, что неудивительно для chain-сессии «делай все» где каждая мини-задача — продолжение предыдущей.

## 8. Class × canon coverage

| Classification | n | canonicalNodes | routerRec | claudeTook | recWithinCanon | rework |
|---|---|---|---|---|---|---|
| other | 20 | [] | 0 | 2 | 0 | 0 |
| question | 5 | [] | 0 | 0 | 0 | 0 |
| analysis | 1 | [#25,#39,#53] | 0 | 0 | 0 | 0 |
| memory-sync | 1 | [] | 0 | 0 | 0 | 0 |

Один analysis-эпизод имел канон (#25 Semgrep / #39 ToB / #53 process-analysis), но классификатор канон не вытащил (`routerRec=0`), а я ничего не взял. Не критично — это была короткая question-like analysis.

## 9. Router vs Opus

| Section | Count |
|---|---|
| A (router дал → Opus оценил) | 0 |
| B (router молчал → Opus сказал «надо был скил») | 0 |
| C (router дал → Opus согласился что излишен) | 0 |

Пусто, потому что router ни разу не дал рекомендацию. Reviewer-найденные wrong_node случаи (см. §13) формально не попадают в эту таблицу — они идут в gap_assessment.

## 10. Chain-ignore breakdown

| Chain length | Count | Ignored | Rework |
|---|---|---|---|
| Total | 0 | 0 | 0 |

Тоже пусто — router цепочек не предлагал.

## 11. Chain-hook effectiveness

| Bucket | Count |
|---|---|
| total | 211 (cumulative с момента wire-up) |
| blocked | 7 (3.3%) |
| passed-with-skill | 0 |
| passed-inline-override | 0 |
| passed-global-override | 0 |
| passed-short-chain | 204 (96.7%) |
| passed-no-mutating | 0 |

Хук активен, 211 срабатываний с регистрации (включая retro период). 96.7% — короткая цепочка (≤1 узел) — фактически большинство triggerов происходит когда нет mutating tool или цепочка пустая. 7 блокировок за 211 событий = ~3% — рабочий уровень, не «дроссель», не «спам».

---

## 12. Reviewer pass — батч-mode (27 episodes, 68.2s, ~$0.05-0.10)

| Поле | Распределение |
|---|---|
| node_quality | disputable 12 (44%) / correct 11 (41%) / wrong_node 3 (11%) / underkill 1 (4%) |
| chain_quality | n/a 25 / missing_step 2 |
| gap_assessment | acceptable 22 / mistake_should_not_start 3 / mistake_should_complete 1 / n/a 1 |
| agent_self_assessment_accuracy | no_self_assessment 17 / accurate 10 |
| error_root_cause | n/a 20 / wrong_skill 6 / external_failure 1 |
| outcome_reviewed | soft_success 15 / success 8 / rework 4 |

**41% correct vs 11% wrong_node + 4% underkill** — приемлемый уровень. Главный сюрприз — 44% «disputable»: reviewer не уверен. Это объясняется природой chain-сессии (chunks 8-16 турнов на одном task_id с пустыми мета-полями).

**Self-assessment отсутствовал в 63% эпизодов** (17 из 27 no_self_assessment). Это известное состояние — self-assessment включается только на сложных задачах. На chain-сессии большинство эпизодов — короткие mini-turn'ы.

## 13. Reviewer-флагнутые случаи (5 эпизодов)

Все 5 трассируются к **коротким ambiguous prompt'ам** где надо было clarify, а не действовать:

| Время | Prompt | Что произошло | Verdict | Что было правильно |
|---|---|---|---|---|
| 08:52 | «пробуй готово» (13 chars) | direct → 68 tool calls 7 файлов 55min | wrong_node + missing_step + rework | clarify |
| 08:55 | «делай дальше» (12 chars) | hard_floor → writing-plans → 38 calls, 2 TDD-hook errors | disputable + wrong_skill | clarify |
| 09:20 | (ambig) | direct → 28 calls multiple Edit errors → rework | underkill + missing_step + rework | #33 claude-md-management |
| 10:16 | «да давай» | **graphify** + 10 Bash calls на context-free affirmation | wrong_node + rework | clarify |
| 12:43 | «deplo» (5 chars) | direct + AskUserQuestion clarification (правильно) но потом 22 calls drift | disputable | clean clarify-first |
| 12:56 | «подбери все хвосты» (18 chars) | classifier null → direct → 9 calls 3 memory файла | wrong_node + rework | clarify |

**Sanity-ответ заказчика подтверждает паттерн:** «Phase 5 можно было через subagent-driven» — да, multi-file TDD таски Phase 5 кейс контекста, где inline TDD стоил больше токенов чем subagent.

Causal chains (deterministic analyzer):
- `826f2823 → 4a8b327e` (общие файлы: `tools/router-classifier.mjs` + `.test.mjs`)
- `4a8b327e → 27e80d61` (общий: `cspell-words.txt`)

Это нормальный workflow «правка → последствие в чужом файле», не error→fix loop.

## 14. Missed activations

**0 missed activations** (для классификаций with canonical nodes). 1 analysis-эпизод с каноном (#25/#39/#53) формально мог триггерить, но текст эпизода short question — Pravila §16.4 conditional rule не вызывает алерт.

## 15. Boundaries inheritance

- withBoundaries: 2/27 (7.4%) — Pravila §15 и Pravila §5
- inheritanceCount: 0 (на коротких turn-цепочках inheritance не сработал)

## 16. Cost report (за период)

- classifier: 283 input + 6500 output tokens (≈$0.10 Sonnet 4.6)
- self_assessment: 0/0 (не вызывался в задачах without self_assessment trigger)
- reviewer batch: ~27 × Opus 4.7 (3963 in / 195 out per episode средне) ≈ $1.7-2.0 (по логам ProxyAPI)
- self_retrospect: 0

**Phase 5 cost-daily.json текущий день:** $0.098349 classifier_usd, 29 эпизодов, total $0.098349.

**Замечание:** reviewer_subagent_usd / reviewer_direct_fallback_usd = 0 в cost-daily, хотя batch_reviewer работал. Stop-hook aggregator не подхватил review-cost. **Phase 5 follow-up candidate** (§17 Candidate 3).

## 17. Self-retrospect status

- `episodes_since_last`: **542** (≥ 50)
- `last_run_at`: null (никогда не запускался)
- **Триггер сработан** — пропозиция /self-retrospect ниже в §18 Candidate 1.

---

## 18. Candidates for owner review

### Candidate 1 — `/self-retrospect` ещё ни разу не запускался (542 эпизодов)

**Источник:** `docs/observer/.self-retrospect-counter.json` показывает `last_run_at: null` + `episodes_since_last: 542` (порог 50). Skill `.claude/skills/self-retrospect/` существует, но никогда не активировался.

**Suggestion:** запустить `/self-retrospect` в отдельной сессии — собрать «привычки контроллера» на 542 эпизодах накопленных с момента wire-up счётчика (явно с 19.05.2026, brain governance Phase B). Сегодня уже было одно self-retrospect ручное (`docs/observer/notes/2026-05-28-self-retrospect.md` — 5 привычек по 81 эпизоду 27-28.05) — оно НЕ обновило counter. Нужно либо понять почему counter не обнулился (баг бампера?), либо запустить full /self-retrospect skill сейчас.

**Reject option:** отложить — отдельная сессия, не сегодня; counter перепроверить вручную после ближайшей сессии.

### Candidate 2 — поведенческий: на коротких ambiguous prompt'ах сначала clarify, потом действовать

**Источник:** reviewer-флагнутые 5 из 6 wrong-cases trace к prompt'ам ≤18 chars где надо было задать AskUserQuestion вместо action. Прецеденты: «пробуй готово» / «делай дальше» / «да давай» / «deplo» / «подбери все хвосты».

**Reviewer уже flagging это** через `gap_assessment: mistake_should_not_start` (3 эпизода). Хук-механики пока нет.

**Suggestion (3 варианта):**
- A. **Поведенческое правило** — добавить в Pravila §17 (universal skill-coverage) подсекцию: «при prompt_signal=new_task + длина prompt'а ≤25 chars + classifier source=prefilter/regex → AskUserQuestion mandatory». Контроллер должен соблюдать сам.
- B. **Хук** — новый PreToolUse `enforce-clarify-short-prompts.mjs` блокирует mutating tools если turn1 user prompt ≤25 chars И classifier source ∈ {prefilter,regex} И tool НЕ AskUserQuestion. Override: inline `clarify-skip: <reason>` ИЛИ если предыдущий tool — AskUserQuestion.
- C. **Не делать** — reviewer-findings достаточно для retro-наблюдения; жёстко регулировать ambiguous-handling нельзя (есть legit-case «делай дальше» после подтверждённого плана).

**Recommendation:** B + дозовая мера. Hard-rule был бы дорогим (regress в нормальный chain-flow). Хук с явным override + список реальных flag'ов из reviewer = баланс.

**Reject option:** оставить только observational mode — reviewer всё равно ловит; жёсткое правило избыточно.

### Candidate 3 — Phase 5 cost-tracker: reviewer-cost не попадает в `cost-daily.json`

**Источник:** запустил batch reviewer на 27 эпизодов с Opus 4.7 (по логам ProxyAPI ~$2). Stop-hook cost-aggregator смотрит только `task_cost.input_tokens` + `task_cost.output_tokens` каждого эпизода. Reviewer пишет результат в `episode.review`, не в `task_cost`.

**Suggestion:** в `tools/cost-aggregator.mjs::episodeUsd(ep, pricing)` добавить чтение `ep.review.tokens_used` (если присутствует) → bucket `reviewer_subagent_usd` (если `outcome_reviewed_source==='subagent'`) / `reviewer_direct_fallback_usd` (`direct_api_*`). Тогда вызов `npx tsx tools/cost-stop-hook.mjs` после batch-review сразу обновит файл.

**Альтернатива:** batch reviewer сам пишет cost в отдельный bucket файла (минуя aggregator).

**Reject option:** оставить cost-daily покрывающим только classifier — это известный gap, отдельный план.

### Candidate 4 — графики `prompt_signal` и `economy_level` плоские (single-bucket)

**Источник:** factorMatrix показал `economy_level`: 100 → 24 episodes / null → 3 episodes. `prompt_signal` matrix — почти весь `neutral` (типично для chain-сессий).

**Это не проблема**, но снижает информативность factor matrix для коротких retro. На таком scale (27 эпизодов 2.5 часа) фактор-анализ слабый.

**Suggestion:** добавить в `tools/brain-retro-analyzer.mjs` rule «если total episodes < 30 ИЛИ factor matrix has cells ≥ 80% single-bucket → mark `factor_analysis: low_signal`» — сигнал в STATUS.md, что retro имеет узкое окно и patterns надо смотреть на retro с ≥30 эпизодов.

**Reject option:** не делать — retro at small N просто меньше говорит, не нужен formal marker.

---

## 19. Cross-refs

- Sanity answers: `docs/observer/sanity-checks/2026-05-28-brain-retro-10.json`
- Self-retrospect skill: `.claude/skills/self-retrospect/`
- Predecessor: `docs/observer/notes/2026-05-28-brain-retro-9.md`
- Cost-daily: `~/.claude/runtime/cost-daily.json`
- Chain-hook ledger: `~/.claude/runtime/hook-outcomes.jsonl`

---

## 20. Report to user (простым языком)

За эти 2.5 часа сессия Phase 4 + Phase 5 шла чисто — без серьёзных обходов и без явных багов мозга. Ревьюер всё-таки нашёл одно повторяющееся слабое место: **короткие неясные сообщения от тебя я переводил в действие, а надо было сначала переспросить**. Примеры: «делай дальше» / «да давай» / «deplo» — в этих случаях я запускал по 20-60 tool calls, иногда с откатами. Лучший ответ — задать уточняющий вопрос.

Phase 5 (cost-tracker) уже работает, в файле `cost-daily.json` сегодня записаны $0.10 — но это только классификатор. Стоимость ревьюера (~$2 за сегодняшний прогон) ещё не попадает в этот файл — это известная мелкая дырка, лечится за полчаса.

Счётчик `/self-retrospect` показывает 542 эпизода с последнего запуска (порог 50) — но запуска фактически никогда не было. Либо запустить full skill в отдельной сессии, либо проверить почему bumper не обнулил счётчик.

Главный кандидат на правку — **поведенческое правило / хук**, чтобы я на коротких неясных сообщениях сначала спрашивал, а не делал. Три варианта в §18 Candidate 2. Что выбрать — за тобой.
