diff --git a/docs/work-items/ORCH-124/12-review.md b/docs/work-items/ORCH-124/12-review.md new file mode 100644 index 0000000..fd86a0b --- /dev/null +++ b/docs/work-items/ORCH-124/12-review.md @@ -0,0 +1,110 @@ +--- +verdict: APPROVED +work_item: ORCH-124 +stage: review +author_agent: reviewer +status: approved +created_at: 2026-06-16 +model_used: claude-opus-4-8 +type: review +work_item_id: ORCH-124 +version: 1 +--- + +# Review ORCH-124 — serial-gate «пауза без блокировки» (per-task park-сигнал) + +## Summary + +Багфикс (метка `Bug`, эскалирован в full-cycle) инцидента ORCH-116/ORCH-123: serial-gate считал +«активной» любую задачу со стадией вне `{done,cancelled}`, а Plane-статусы Backlog/Blocked/Needs-Input +(слой B) не меняют `tasks.stage` (слой A) ⇒ приостановленный предшественник держал FIFO-гейт закрытым +против срочного успешника. Решение — **новая ортогональная ось планировщика «пауза»**: аддитивная +колонка `tasks.paused_at TEXT` + терм `AND paused_at IS NULL` во всех 3 точках определения «активной +задачи», операторские эндпоинты `POST /serial-gate/pause|resume`, под независимым под-флагом +`serial_gate_pause_enabled`. + +Реализация **точно соответствует** ADR-001 (D1–D9) и закрывает все FR/AC из ТЗ. Проверено по 4 осям — +**замечаний уровня P0/P1 нет**. Все тесты зелёные (15 новых TC + 51 существующий serial-gate + +151 db/queue/claim/task_deps — без регресса). Документация обновлена полностью. **Вердикт: APPROVED.** + +## Проверка по осям + +### 1. Соответствие ТЗ (`02-trz.md` / `03-acceptance-criteria.md`) — ✅ +- FR-1 (пауза исключает из горячего SQL): `build_claim_clause` — терм внутри существующего `EXISTS`, + offline, fail-OPEN сохранён. ✓ +- FR-2 (зеркало + снапшот согласованы): один предикат во всех 3 точках; анти-дрейф проверен **TC-11**. ✓ +- FR-3 (явное durable DB-намерение): колонка `paused_at` + `set/clear/is_task_paused` + эндпоинты; + durable через рестарт — **TC-06**. ✓ +- FR-4 (анти-stale-base при resume): через существующие механизмы (D8), без новой rebase-машинерии. ✓ +- FR-5 (причина ожидания): `_waiting_reason` (`freeze`→`dependency`→`active-task`→`null`) + ключ + `paused`; проверено **TC-10**. ✓ +- FR-6 (явные блоки сохранены): пауза НЕ обходит `repo_freeze`/`task_deps` — **TC-08/TC-09**. ✓ +- FR-7 (условность/нейтральность): под-флаг + scope `serial_gate_repos`; kill-switch off байт-в-байт — + **TC-14** (enduro вне scope не затронут). ✓ +- AC-1…AC-10 — все покрыты TC-01…TC-15 буквально по файлам/тестам. + +### 2. Соответствие ADR (`06-adr/ADR-001`, глобальный `adr-0051`) — ✅ +Реализация = ADR 1:1: D1 (явный per-task флаг), D2 (`tasks.paused_at` через `_ensure_column`, +паттерн `cancelled_at`/`track`), D3 (ортогональная ось — терминал `{done,cancelled}` **байт-в-байт**), +D4 (3 точки согласованно), D5 (наблюдаемость), D6 (`serial_gate_pause_enabled`), D7 (эндпоинты), +D8 (анти-stale-base реюзом), D9 (never-raise/fail-directions). +- **Трассировка (ORCH-078/TRACEABILITY):** правка горячего SQL с маркерами `ORCH-088`/`ORCH-090` — + инвариант FIFO (`t2.id < jobs.task_id`, R-7) и терминал-множество `{done,cancelled}` (adr-0026) + **не сломаны** (подтверждено структурным **TC-15** + сверкой `task_deps`/`stages.py` не читают + `paused_at`). Маркер `ORCH-124` размещён рядом; сводный сквозной `adr-0051` заведён. ✓ +- Нет нарушений глобальных ADR. `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/схемы + существующих таблиц — не тронуты (`src/stages.py`, `src/qg/`, `src/frontmatter.py` вне диффа). ✓ + +### 3. Качество кода — ✅ +- Чисто, читаемо; docstrings на всех новых публичных функциях; маркеры/ссылки на ADR в коде. +- never-raise на всех публичных функциях `serial_gate`/`db`-хелперах; hot-claim fail-OPEN, + freeze fail-CLOSED — направления не инвертированы (**TC-13**). +- **Багфикс-трек (ORCH-019 BR-4):** обязательный регресс-тест-фиксатор **TC-01** воспроизводит + инцидент ORCH-116/ORCH-123 (красный до фикса — опирается на отсутствовавшие `set_task_paused`/ + `paused_at`; зелёный после). ✓ +- Тесты содержательные (не тривиальные): 15 TC покрывают регресс, анти-регресс ORCH-088, durable/ + restart, resume, сохранность freeze/dependency, анти-дрейф 3 точек, offline hot-path, never-raise, + kill-switch-нейтральность, структурный анти-регресс реестров/схем. +- Helper-сигнатуры выверены: `get_task_by_work_item_id` → `dict|None` (совместимо с `.get()`), + `link_for`/`send_telegram` существуют; `claim_next_job` сплайсит `build_claim_clause()` через + **существующую** точку (не модифицирована). + +### 4. Документация (обязательная ось) — ✅ обновлена в том же PR +- `docs/architecture/README.md` — раздел serial-gate + ось «пауза», таблица БД (`paused_at`), + таблица API (`/serial-gate/pause|resume`). ✓ +- `docs/architecture/internals.md` — ось «пауза» ⊥ оси «терминальность». ✓ +- `CHANGELOG.md` — развёрнутая запись (механизм/хранилище/ось/3 точки/эндпоинты/анти-stale-base/ + наблюдаемость/откат/покрытие/доки). ✓ +- `.env.example` — `ORCH_SERIAL_GATE_PAUSE_ENABLED`. ✓ +- ADR: `06-adr/ADR-001` + сквозной `adr/adr-0051` + `08-data-requirements.md`. ✓ +- **Обзорные доки (ORCH-079):** в `README.md` «Известные ограничения» нет открытого пункта, + закрываемого этим PR (п.3 — эпик ORCH-088 batch-autonomy, шире данного багфикса) → обновление не + требуется. **Витрина `docs/overview/` (ORCH-011):** serial-gate не фигурирует в витрине (внутренний + планировщик, не бизнес-способность) → обновление не требуется. ✓ + +## Findings + +### P0 — Blocker +- Нет. + +### P1 — Must fix +- Нет. + +### P2 — Should fix +- Нет. + +### P3 — Nice-to-have (не блокирует) +- [ ] HTTP-уровневых тестов для `POST /serial-gate/pause|resume` нет (терминальный no-op / + под-флаг-off no-op / success+telegram). Не блокирует: это тонкая обёртка над **полностью + покрытыми** `db.set/clear/is_task_paused`, а ветвь гейта (SQL-предикат) протестирована исчерпывающе; + соответствует конвенции репо — соседние операторские эндпоинты (`/serial-gate/unfreeze`, + `/transition-lease/release`) также не покрыты HTTP-тестами. Опционально: добавить TestClient-кейсы. +- [ ] `.task-dev.md` (dev-скретч с метаданными задачи) закоммичен с содержимым ORCH-124 — pre-existing + трекаемый паттерн, вне области ORCH-124; кандидат на `.gitignore` отдельной гигиенической задачей. + +## Документация +**Обновлена полностью в том же PR.** `src/` изменён (config/db/main/serial_gate) — и golden-source доки +(`README.md` архитектуры, `internals.md`, `CHANGELOG.md`, `.env.example`), оба ADR (work-item + сквозной +`adr-0051`) и `08-data-requirements.md` синхронно обновлены. Обзорная витрина (`README.md` ограничения, +`docs/overview/`) обновления не требует (нет затронутого пункта/способности). Структурные доковые тесты +(`test_system_docs.py`, `test_no_host_hardcodes.py`) зелёные. Замечаний по документации нет.