Files
orchestrator/docs/work-items/ORCH-087/08-data-requirements.md

87 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Требования к схеме БД — ORCH-087
Все изменения — **строго аддитивные и идемпотентные** (`CREATE TABLE IF NOT EXISTS`
/ `_ensure_column`), restart-safe на живой ОБЩЕЙ прод-БД (SQLite). Данные
enduro-trails не трогаются. Существующие колонки/таблицы не ломаются. Точка врезки —
`src/db.py::init_db` (рядом с прочими `_ensure_column`/`executescript`).
---
## 1. Колонка `agent_runs.effort` (BR-EFF, обязательно)
```python
_ensure_column(conn, "agent_runs", "effort", "TEXT")
```
- Тип `TEXT`, nullable. Хранит РЕАЛЬНО ушедшее в `--effort` значение
(`low|medium|high|xhigh|max`) или `NULL`, если флаг не подавался (резолв вернул "").
- Заполняется в `launcher._spawn` сразу после `resolve_agent_effort(agent,
project_id)` через `UPDATE agent_runs SET effort=? WHERE id=run_id`
(`effort or None`).
- Читается в `render_task_tracker` (добавить `effort` в SELECT `agent_runs`).
- Исторические строки (до миграции) → `effort IS NULL` → суффикс эффорта в карточке
опускается; допустим fallback на `resolve_agent_effort(run["agent"])`.
- Идемпотентность: `_ensure_column` — no-op при уже существующей колонке (AC-E.1,
TC-09).
## 2. Таблица-леджер `tracker_messages` (BR-G1, вариант A1 ADR-001)
```sql
CREATE TABLE IF NOT EXISTS tracker_messages (
task_id INTEGER NOT NULL,
message_id INTEGER NOT NULL,
created_at TEXT DEFAULT (datetime('now')),
deleted_at TEXT, -- NULL = карточка ещё жива (незакрыта)
PRIMARY KEY (task_id, message_id)
);
CREATE INDEX IF NOT EXISTS idx_tracker_messages_open
ON tracker_messages(task_id) WHERE deleted_at IS NULL;
```
- Авторитетный учёт ВСЕХ созданных карточек задачи; `deleted_at IS NULL` ⇔ карточка
считается живой и подлежит зачистке на следующем bump.
- Логический FK на `tasks.id` без `REFERENCES` (зеркалит `jobs.task_id`/`job_deps`) —
миграция не падает на pre-existing БД.
- Частичный индекс `WHERE deleted_at IS NULL` — дешёвая выборка незакрытых mid в
горячем пути рендера/зачистки.
- `PRIMARY KEY (task_id, message_id)` — идемпотентность INSERT (повторный mid не
дублируется); защита от двойного учёта при гонке.
**Новые геттеры/сеттеры в `src/db.py` (предложение, точная сигнатура — за разработчиком):**
| Функция | Назначение |
|---------|-----------|
| `add_tracker_message(task_id, message_id)` | INSERT нового mid (после успешного `send`). `INSERT OR IGNORE` для идемпотентности. |
| `get_open_tracker_messages(task_id) -> list[int]` | Все `message_id` с `deleted_at IS NULL`. |
| `mark_tracker_message_deleted(task_id, message_id)` | `UPDATE … SET deleted_at=datetime('now')` для успешно удалённых / «already gone». |
Контракт — как у существующих хелперов БД (never-raise по месту вызова в
notifications: ошибка БД не валит конвейер).
### Сосуществование со скаляром `tasks.tracker_message_id`
- `tasks.tracker_message_id` **СОХРАНЯЕТСЯ** без изменения семантики — указатель на
ТЕКУЩУЮ карточку (читатели `get_tracker_message_id`/`set_tracker_message_id` не
трогаются). Обратная совместимость полная.
- Леджер `tracker_messages` — НАДмножество: источник истины для зачистки сирот.
- Одноразовый бэкфилл скаляра в леджер **не требуется** (старые сироты всё равно за
48ч-окном Telegram). Новый поток ведёт леджер с нуля.
## 3. Что НЕ меняется
- `tasks` (кроме отсутствия изменений — скаляр сохранён), `jobs`, `events`,
`job_deps`, прочие колонки `agent_runs` (`model`, токены, cost, exit_code) — без
изменений.
- Никаких `DROP`/`ALTER … DROP`/переименований/перетипизаций (SQLite-небезопасно на
живой БД).
- `STAGE_TRANSITIONS` / `QG_CHECKS` — вне зоны БД, не затрагиваются.
## 4. Идемпотентность и restart-safety (проверка)
- Двойной вызов `init_db` → без ошибок (`IF NOT EXISTS` / `_ensure_column` no-op) —
TC-09.
- Леджер переживает рестарт орка: незакрытые mid читаются из БД → следующий bump
подчищает старые карточки (TC-05, AC-1.3).
- Миграция на БД с существующими данными enduro: только добавляет колонку/таблицу,
данные нетронуты (AC-X.5).