Files
orchestrator/docs/work-items/ORCH-124/02-trz.md
claude-bot fef5ba15d5
All checks were successful
CI / test (push) Successful in 1m9s
analyst(ET): auto-commit from analyst run_id=763
2026-06-16 17:56:23 +03:00

13 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used, escalate
work_item stage author_agent status created_at model_used escalate
ORCH-124 analysis analyst ready-for-review 2026-06-16 claude-opus-4-8 full-cycle

02 — ТЗ (TRZ): ORCH-124 — wait/terminal-семантика serial-gate (пауза без блокировки)

Work Item: ORCH-124 · Repo: orchestrator · Стадия: analysis

ТЗ описывает требования к изменениям, выведенные из BRD и фактического кода. Выбор механизма «паузы без блокировки» (release-on-status / per-task hold-флаг / task_deps) и его архитектурное обоснование — задача архитектора (06-adr, эскалация в full-cycle). Ниже — что должно стать истинным и какие модули это затронет, без предписания «как именно».

1. Сводка изменения

Сейчас serial-gate (src/serial_gate.py) считает «активной» любую задачу репо со стадией вне {done,cancelled} — в трёх точках (build_claim_clause / repo_has_active_task / _per_repo_snapshot). Поскольку Plane-статусы Backlog/Blocked/Needs-Input (слой B индикации) не меняют tasks.stage (слой A), приостановленная задача неотличима от активной и держит FIFO-гейт закрытым для более поздних analyst-job. Требуется ввести явный, durable, DB-резолвимый признак «пауза/park» и научить определение «активной задачи» его учитывать, сохранив анти-stale-base ORCH-088 при возобновлении (R-1). Машинные гейты не трогаются — это правка планировщика очереди.

2. Задействованные модули / пути

Путь Действие
src/serial_gate.py изменить — определение «активной задачи» во всех 3 точках (build_claim_clause, repo_has_active_task, _per_repo_snapshot); причина ожидания в снапшоте
src/db.py изменить (вероятно) — claim_next_job (учёт нового предиката в горячем SQL) + (если выбран DB-сигнал) аддитивная колонка/таблица _ensure_column/CREATE TABLE IF NOT EXISTS + read-only/мутатор-хелперы
src/config.py изменить — под-флаг(и) семантики паузы (kill-switch), область репо (по образцу serial_gate_*)
src/main.py изменить (вероятно) — операторский эндпоинт pause/resume или расширение блока serial_gate в GET /queue причиной ожидания
src/webhooks/plane.py и/или src/plane_sync.py изменить (если механизм = release-on-status) — захват намерения паузы из смены Plane-статуса в durable DB-сигнал (не на hot-path)
tests/test_serial_gate*.py (новый tests/test_orch124_serial_gate_pause.py) создать/дополнить — кейсы паузы + регресс инцидента
docs/architecture/README.md, CHANGELOG.md, docs/work-items/ORCH-124/06-adr/ обновить — раздел serial-gate + ADR (архитектор)

Точный набор модулей зависит от выбранного механизма (ADR). Минимально-необходимый набор — serial_gate.py (3 точки) + db.py (hot-path) + config.py (флаг) + тесты; остальное — по решению архитектора.

3. Функциональные требования

FR-1 — Признак паузы исключает задачу из «активных» в горячем SQL (BR-1, NFR-2)

build_claim_clause(): подзапрос EXISTS (... t2.stage NOT IN ('done','cancelled')) должен дополнительно исключать приостановленные задачи-предшественники. Предикат — чисто SQL по локальной БД (никакой сети). Форма исключения — функция выбранного DB-сигнала (доп. колонка tasks.<paused> / отдельная таблица hold / task_deps): архитектор фиксирует точную SQL-форму в ADR. Инвариант: job'ы уже активной задачи (agent != 'analyst') проходят как раньше; самоблокировки собственной строки (R-7 ORCH-088) нет.

FR-2 — Зеркало и снапшот согласованы с FR-1 (BR-1/BR-4)

repo_has_active_task() и _per_repo_snapshot() используют тот же предикат «активна», что и build_claim_clause — приостановленный предшественник не попадает в active_task. Все три точки правятся согласованно (анти-дрейф: они должны давать один ответ на один вход).

FR-3 — Явное durable намерение паузы (BR-2, BR-5, NFR-2)

Должен существовать явный оператор-инициируемый сигнал «park/pause» задачи, durable (переживает рестарт) и DB-резолвимый. Распауза (resume) — обратная операция, восстанавливающая участие задачи в serial-gate (BR-5). Сигнал отличен от cancel/done (не терминальный) и от глобального kill-switch. Конкретная форма (новый эндпоинт POST /serial-gate/pause|resume, или маппинг Plane-статуса в DB-сигнал через webhook, или декларация task_deps) — решение архитектора.

FR-4 — Анти-stale-base при возобновлении (BR-3, R-1 — критично)

