144 lines
14 KiB
Markdown
144 lines
14 KiB
Markdown
---
|
||
work_item: ORCH-098
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 01 — BRD (бизнес-требования): ORCH-098 — FND: машинный журнал уроков (структурированная база отклонений)
|
||
|
||
Work Item: **ORCH-098** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
## 1. Бизнес-контекст и проблема
|
||
|
||
Оркестратор уже автономно проводит задачи через конвейер (ORCH-54), но **развивает** платформу
|
||
по-прежнему вручную связка Слава+Стрим: ловим инциденты → формулируем уроки → заводим задачи.
|
||
Уроки сегодня живут **свободным текстом** в `memory/` — они не машиночитаемы, по ним нельзя
|
||
считать паттерны, нельзя приоритизировать, нельзя автоматически предлагать улучшения.
|
||
|
||
ORCH-098 — шаг 1 эпика саморазвития (`docs/epics/self-evolution.md`, **домен 0 «Фундамент», F2**,
|
||
ORCH-8). Это **«топливо» вертикали-двигателя** (петля самообучения 8A): формализовать свободный
|
||
текст в **машинную структурированную таблицу отклонений конвейера**. Каждый урок — запись с
|
||
полями для машинного анализа паттернов. Журнал — фундамент, на котором позже встанут
|
||
ретроспективщик (E2), приоритизатор RICE (E3) и Стрим как потребители.
|
||
|
||
**Установленные факты-источники сигналов («уроков»)** — из памяти орка (инциденты 06–09.06) и §8A
|
||
эпика:
|
||
- Провал гейта (BLOCKED / FAILED / REQUEST_CHANGES).
|
||
- **Ручное вмешательство человека — самый ценный сигнал** (каждый ручной пинок = дыра автономности).
|
||
- Ретраи, откаты деплоя, таймауты агентов.
|
||
- Ложные срабатывания гейтов (исторический пример: substring `PASS` в `check_tests_passed`).
|
||
- «Деплой SUCCESS, а прод не работает» (урок ET-8); транзиенты (Gitea `405`, Anthropic `Overloaded`).
|
||
|
||
**Решение Славы 10.06 (ОБЯЗАТЕЛЬНО учесть на этапе схемы):** схема журнала ДОЛЖНА **с самого
|
||
начала** нести поля для будущей **АТРИБУЦИИ** урока (иначе потом переделывать схему на живой
|
||
общей прод-БД). Атрибуция (`platform-level` / `project-level` / `both` / `unknown`), целевой
|
||
проект и целевой домен улучшения — это §8A эпика «platform-level vs project-level». При автозаписи
|
||
поля атрибуции могут быть пустыми/`unknown` (классификацию позже ставит ретроспективщик/Стрим), но
|
||
**колонки в схеме должны существовать сразу** — аддитивные, нуллабельные.
|
||
|
||
**Связь со слоями наблюдения (§2 эпика):** деградация продукта (слой 3, урок ET-8) — один из типов
|
||
урока; журнал должен уметь его хранить с атрибуцией `platform`/`project`.
|
||
|
||
## 2. Объём (scope)
|
||
|
||
### В объёме
|
||
- Аддитивная идемпотентная таблица БД `lessons` для структурированных уроков со всеми полями
|
||
контекста, анализа, статуса **и атрибуции** (колонки атрибуции — сразу, нуллабельные).
|
||
- Leaf-модуль `src/lessons.py` (never-raise, kill-switch) + helper записи урока.
|
||
- **Автозапись** ≥2–3 типов отклонений из кода через best-effort точки врезки в
|
||
`stage_engine.py` / `merge_gate.py` / `launcher.py` (провал гейта/откат, HOLD, транзиент-ретрай).
|
||
- **Read-only выборка** уроков (HTTP-эндпоинт + блок в `GET /queue`) — для будущего
|
||
ретроспективщика и Стрим.
|
||
- **Ручная запись** урока (HTTP-эндпоинт / helper) — Стрим/оператор кладёт урок руками.
|
||
- Доки (CLAUDE.md / architecture README / ADR) + `CHANGELOG.md`.
|
||
|
||
### Вне объёма
|
||
- **Анализ паттернов / ретроспективщик (E2)** — отдельная задача-потребитель журнала.
|
||
- **Приоритизатор RICE (E3)** — отдельная задача.
|
||
- **Автоматическая классификация атрибуции** — её ставит ретроспективщик/человек позже; здесь —
|
||
только колонки и возможность проставить значение руками/через update.
|
||
- **Банк идей (D4 / идеатор, E5)** — отдельный реестр, НЕ путать с журналом уроков.
|
||
- **Слой-3 детекция здоровья продукта** (мониторинг задеплоенного приложения) — отдельная
|
||
D4/D5-способность; журнал лишь умеет **хранить** такой урок, когда детектор появится.
|
||
- Изменение `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключей / любых
|
||
существующих таблиц.
|
||
- Миграция исторических уроков из `memory/` (ручной разовый импорт — вне объёма).
|
||
|
||
## 3. Заинтересованные стороны
|
||
- **Заказчик:** Слава (требование атрибуции 10.06 — нормативно).
|
||
- **Прямой потребитель (будущее):** агент-ретроспективщик E2, приоритизатор E3, Стрим (ручной
|
||
разбор).
|
||
- **Затрагивается:** self-hosting прод-инстанс orchestrator (общая БД и очередь с enduro-trails) —
|
||
enduro **не должен быть затронут** (аддитивность, never-raise).
|
||
- **Принимает результат:** reviewer/tester конвейера + Слава.
|
||
|
||
## 4. Бизнес-требования (BR)
|
||
|
||
- **BR-1 — Структурированная таблица уроков.** Аддитивная, идемпотентная (`CREATE TABLE IF NOT
|
||
EXISTS`) таблица `lessons` на общей прод-БД с полями: тип отклонения; контекст
|
||
(work_item/task/стадия/агент/repo); корневая причина (если известна); предложенное улучшение
|
||
(если есть); статус (`new`/`in_progress`/`closed`/`linked`) + связанная задача; timestamp.
|
||
- **BR-2 — Поля атрибуции с самого начала.** Схема несёт **сразу** нуллабельные колонки:
|
||
`attribution` (`platform`/`project`/`both`/`unknown`), `target_repo` (кого касается:
|
||
`orchestrator`/`enduro-trails`/др.), `target_domain` (домен улучшения:
|
||
`reliability`/`quality`/`economy`/`features`/`scale`). При автозаписи допустимо пусто/`unknown`.
|
||
- **BR-3 — Автозапись ≥2–3 типов отклонений.** Из кода, best-effort, в детерминированных
|
||
choke-point: (а) провал гейта / откат на `development` (reviewer REQUEST_CHANGES, tester FAIL,
|
||
staging/deploy FAILED), (б) HOLD merge-актора / regression-guard HOLD, (в) транзиент-ретрай
|
||
(Gitea-merge `405`/`5xx`, Anthropic `Overloaded`/agent-timeout requeue). Дополнительно желательно
|
||
(г) post-deploy `DEGRADED` (урок «деплой OK / прод сломан», слой-3, ET-8) с атрибуцией.
|
||
- **BR-4 — Read-only выборка.** HTTP-эндпоинт `GET /lessons` (фильтры: тип/статус/repo/work_item,
|
||
лимит) + read-only блок `lessons` в `GET /queue` (сводка). Только чтение.
|
||
- **BR-5 — Ручная запись.** HTTP-эндпоинт `POST /lessons` (+ публичный helper) — оператор/Стрим
|
||
кладёт урок руками, в т.ч. с проставленной атрибуцией.
|
||
- **BR-6 — Обновление урока.** Возможность сменить статус / проставить атрибуцию / привязать
|
||
задачу после создания (helper/эндпоинт `POST /lessons/{id}` или поля в `POST /lessons`) — чтобы
|
||
ретроспективщик/человек позже классифицировал автозаписанный `unknown`.
|
||
|
||
## 5. Нефункциональные требования (NFR)
|
||
|
||
- **NFR-1 — never-raise (критично, self-hosting).** Сбой записи/чтения урока **никогда** не роняет
|
||
и не тормозит конвейер. Любая ошибка детектора/записи → лог WARNING + продолжение основного
|
||
потока. Журнал — наблюдатель, не участник пайплайна.
|
||
- **NFR-2 — Kill-switch.** Флаг `lessons_enabled` (env `ORCH_LESSONS_ENABLED`). `False` →
|
||
автозапись и эндпоинты инертны (нулевая регрессия, поведение конвейера байт-в-байт прежнее).
|
||
- **NFR-3 — Аддитивность / изоляция enduro.** Только новая таблица + новый leaf + новые эндпоинты +
|
||
тонкие врезки. `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключи / схема
|
||
существующих таблиц — **байт-в-байт не тронуты**. Общая БД: enduro-trails не затронут.
|
||
- **NFR-4 — Restart-safe / идемпотентность таблицы.** `CREATE TABLE IF NOT EXISTS` + `_ensure_column`
|
||
(паттерн `repo_freeze`/`coverage_baseline`) — безопасно на живой БД, повторный старт без эффекта.
|
||
- **NFR-5 — Лёгкость.** Запись — один `INSERT`, чтение — простые `SELECT` (общий хост впритык:
|
||
RAM 171Mi free, диск 92%). Никаких фоновых потоков/сканов.
|
||
- **NFR-6 — Схема-forward-proof.** Колонки атрибуции добавлены сразу (BR-2), чтобы не
|
||
переделывать схему на живой БД, когда появится ретроспективщик.
|
||
- **NFR-7 — Self-hosting безопасность.** Модуль только пишет/читает БД и отдаёт JSON — не
|
||
деплоит, не рестартит прод, не трогает `main`, не порождает процессы/сеть.
|
||
|
||
## 6. Допущения и ограничения
|
||
- Журнал уроков — **исключение** из правила «наблюдатель отделён от наблюдаемого» (§2 эпика): это
|
||
историческая память петли, не realtime-мониторинг → допустимо в БД орка; запись best-effort.
|
||
- Точки автозаписи привязаны к существующим choke-point: `stage_engine._handle_qg_failure_rollbacks`
|
||
(откаты), `merge_gate` (HOLD/transient-классификатор ORCH-093), `launcher` (timeout/requeue
|
||
транзиентов). Архитектор уточняет точный набор и сигнатуры врезок.
|
||
- Набор значений `lesson_type` / `attribution` / `target_domain` — конвенция (строковые слаги),
|
||
не enum-констрейнт БД (forward-compatible; новый тип не требует миграции).
|
||
- Общая прод-БД с enduro: любое поле repo-scoped, фильтрация на уровне выборки.
|
||
|
||
## 7. Критерии успеха
|
||
Таблица `lessons` создаётся идемпотентно на старте; автозаписаны ≥2–3 типа отклонений из реального
|
||
прогона; `GET /lessons` и `POST /lessons` работают; атрибутивные колонки присутствуют и
|
||
проставляемы; kill-switch выключает всё без регрессии; `pytest tests/ -q` зелёный; доки+CHANGELOG
|
||
обновлены. Детальные PASS/FAIL — `03-acceptance-criteria.md`.
|
||
|
||
## 8. Риски
|
||
- Врезка детектора в горячий путь конвейера → риск регрессии при сбое записи. Митигация: NFR-1
|
||
never-raise + kill-switch.
|
||
- Рост таблицы со временем (автозапись на каждом откате/ретрае). Митигация: лёгкие строки;
|
||
будущая ретенция — вне объёма, отметить в `10-tech-risks.md` (архитектор).
|
||
- Недооформленная схема атрибуции → переделка на живой БД. Митигация: BR-2/NFR-6 (колонки сразу).
|
||
- Детали и архитектурные развилки (точные точки врезки, индексы, дедуп автозаписей) — задача
|
||
архитектора (`06-adr/`, `10-tech-risks.md`).
|