13 KiB
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).