Files
orchestrator/docs/architecture/adr/adr-0051-serial-gate-pause-without-blocking.md
claude-bot de4f067655
All checks were successful
CI / test (push) Successful in 1m12s
architect(ET): auto-commit from architect run_id=764
2026-06-16 19:17:43 +03:00

8.6 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-124 architecture architect proposed 2026-06-16 claude-opus-4-8

ADR-0051: Ось «пауза» serial-gate — park-сигнал без блокировки FIFO

Сквозной (cross-cutting) ADR. Детальное решение задачи — docs/work-items/ORCH-124/06-adr/ADR-001-serial-gate-pause-without-blocking.md.

Статус: Proposed · Дата: 2026-06-16 · Источник: ORCH-124 (bug → escalate full-cycle)

Контекст

ORCH-088 (serial-gate, adr-0017) определяет «активную задачу репо» исключительно по машинной стадии tasks.stage NOT IN ('done','cancelled') (после ORCH-090/adr-0026 — с учётом терминала cancelled). Plane-статусы Backlog/Blocked/Needs-Input — слой B (индикация), ORCH-066 — не меняют tasks.stage (слой A); у таблицы tasks нет колонки статуса. ⇒ приостановленная оператором задача неотличима от активно исполняемой и держит FIFO-гейт (t2.id < jobs.task_id) закрытым для более поздних analyst-job того же репо.

Инцидент ORCH-116/ORCH-123: ORCH-116 поставили на паузу, чтобы пропустить срочный фикс ORCH-123, но serial-gate держал analyst-job ORCH-123 в queued. Единственные обходы (терминальный cancel, довод до done, глобальное serial_gate_enabled=false) — грубые.

Горячий путь serial_gate.build_claim_clause врезан в claim_next_joboffline SQL — и сетевого чтения Plane-статуса (как делает reconciler ORCH-060) позволить не может. Нужен DB-резолвимый сигнал паузы.

Решение

Инвариант: «пауза» — ОТДЕЛЬНАЯ ОСЬ планировщика, ортогональная «терминальности»

Вводится per-task park-сигнал — аддитивная нуллабельная колонка tasks.paused_at TEXT (NULL = не на паузе) — и новая ось планировщика «пауза», независимая от оси «терминальность».

Ось Предикат Кто использует Меняется ORCH-124?
Терминальность (adr-0026) stage IN ('done','cancelled') serial_gate + task_deps + stages.py НЕТ — байт-в-байт
Пауза (новая, ORCH-124) paused_at IS NOT NULL только FIFO «active» предикат serial_gate да (аддитивно)

serial-gate «активная задача» ⇔ stage NOT IN ('done','cancelled') AND paused_at IS NULL. Это осознанная, задокументированная дивергенция serial-gate от чисто-терминального предиката (требование гармонизации adr-0026): пауза выводит предшественника из FIFO-учёта serial-gate, не делая его терминальным.

Что НЕ меняется (анти-регресс adr-0026)

  • task_deps (adr-0015) и stages.py::STAGE_TRANSITIONS колонку paused_at не читают — остаются чисто терминальными. Явно объявленная зависимость (job_deps) на приостановленную задачу по-прежнему блокирует зависимый job. Пауза («пропустите меня в FIFO») и dependency («B нужен результат A») — разные оси; пауза НЕ обходит dependency и НЕ обходит per-repo repo_freeze.
  • STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict / схемы существующих таблиц — без изменений. Пауза — не стадия и не Quality Gate, а признак планировщика очереди.

Точки, признающие ось «пауза» (исчерпывающе)

  1. src/serial_gate.py::build_claim_clause — терм AND t2.paused_at IS NULL внутри active_clause (под под-флагом). (маркер ORCH-124, рядом с ORCH-088/ORCH-090)
  2. src/serial_gate.py::repo_has_active_task / _per_repo_snapshot — тот же предикат + наблюдаемость (ключ paused, reason ожидания).
  3. src/db.py — колонка tasks.paused_at (_ensure_column) + хелперы set_task_paused/ clear_task_paused/is_task_paused.
  4. src/main.py — операторские эндпоинты POST /serial-gate/pause|resume (по образцу POST /serial-gate/unfreeze).

Анти-stale-base при возобновлении (ORCH-088 не регрессирует)

Пауза «демотирует» задачу в FIFO; свежесть базы при resume обеспечивают существующие механизмы — новой rebase-машинерии нет: отложенный срез ветки (ORCH-088, для паузнутой-в-analysis) + безусловный pre-merge auto_rebase_onto_main под merge-lease (ORCH-026/093) + merge-gate re-test (ORCH-110) для уже материализованной ветки. Нормальная задача (paused_at IS NULL) по-прежнему держит гейт.

Флаги / совместимость

  • Независимый под-флаг serial_gate_pause_enabled (env ORCH_SERIAL_GATE_PAUSE_ENABLED, дефолт True) — зеркало serial_gate_freeze_enabled. False ⇒ pause-терм опущен из SQL, эндпоинты no-op ⇒ serial-gate байт-в-байт как ORCH-088/090. Область — переиспользует serial_gate_repos (новый *_repos не вводится).
  • Дефолт True безопасен: пока ни одна задача не на паузе, paused_at везде NULL ⇒ истинный no-op (enduro не затронут).
  • never-raise: pause-терм в build_claim_clause сохраняет fail-OPEN; freeze — fail-CLOSED.
  • Миграция — только аддитивная/идемпотентная (_ensure_column); общая прод-БД безопасна (NFR-3).

Последствия

  • + Чистая операторская «пауза без блокировки», отличная от cancel (терминал) и от kill-switch; durable, offline, webhook-независимая; закрывает инцидент ORCH-116/ORCH-123.
  • + Единый, явно описанный двухосевой предикат планировщика (терминальность ⊥ пауза) — устранён риск будущего рассинхрона.
  • Появилась вторая ось «активности» serial-gate — будущие подсистемы планировщика обязаны помнить: serial-gate «активна» = не терминальна И не на паузе, но терминал (task_deps/stages.py) ось «пауза» НЕ включает. Митигейшн: этот ADR + маркер ORCH-124 в изменённых местах + тесты.
  • Откат: ORCH_SERIAL_GATE_PAUSE_ENABLED=false (serial-gate 1:1 как ORCH-088/090; колонка paused_at инертна).

Эволюция маркеров

Горячий SQL serial-gate несёт теперь 3 маркера (ORCH-088 FIFO-гейт, ORCH-090 терминал cancelled, ORCH-124 ось паузы) — правка любого из них сверяется с этим сводным ADR (анти-археология: 3+ маркеров → одна ссылка сюда, docs/_standards/TRACEABILITY.md).

Ссылки

  • Детальный ADR: docs/work-items/ORCH-124/06-adr/ADR-001-serial-gate-pause-without-blocking.md
  • Данные: docs/work-items/ORCH-124/08-data-requirements.md
  • Связанные: adr-0017 (serial-gate ORCH-088), adr-0026 (терминал {done,cancelled} ORCH-090), adr-0015 (task-deps), adr-0027 (merge-актор rebase/retry ORCH-093), adr-0042 (merge-gate re-test ORCH-110)