77 lines
5.5 KiB
Markdown
77 lines
5.5 KiB
Markdown
---
|
||
work_item: ORCH-098
|
||
stage: architecture
|
||
author_agent: architect
|
||
status: proposed
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 08 — Требования к данным: ORCH-098 — машинный журнал уроков `lessons`
|
||
|
||
Work Item: **ORCH-098** · Repo: **orchestrator** · Стадия: architecture
|
||
|
||
> When-applicable: задача **добавляет** одну таблицу на общую прод-БД. Схемы существующих таблиц —
|
||
> не затрагиваются.
|
||
|
||
## Изменения схемы БД
|
||
|
||
**Новая аддитивная таблица `lessons`** + три индекса, создаются идемпотентно в `db.init_db()`
|
||
(`CREATE TABLE IF NOT EXISTS` / `CREATE INDEX IF NOT EXISTS`), restart-safe (паттерн `repo_freeze`,
|
||
`coverage_baseline`). На уже существующей таблице новые/будущие колонки добавляются через
|
||
`_ensure_column(conn, "lessons", "<col>", "<decl>")` (`src/db.py:341`) — forward-safe, без миграции
|
||
данных. DDL — см. ADR-001 D1.
|
||
|
||
Существующие таблицы (`tasks`/`jobs`/`agent_runs`/`events`/`job_deps`/`repo_freeze`/
|
||
`coverage_baseline`/`tracker_messages`) — **байт-в-байт не тронуты** (NFR-3, AC-8).
|
||
|
||
## Новые/изменённые сущности
|
||
|
||
Сущность **`lesson`** — одна запись структурированного отклонения конвейера. Колонки:
|
||
|
||
| Колонка | Тип | Null | Назначение |
|
||
|---|---|---|---|
|
||
| `id` | INTEGER PK AUTOINCREMENT | — | суррогатный ключ |
|
||
| `created_at` | TEXT `DEFAULT datetime('now')` | NOT NULL | момент записи |
|
||
| `updated_at` | TEXT | NULL | момент последнего `update` |
|
||
| `lesson_type` | TEXT | NOT NULL | slug-тип (`gate_failure`/`merge_hold`/`transient_retry`/`deploy_degraded`/…) |
|
||
| `work_item_id` | TEXT | NULL | контекст: задача (`ORCH-NNN`/`ET-NNN`) |
|
||
| `task_id` | INTEGER | NULL | контекст: внутренний id задачи |
|
||
| `stage` | TEXT | NULL | контекст: стадия конвейера |
|
||
| `agent` | TEXT | NULL | контекст: агент-роль |
|
||
| `repo` | TEXT | NULL | контекст: репозиторий, **разрез выборки** |
|
||
| `root_cause` | TEXT | NULL | анализ: корневая причина (если известна) |
|
||
| `suggestion` | TEXT | NULL | анализ: предложенное улучшение (если есть) |
|
||
| `status` | TEXT `DEFAULT 'new'` | NOT NULL | `new`/`in_progress`/`closed`/`linked` |
|
||
| `related_task` | TEXT | NULL | связанная заведённая задача |
|
||
| `attribution` | TEXT | **NULL** | **АТРИБУЦИЯ:** `platform`/`project`/`both`/`unknown` |
|
||
| `target_repo` | TEXT | **NULL** | **АТРИБУЦИЯ:** кого касается улучшение |
|
||
| `target_domain` | TEXT | **NULL** | **АТРИБУЦИЯ:** `reliability`/`quality`/`economy`/`features`/`scale` |
|
||
| `source` | TEXT | NULL | `auto` (детектор) / `manual` (оператор/Стрим) |
|
||
| `detail` | TEXT | NULL | свободный JSON/текст — payload детектора |
|
||
|
||
**Инварианты данных:**
|
||
- Три колонки **атрибуции** (`attribution`/`target_repo`/`target_domain`) присутствуют в исходной
|
||
схеме, **нуллабельны** (требование Славы 10.06, NFR-6, AC-2) — при автозаписи допустимо
|
||
пусто/`unknown`; проставляются позже через `update` (AC-5).
|
||
- **Без `enum`/`CHECK`-констрейнтов** — значения `lesson_type`/`attribution`/`target_domain` суть
|
||
конвенция строковых слагов (forward-compatible: новый тип не требует миграции).
|
||
- Индексы: `idx_lessons_type_status (lesson_type, status)` — выборка/snapshot; `idx_lessons_repo
|
||
(repo)` — репо-разрез; `idx_lessons_wi_type (work_item_id, lesson_type)` — дедуп автозаписи
|
||
(ADR-001 D4).
|
||
|
||
## Совместимость данных / миграции
|
||
|
||
- **Аддитивно / идемпотентно / restart-safe:** только новая таблица + индексы; повторный `init_db()`
|
||
не падает и не дублирует (NFR-4).
|
||
- **Общая прод-БД (self-hosting):** таблица создаётся на том же файле БД, что обслуживает
|
||
orchestrator и enduro-trails. Уроки про любой репо хранятся в одной таблице; **изоляция enduro** —
|
||
таблица аддитивна и не участвует в пайплайне enduro (NFR-3); репо-разрез — поле `repo` + фильтр
|
||
выборки (ADR-001 D2).
|
||
- **Объём строки** — короткие текстовые поля; `detail` — компактный payload. Запись — один `INSERT`,
|
||
чтение — простой параметризованный `SELECT … ORDER BY id DESC LIMIT ?` (NFR-5; общий хост впритык:
|
||
RAM/диск).
|
||
- **Ретенция / архивация** — вне объёма v1; тренд роста и будущая стратегия — `10-tech-risks.md`
|
||
(TR-2).
|
||
- **Миграция исторических уроков из `memory/`** — вне объёма (BRD §2).
|