docs(brain): spec v1.0 → v1.1 — factor analysis amendment (routing_decision + primary_rationale)
User-requested перед запуском суб-агента: observer должен фиксировать не только факт выбора узла, но и причину — чтобы был возможен факторный анализ через /brain-retro. Изменения §5.2: - 4 обязательных поля → 5 (+primary_rationale на эпизод-уровне). - Новое событие routing_decision в массиве events[] (1 на каждое решение роутера в сессии; для цепочки из N — N событий). - Новая под-секция §5.2.1 — структура 7 полей (step / node_chosen / triggers_matched / candidates_considered / boundaries_applied / hard_floor / task_classification). primary_rationale — копия первого routing_decision для дешёвой агрегации без чтения events[]. - Полный JSON-пример эпизода с цепочкой из 2 узлов. Изменения §5.5: - /brain-retro aggregation расширен новой секцией «Факторная матрица»: таблица «узел × фактор × частота» + cross-tab «фактор × фактор». 5 осей факторов: triggers / dropped_because / boundaries / hard_floor.rules / task_classification. Эффект: /brain-retro теперь может выдавать утверждения уровня «#55 выбрался против #53 по ADR-009 7 раз и по triggers-match 5 раз», а не просто «#55 использован 12 раз». Это closes гэп факторного анализа. Header bump v1.0 → v1.1. ADR-011 текст в плане Task A1 будет обновлён следующим коммитом (план amendment). Связано:dd5bded(spec v1.0),ca93cf7(plan v1.0). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Brain governance design — router-only + observer scope B + 4 контролёра
|
||||
date: 2026-05-19
|
||||
status: design (approved by user — awaiting written-spec user review per brainstorming flow)
|
||||
version: 1.1
|
||||
status: design (approved by user; v1.1 amendment 2026-05-19 — structured routing_decision + primary_rationale for factor analysis per user request before subagent execution)
|
||||
author: Дмитрий (заказчик) + Claude (Opus 4.7) via superpowers:brainstorming
|
||||
related:
|
||||
- docs/discovery/2026-05-18-system-audit-brain.md
|
||||
@@ -188,7 +189,7 @@ Observer **только пишет evidence, не вмешивается**. Ни
|
||||
|
||||
**Action**: append одной JSONL-строки в `docs/observer/episodes-YYYY-MM.jsonl` (rotation помесячно — простое именование, никакой инфраструктуры).
|
||||
|
||||
**4 обязательных поля**:
|
||||
**5 обязательных полей** (v1.1 — factor analysis amendment 2026-05-19):
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|---|---|---|
|
||||
@@ -196,18 +197,66 @@ Observer **только пишет evidence, не вмешивается**. Ни
|
||||
| `timestamps` | `{started_at, ended_at}` ISO-8601 | Начало и конец сессии (для time-burn анализа) |
|
||||
| `path_type` | enum: `regulated` / `improvised` / `alternative` / `mixed` | Пошёл ли роутер по канонической связке L1–L12, импровизировал, ушёл альтернативой или смешанно |
|
||||
| `outcome` | enum: `success` / `partial` / `failure` / `aborted` | Итог сессии |
|
||||
| `primary_rationale` | structured object (см. §5.2.1) | **Главное решение роутера на эпизод** — структурированные факторы выбора первичного узла. Дублирует первое `routing_decision` событие в `events[]` для быстрых агрегатов без чтения массива. |
|
||||
|
||||
**Структурированные события** (опционально, массив `events[]`):
|
||||
|
||||
| Тип | Описание |
|
||||
|---|---|
|
||||
| `routing_decision` | **Структурированный факт выбора узла** — 7 полей (см. §5.2.1). Записывается один раз на каждое решение роутера в сессии (если цепочка из N узлов — N событий с возрастающим `step`). Это основа факторного анализа. |
|
||||
| `hook_fired` | Сработал хук (skill-marker, skill-check, state-guard, postcompact, verifier, economy-mode, security-guidance, ruflo-* — текущая 6+ компонентная архитектура) |
|
||||
| `chain_divergence` | Роутер пошёл не по канонической связке, хотя совпадение триггеров было |
|
||||
| `skill_invoked` | Инвокирован skill — записать `skill_id` + `reason` |
|
||||
| `chain_divergence` | Роутер пошёл не по канонической связке, хотя совпадение триггеров было. Поля: `expected_chain` (L1–L12 ID), `chosen_nodes[]`, `reason_summary`. Дополняет (не подменяет) `routing_decision` на этом же шаге. |
|
||||
| `skill_invoked` | Инвокирован skill — поля `skill_id` + `reason` (free-text). Для факторного анализа выбора skill'а — используется отдельный `routing_decision` события с тем же `step`. |
|
||||
| `error` | Возникла ошибка — записать `class` (например `quirk:72`) + `recovery_action` |
|
||||
| `confusion_marker` | Заказчик/Claude пометил место как «запутано» (вручную через TODO-метку в промпте) |
|
||||
| `time_burn` | Большой блок времени потрачен на одну операцию (порог: >5 минут на single tool-call) |
|
||||
|
||||
#### §5.2.1. Структура `routing_decision` и `primary_rationale`
|
||||
|
||||
Оба объекта используют **одинаковую схему 7 полей** — `primary_rationale` это **копия первого `routing_decision`** в эпизоде, поднятая на уровень эпизода для дешёвой агрегации.
|
||||
|
||||
| Поле | Тип | Обязательное | Описание |
|
||||
|---|---|---|---|
|
||||
| `step` | int | yes (для events) / нет в primary_rationale | Номер решения в эпизоде (1, 2, 3 ...). Для primary_rationale — всегда 1. |
|
||||
| `node_chosen` | string (`#NN` или `<name>`) | yes | Выбранный узел из Tooling Прил. Н §4.X. |
|
||||
| `triggers_matched` | array of string | yes | Список триггеров из реестра, которые сработали (например `["discovery", "интервью", "JTBD"]`). Empty `[]` допустим если решение принято исключительно по hard-floor. |
|
||||
| `candidates_considered` | array of `{node_id, dropped_because}` | yes | Узлы, которые роутер рассмотрел и отбросил. Каждый элемент содержит ID отброшенного узла и **строку причины** (ADR-ref / specificity / hard-floor / manual). Empty `[]` если альтернатив не было. |
|
||||
| `boundaries_applied` | array of string | yes | ADR-ссылки или PSR_v1 R-ссылки, применённые для разруливания (например `["ADR-009", "PSR_v1 R15.3"]`). Empty `[]` если границ не применялось. |
|
||||
| `hard_floor` | `{invoked: bool, rules: string[]}` | yes | Информация о hard-floor §12/§14/§15. Если применилось — `invoked: true` и в `rules` перечислены сработавшие правила (например `["Pravila §12"]`). |
|
||||
| `task_classification` | string | yes | Категория задачи на момент решения (`discovery` / `brainstorm` / `writing-plan` / `TDD` / `debug` / `arch-decision` / `refactor` / `docs` / `sync` / `migration` / `commit` / `review` / `other`). |
|
||||
|
||||
**Пример** (запись эпизода с цепочкой из 2 узлов):
|
||||
|
||||
```json
|
||||
{
|
||||
"task_id": "2026-05-19-brain-governance-plan",
|
||||
"timestamps": {"started_at": "2026-05-19T04:00:00+03:00", "ended_at": "2026-05-19T04:35:00+03:00"},
|
||||
"path_type": "regulated",
|
||||
"outcome": "success",
|
||||
"primary_rationale": {
|
||||
"step": 1,
|
||||
"node_chosen": "superpowers:brainstorming",
|
||||
"triggers_matched": ["brainstorm", "design"],
|
||||
"candidates_considered": [
|
||||
{"node_id": "superpowers:writing-plans", "dropped_because": "specificity: brainstorm предшествует writing-plans"}
|
||||
],
|
||||
"boundaries_applied": ["PSR_v1 R15.3"],
|
||||
"hard_floor": {"invoked": true, "rules": ["Pravila §12"]},
|
||||
"task_classification": "brainstorm"
|
||||
},
|
||||
"events": [
|
||||
{"kind": "routing_decision", "step": 1, "node_chosen": "superpowers:brainstorming", "triggers_matched": ["brainstorm", "design"], "candidates_considered": [...], "boundaries_applied": ["PSR_v1 R15.3"], "hard_floor": {"invoked": true, "rules": ["Pravila §12"]}, "task_classification": "brainstorm"},
|
||||
{"kind": "routing_decision", "step": 2, "node_chosen": "superpowers:writing-plans", "triggers_matched": ["writing-plans"], "candidates_considered": [], "boundaries_applied": [], "hard_floor": {"invoked": true, "rules": ["Pravila §12"]}, "task_classification": "writing-plan"},
|
||||
{"kind": "skill_invoked", "skill_id": "superpowers:writing-plans", "reason": "terminal skill brainstorming-flow"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Граница**: `primary_rationale` НЕ дублирует все шаги цепочки — только **первое** решение. Полная цепочка читается через `events[].kind=="routing_decision"`. Это даёт два уровня агрегации:
|
||||
|
||||
1. **Дешёвая верхнеуровневая** (читай только `primary_rationale` каждого эпизода): «какой узел чаще всего открывает сессию», «какие факторы доминируют в первом решении».
|
||||
2. **Глубокая факторная** (читай все `routing_decision` событий): «какие пары факторов чаще всего разруливают конкретные конфликты», «какие ADR-границы выходят на первый план».
|
||||
|
||||
### 5.3. Опциональные MD-заметки
|
||||
|
||||
**Путь**: `docs/observer/notes/YYYY-MM-DD-<slug>.md`. Создаются **только если у сессии есть качественная история, которая не помещается в JSONL**: длинный narrative разбора, скриншот ошибки, цепочка из 5+ узлов с границами и т.д.
|
||||
@@ -239,6 +288,13 @@ Observer **только пишет evidence, не вмешивается**. Ни
|
||||
- Топ-связки L1–L12 (использованы) + новые связки (path_type=improvised, повторившиеся ≥2 раз).
|
||||
- Top `error` classes + recovery-патерны.
|
||||
- `chain_divergence` cases — где роутер ушёл с канонической связки.
|
||||
- **Факторная матрица** (v1.1+ amendment): по каждому узле в `routing_decision` событиях — частоты по 5 осям факторов:
|
||||
- `triggers_matched` → какие триггеры чаще всего ведут к этому узлу
|
||||
- `candidates_considered.dropped_because` → какие альтернативы чаще всего отбрасываются и по какой причине
|
||||
- `boundaries_applied` → какие ADR-границы / R-rules чаще всего разруливают
|
||||
- `hard_floor.rules` → как часто узел вынуждается hard-floor §12/§14/§15
|
||||
- `task_classification` → в каких классах задач узел доминирует
|
||||
Output — таблица «узел × фактор × частота» + cross-tab «фактор × фактор» для каждой пары факторов (например «ADR-009 ↔ triggers_matched=['discovery']» — 8 раз).
|
||||
3. Возвращает **кандидатов на корректировку нормативки**:
|
||||
- Новая связка L13+ (если improvised повторился ≥2 раз с success).
|
||||
- Граница X ↔ Y нуждается в ADR-уточнении (если chain_divergence повторился).
|
||||
|
||||
Reference in New Issue
Block a user