Решение обязано не регрессировать ORCH-088: нормально исполняемая задача держит гейт; а возобновлённая ранее приостановленная задача не должна приводить к stale-базе у успешника, который прошёл вперёд. Механизм разрешения (демотирование в FIFO + обязательный rebase при resume / явный yield с принятием rebase / иное) фиксируется архитектором в ADR. ТЗ требует лишь: после распаузы ни одна из задач не остаётся на устаревшей базе незаметно.

FR-5 — Корректная причина ожидания (BR-4)

Блок serial_gate в GET /queue для ожидающего успешника различает причины: active-task (идёт работа) / paused-predecessor (предшественник на паузе — не должно случаться после фикса, но наблюдаемо) / freeze / dependency. Аддитивно к существующим ключам снапшота (active_task / waiting / frozen / frozen_reason / frozen_at).

FR-6 — Явные блоки сохранены (BR-6)

repo_freeze (durable per-repo freeze) и task_deps (job_deps) продолжают блокировать claim ровно как сейчас. «Пауза» НЕ должна обходить freeze/dependency — это разные оси (freeze = весь репо; dependency = конкретная пара; пауза = «пропустите меня»).

FR-7 — Условность и нейтральность (NFR-3)

Поведение под выключателем (существующий serial_gate_enabled либо новый под-флаг паузы) → байт-в-байт до ORCH-124. Область репо — по образцу serial_gate_repos (CSV; пусто → текущая область serial-gate, т.е. все репо). enduro не затронут при нейтральном поведении.

4. Изменения API

Вероятно (на усмотрение архитектора, ADR):

  • Новые операторские эндпоинты POST /serial-gate/pause?work_item=<id> и POST /serial-gate/resume?work_item=<id> (по образцу существующего POST /serial-gate/unfreeze), если механизм = явный per-task hold. Возвращают новое состояние (paused/active) задачи.
  • Расширение GET /queue → блок serial_gate дополняется причиной ожидания (FR-5) и (если есть) списком приостановленных задач репо. Существующие ключи не меняются (BC).

Если механизм = release-on-status, новых ручных эндпоинтов может не быть (намерение — смена Plane-статуса, захватываемая webhook'ом в durable DB-сигнал); тогда раздел сводится к расширению GET /queue.

5. Изменения схемы БД

Вероятно аддитивно (на усмотрение архитектора):

  • Колонка tasks.paused_at TEXT (NULL = не на паузе), идемпотентно через _ensure_column — паттерн существующих tasks.cancelled_at / tasks.cancel_requested_at / tasks.track; или
  • Отдельная таблица hold (по образцу repo_freeze: work_item_id/task_id, paused_at, cleared_at IS NULL = активна), CREATE TABLE IF NOT EXISTS. Схемы существующих таблиц (tasks/jobs/job_deps/repo_freeze) — без деструктивных изменений. Если механизм = task_deps, новой схемы может не понадобиться вовсе. Финальное решение — ADR + 08-data-requirements.md (архитектор).

6. Требования к новым/изменённым QG checks

Нет. STAGE_TRANSITIONS / состав QG_CHECKS / семантика и имена check_* / machine-verdict ключи (verdict:/result:/deploy_status:/staging_status:/security_status:) — байт-в-байт не трогаются. ORCH-124 — правка планировщика очереди (claim) и наблюдаемости, не Quality Gate и не новая стадия конвейера.

7. Совместимость / регресс

  • Обратная совместимость: аддитивно; выключатель → поведение до ORCH-124 байт-в-байт (NFR-3, FR-7). Существующие тесты serial-gate (tests/test_serial_gate*.py) остаются зелёными.
  • Kill-switch / область: переиспользовать serial_gate_enabled (kill-switch) + при необходимости ввести под-флаг семантики паузы (независимый тумблер, по образцу serial_gate_freeze_enabled) и область *_repos (CSV).
  • Обратимость: выставить под-флаг паузы в False → serial-gate работает как ORCH-088/090 (приостановленные снова считаются активными — т.е. возврат к текущему багу, но это осознанный rollback-режим, не дефолт).
  • never-raise / fail-direction (NFR-1): сохранить fail-OPEN на hot-claim build и fail-CLOSED на freeze; новая ветка паузы не инвертирует эти направления.
  • Гармонизация предиката (NFR-4): не сломать task_deps/stages.py терминальное множество {done,cancelled} (ORCH-090/adr-0026); расхождение serial-gate (паузой) — только осознанно и задокументированно в ADR.
  • Артефакты pipeline: обновляются docs/architecture/README.md (раздел serial-gate ORCH-088 + семантика паузы), CHANGELOG.md, новый docs/work-items/ORCH-124/06-adr/ADR-001-*.md (архитектор), при необходимости 08-data-requirements.md (архитектор). Reviewer проверяет обновление доки (правило агентов §6).