55 lines
4.0 KiB
Markdown
55 lines
4.0 KiB
Markdown
---
|
||
work_item: ORCH-124
|
||
stage: architecture
|
||
author_agent: architect
|
||
status: proposed
|
||
created_at: 2026-06-16
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 08 — Требования к данным: ORCH-124 — per-task park-сигнал serial-gate
|
||
|
||
Work Item: **ORCH-124** · Repo: **orchestrator** · Стадия: architecture
|
||
|
||
> When-applicable / информационный (гейтом не парсится).
|
||
|
||
## Изменения схемы БД
|
||
|
||
**Одна аддитивная нуллабельная колонка** на существующей таблице `tasks` (никаких новых таблиц):
|
||
|
||
| Таблица | Колонка | Тип / дефолт | Семантика |
|
||
|---------|---------|--------------|-----------|
|
||
| `tasks` | `paused_at` | `TEXT` (по умолчанию отсутствует → `NULL`) | `NULL` = не на паузе; ISO-таймстамп (`datetime('now')`) = задача поставлена оператором на паузу (park) |
|
||
|
||
Миграция — идемпотентный `_ensure_column(conn, "tasks", "paused_at", "TEXT")` в `init_db()`, ровно по
|
||
образцу `tasks.cancelled_at` / `tasks.cancel_requested_at` / `tasks.track` (`src/db.py:141-149`). На уже
|
||
мигрированной БД — no-op.
|
||
|
||
**Индекс не требуется.** Горячий SQL `build_claim_clause` сканирует `tasks t2` уже сегодня (по `repo`/`id`);
|
||
терм `AND t2.paused_at IS NULL` — дополнительный фильтр в существующем `EXISTS`-подзапросе, не новый план
|
||
доступа. Кардинальность `tasks` per-repo мала; добавление индекса — преждевременная оптимизация (принцип
|
||
минимума).
|
||
|
||
## Новые/изменённые сущности
|
||
|
||
- **`tasks.paused_at`** — единственное durable хранилище намерения паузы. Запись — `db.set_task_paused`
|
||
(`paused_at=datetime('now')`); сброс — `db.clear_task_paused` (`paused_at=NULL`); чтение —
|
||
`db.is_task_paused` и SQL-предикат serial-gate. Все хелперы never-raise.
|
||
- **Инвариант оси:** `paused_at` — **ортогональная** ось «пауза», независимая от оси «терминальность»
|
||
(`stage IN ('done','cancelled')`). serial-gate «активна» = `stage NOT IN ('done','cancelled') AND
|
||
paused_at IS NULL`. `task_deps`/`stages.py` колонку `paused_at` **не читают** (терминал не трогается,
|
||
NFR-4).
|
||
- **Существующие таблицы** (`jobs` / `job_deps` / `repo_freeze` / `agent_runs`) — без изменений.
|
||
|
||
## Совместимость данных / миграции
|
||
|
||
- **Аддитивно и идемпотентно:** `_ensure_column` — no-op на уже-мигрированной БД; новая колонка
|
||
дефолтит в `NULL` для всех существующих строк ⇒ все текущие задачи считаются «не на паузе» ⇒ поведение
|
||
до ORCH-124 сохраняется до первой явной операторской паузы.
|
||
- **Restart-safe / durable:** значение в БД переживает рестарт процесса/контейнера (BR-2, R-3).
|
||
- **Общая прод-БД (self-hosting):** колонка добавляется на общей БД; при дефолтном `serial_gate_pause_enabled`
|
||
и отсутствии паузнутых задач — нулевая регрессия для enduro (`paused_at` везде `NULL`).
|
||
- **Откат:** колонка инертна при `ORCH_SERIAL_GATE_PAUSE_ENABLED=false` (pause-терм опускается из SQL).
|
||
Колонку можно оставить (безвредна); деструктивный drop не требуется и не рекомендуется на прод-БД.
|
||
</content>
|