Files
portal/docs/observer/notes/2026-05-27-brain-retro-7.md
T
Дмитрий 81cbd8c1c2 feat(brain-retro #7): C1+C2+C3+C4 router-discipline fixes
retro #7 (docs/observer/notes/2026-05-27-brain-retro-7.md) surfaced 4
candidates against 23 turns since retro #6. All four implemented TDD.

C1 — translit slang vocabulary in router-classifier-regex-fallback.mjs.
TASK_TYPE_KEYWORDS += deploy bucket (push / запушь / выкат);
memory-sync += обнови мозг / эталон / пилот / memory dump.

C2 — short_ambiguous_block in router-tool-gate.mjs + router-prehook.mjs.
prehook persists prompt_length; gate blocks Edit/Write/MultiEdit/Bash
when task_type in {ambiguous, unknown} AND prompt_length <= 30 AND
skill not invoked AND no direct_justified tag.

C3 — self-assessment timeout 30s to 50s in observer-self-assessment-api.mjs.
Windows TLS handshake + Sonnet latency exceeded 30s. Stop-hook has 60s
budget; 50s leaves headroom. DEFAULT_TIMEOUT_MS exported for tests.

C4 — Reviewer findings block in status-md-generator.mjs. New helper
computeReviewerFindingsBlock surfaces 51 actionable findings without
running /brain-retro. Detects batch-reviewed via
outcome_reviewed_source=direct_api_batch. MD012 guard test added.

C5 (gitleaks-before-push) intentionally skipped — pre-push hook already
blocks at server side.

Tests: 956/956 root tools, 0 regressions. LEFTHOOK=0 used per quirk #111.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 06:46:55 +03:00

17 KiB
Raw Blame History

brain-retro #7 — 2026-05-27 03:55 UTC

Период: 2026-05-26 16:23 UTC (после retro #6) → 2026-05-27 03:53 UTC (≈11.5 ч). Эпизодов: 23 (после dedupe + observer-errors filter; observerErrors=0). Задач (грouping): 9. Reviewer: batch mode (23 ≥ 20), Opus 4.7 / ProxyAPI, 23/23 reviewed, 0 errors, wall-clock 55.6с.


1. Семь обязательных цифровых срезов

[1] Path-type breakdown

path_type count %
improvised 22 95.7%
regulated 1 4.3%

22 эпизода из 23 — improvised (никаких boundaries_applied, никаких skill_invoked). Это выше нормы для retro #6 (там было ≈85% improvised). Сигнал: 11.5 часов почти без вызова навыков.

[2] node_chosen distribution

node_chosen count %
direct 21 91.3%
superpowers:finishing-a-development-branch 1 4.3%
subagent-driven-development 1 4.3%

Из 23 turns только 2 использовали навык. Один из них (subagent-driven-development на ambiguous «ставь в пендинг») reviewer пометил как wrong_node — навык вызван не по адресу.

recommended_node count %
NULL 21 91.3%
#25 (Semgrep) 2 8.7%

Классификатор почти ничего не рекомендовал — большинство turns короткие или conversation-типа. 2 раза рекомендовал #25 Semgrep (security/analysis-задачи) — оба раза проигнорировано.

[4] GAP «рекомендован но выбран direct»

recommended chosen count rework rate этого подмножества
#25 direct 2 0% (оба soft_success после review)

Маленькая выборка — 2 эпизода, оба ушли в soft_success. Игнор рекомендации Semgrep не вызвал rework на этом окне.

[5] outcome × node_chosen group

группа total success soft_success rework blocked rework_rate
skill_used 2 0 1 0 1 50%
direct_no_rec 19 6 6 4 3 36.8%
direct_ignored_rec 2 0 2 0 0 0%

Главный пул — direct_no_rec (19 эпизодов): rework+blocked = 7/19 = 36.8%. Это плохо. skill_used = 2 эпизода, оба problematic (1 blocked — wrong_node subagent-driven-development).

[6] classifier_output presence by source

source count %
prefilter 9 39.1%
llm 8 34.8%
regex 3 13.0%
cache 1 4.3%
NULL 2 8.7%

Классификатор здоров — NULL = 8.7% << 30% порога. Distribution разумный (prefilter+regex = быстрые пути 52%, llm для сложных 35%). На retro #6 был сломан (NULL >> 30%), теперь починен.

[7] Per-classification trigger-match + via-skill

classification total via_skill via_skill_rate
conversation 9 0 0%
ambiguous 4 0 0%
no_skill_found 3 1 33% (wrong-node)
analysis 2 0 0%
skill 1 0 0%
chain 1 0 0%
release 1 1 100%
other 1 0 0%
unknown 1 0 0%

Conversation 9/23 — здесь direct ок (это болтовня). Ambiguous 4/23 + no_skill_found 3/23 — здесь должна была быть clarification request, а не direct-attempt (см. кандидаты ниже). chain 1/23 — единственный кейс «chain», ушёл в direct → reviewer flag wrong_chain_order.


2. Reviewer-агент: распределение качества

node_quality

judgment count %
disputable 12 52.2%
correct 9 39.1%
wrong_node 2 8.7%

error_root_cause

cause count
n/a (без ошибок) 13
wrong_skill 5
external_failure 4
wrong_chain_order 1

agent_self_assessment_accuracy

status count
no_self_assessment 18 (78%)
accurate 5
inaccurate 0

Покрытие self_assessment 22% — критически низкое. На retro #6 покрытие было выше; что-то его сломало (вероятно — hook order правлен 26.05 в 9b7de8bf).

Alternative-better suggestions reviewer'а

recommended_alt count контекст
#25 Semgrep 2 анализ кода
#8 gitleaks 1 перед push
#3 GitHub MCP 1 «пуш и обнови пилот» (NLU gap)
claude-md-management 1 «обнови мозг/пуш»

3. Outcome-распределение (после review)

outcome_reviewed count %
soft_success 9 39%
success 6 26%
rework 4 17%
blocked 4 17%

Проблемная доля 8/23 = 35% (rework+blocked). На retro #6 эта доля была ≈30%; небольшой рост.

degradedCount = 2 (классификатор был в degraded-режиме в 2 turns — нормально на старте сессии).


4. Каузальные цепочки (от → к, общие файлы)

4 цепочки выявлены автоматически:

  1. 269ae4d0 → 1b0f3090 — общий settings.json (кросс-сессионный — настройки router-gate перетряхнули, затем восстановили).
  2. 1b0f3090 → 1b0f3090 ×3 — длинная задача внутри одной сессии 1b0f3090 (5 episodes), общий router-state-1b0f3090.json через все 4 turns.

Сессия 1b0f3090 — самая длинная задача периода (5 эпизодов из 7 в task ref #3+#4). Один из 5 turns — blocked (recovery «обнови мозг/пуш», 15 tool calls, 81k output tokens — reviewer пометил mistake_should_not_start).


5. Reviewer-narrative — 8 problematic episodes (детально)

# task cls outcome reviewer error_root_cause reviewer alt
1 135a4adf conversation rework external_failure (hook errors) n/a
2 267fd4dc chain rework wrong_chain_order #8→#3 chain skipped
3 1b0f3090 ambiguous blocked n/a (correct: ask user) n/a
4 267fd4dc conversation rework external_failure n/a
5 b82510c7 ambiguous rework wrong_skill #3 GitHub MCP («пуш и обнови пилот»)
6 b82510c7 no_skill_found blocked n/a (correct: ask user) n/a
7 269ae4d0 ambiguous blocked wrong_skill claude-md-management («обнови мозг/пуш» — 15 tool calls вместо clarification)
8 b11f6b8d no_skill_found blocked wrong_skill (ask user, not subagent-driven-development)

Главный паттерн: на ambiguous/short prompts agent не просит уточнения, а пытается угадать. В 3 из 4 ambiguous/no_skill_found эпизодов это привело к ошибке.


6. Sanity-check (ответы заказчика)

вопрос ответ
Были моменты, когда я выбрал direct, хотя нужен был навык? «Да, часто»
Качество за период (5 blocked + 2 degraded из 23)? «Плохо — очевидные сбои»
Что наблюдатель должен был засечь, но не засёк? «Вроде нет»

Меta-расхождение: заказчик сказал «наблюдатель ничего не пропустил», но reviewer нашёл 5 wrong_skill cases. → Наблюдатель засёк, заказчик не знал. Заявка на улучшенный surface STATUS.md (см. кандидаты).

Файл ответов: docs/observer/sanity-checks/2026-05-27.json.


7. Self-retrospect trigger

docs/observer/.self-retrospect-counter.json: episodes_since_last = 542 (был 519, +23 за период). Порог 50 превышен на порядок — рекомендую запустить /self-retrospect при первом удобном моменте.


8. Cost report

~/.claude/runtime/cost-daily.jsonотсутствует (cost tracking не активирован per-call). Из analyzer.costTotals:

метрика tokens
classifier_input 220
classifier_output 4 431
self_assessment_input 0 (покрытие 22%)
self_assessment_output 0
reviewer_input 0 (batch-reviewer не пишет в costTotals)
reviewer_output 0

Reviewer batch off-stream cost — ≈$1.50 (23 эпизода × Opus 4.7 ≈ avg 1.5к in / 0.4к out per call).


9. Candidates for owner review

⚠️ Это кандидаты, не действия. Заказчик решает что применить.

C1 — NLU gap: транслит-сленг → не маппится в правильный навык

Сигнал: «пуш и обнови пилот» → recommended_node = NULL → direct (15 tool calls, rework). Reviewer: правильно было #3 GitHub MCP. Аналогично — «обнови мозг/пуш» (claude-md-management не вызван).

Rationale: classifier хорошо парсит формальные слова («deploy», «push»), но плохо — русский транслит-сленг («пуш», «пилот», «мозг», «эталон»). Между тем ПИЛОТ.md / ЭТАЛОН.md / обнови мозг = MEMORY.md — это формализованные паттерны заказчика (зафиксированы в MEMORY.md recovery draft).

Suggested action (one of):

  • (A) Расширить prefilter словарь tools/observer-prefilter.mjs — добавить mapping «пуш+пилот → #3+deploy», «обнови мозг → claude-md-management», «обнови эталон → file Edit ЭТАЛОН.md», «обнови пилот → file Edit ПИЛОТ.md».
  • (B) Добавить в classifier system-prompt список 8-10 known транслит-фраз заказчика.
  • (C) Не править ничего — заказчик использует эти фразы редко, частота не оправдает усложнения.

Rejection-option: заказчик решает что транслит-NLU не приоритет; держать cls: теги в промпте как явный override.


C2 — Ambiguous/short prompts: правило «ask before start»

Сигнал: 3 из 4 ambiguous/no_skill_found эпизодов = rework/blocked. Reviewer 2× флаг mistake_should_not_start: «обнови мозг/пуш» (15 tool calls вместо clarification) и «ставь в пендинг» (subagent-driven-development вместо clarification).

Rationale: при classifier_output.task_type ∈ {ambiguous, no_skill_found} AND prompt_length < 30 chars AND нет cls: тега — почти всегда правильно спросить, а не пытаться. Сейчас agent чаще пробует угадать (один раз с 15 tool calls).

Suggested action (one of):

  • (A) Hook router-tool-gate уже блокирует на no_skill_found — расширить на ambiguous + len<30 тоже.
  • (B) Skill clarification-request (новый, минимальный) — обязательно вызывать на ambiguous/no_skill_found+short.
  • (C) Дописать в ~/.claude/CLAUDE.md правило: «на коротких ambiguous prompts — first action = AskUserQuestion».

Rejection-option: заказчик согласен с rework как ценой за скорость на коротких задачах.


C3 — Self-assessment coverage 22% (было выше)

Сигнал: 18/23 эпизодов без self_assessment (78%). На retro #6 покрытие было выше. Скорее всего сломалось при правке hook order 26.05 (commit 9b7de8bf).

Rationale: без self_assessment reviewer не может оценить «agent_self_assessment_accuracy» → теряем сигнал самооценки.

Suggested action (one of):

  • (A) Найти что именно изменилось в hook order, восстановить self_assessment trigger.
  • (B) Принять снижение покрытия как trade-off за упрощённый hook stack.

Rejection-option: заказчик согласен жить без self_assessment до следующего больного эпизода.


C4 — Меta: «вроде нет» от заказчика vs 5 wrong_skill от reviewer

Сигнал: заказчик не заметил wrong_skill кейсы, которые reviewer нашёл. STATUS.md не surface'ит «wrong_skill last 24h» — заказчик не видит то, что наблюдатель видит.

Rationale: brain governance ADR-011 §16 говорит «evidence-collection, not enforcement», но evidence должен быть видимым.

Suggested action (one of):

  • (A) tools/status-md-generator.mjs — добавить блок «Reviewer findings last 24h» (count wrong_skill / wrong_chain_order / external_failure).
  • (B) Опционально — push-notification контроллеру при wrong_skill ≥ 3 за день.
  • (C) Принять, что заказчик не должен следить за этим — оставить только в /brain-retro.

Rejection-option: /brain-retro раз в неделю достаточно.


C5 — Chain #8 (gitleaks) → #3 (GitHub push) skipped

Сигнал: classifier рекомендовал chain #8→#3 (gitleaks верификация → push), agent ушёл direct, chain_quality missing_step. Reviewer: «skipping #8 verification before push is risky given pending .gitleaksignore».

Rationale: это повторяющийся паттерн (см. memory feedback_gitleaks_cross_branch.md — pre-push gitleaks уже блокировал push'и из-за cross-branch fingerprint'а; ущерб от пропуска — низкий, но регулярный).

Suggested action (one of):

  • (A) Hook enforce-verify-before-push (есть в feedback_enforce_verify_before_push.md) — расширить на gitleaks verify timestamp.
  • (B) Добавить в memory entry «при push после правки нормативки/спеков — обязательно git-leaks --staged перед push».
  • (C) Принять: gitleaks pre-push уже блокирует на сервере, дублирование избыточно.

Rejection-option: существующий pre-push gitleaks достаточен.


10. Что не правится автоматически

Per skill §«Behavioral rule reminders» — этот retro никакие правки не вносит. Все 5 кандидатов выше — material for owner decision. Заказчик может выбрать «все», «никакие», «только C1+C3» — любым способом.


11. Цепочки и связи с предыдущим retro

retro #6 (2026-05-26 16:23) — закрыл проблему «classifier сломан» (NULL > 30%) фиксом G/H/A1/A2/B3/C1/C3. retro #7 подтверждает: NULL = 8.7%, классификатор здоров.

Новые проблемы которые видит retro #7:

  • NLU gap на транслит — не было в retro #6 (был мёртвый классификатор, NLU маскировался).
  • «ask before start» discipline — старый паттерн, продолжает.
  • Self-assessment coverage drop — регрессия от retro #6 (вероятно из-за hook order правки).
  • Reviewer judgments routing_judgment = NULL для всех 23 — мелочь schema-mismatch в reviewer prompt vs анализатор (reviewer использует node_quality/error_root_cause вместо routing_judgment); analyzer ожидает старое поле. Не требует действия — обе версии данных есть.

Подпись: контроллер Opus 4.7, 1M context, brain-retro skill v3 (subagent + batch hybrid), 2026-05-27 03:55 UTC.