---
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 не требуется и не рекомендуется на прод-БД.
