11 KiB
verdict, work_item, stage, author_agent, status, created_at, model_used, type, work_item_id, version
| verdict | work_item | stage | author_agent | status | created_at | model_used | type | work_item_id | version |
|---|---|---|---|---|---|---|---|---|---|
| REQUEST_CHANGES | ORCH-114 | review | reviewer | changes-requested | 2026-06-15 | claude-opus-4-8 | review | ORCH-114 | 1 |
Review ORCH-114 — Durable transition-ownership lease + expected-stage CAS
Summary
Сильная, аккуратная реализация корневого класса инцидент-цепочки ORCH-110/111/112/113.
Архитектура (durable-lease на входе + expected-stage CAS на записи, liveness по pid+boot_id
без heartbeat, self-hosting-скоуп, kill-switch, never-raise) реализована в точном соответствии
с ADR-001 D1–D10. Код-инварианты конвейера соблюдены: src/stages.py и src/qg/checks.py
не тронуты (AC-11), схема БД аддитивна (одна таблица transition_lease, без epoch-колонки),
hot-path claim_next_job не консультирует lease (AC-10/fail-open). Прогон полного pytest tests/ — 2048 passed в детерминированном порядке (плагина random-ordering нет), т.е. AC-9
(байт-в-байт при kill-switch off) и CI-green выполняются операционно. Тесты содержательные:
TC-01a/b воспроизводят обязательный регресс класса ORCH-111 (kill-switch off = «красный»,
on = «зелёный»), TC-02…TC-14 покрывают AC-2…AC-13.
Однако вердикт — REQUEST_CHANGES: документация (golden source наравне с кодом) обновлена
частично. Архитектурные доки (docs/architecture/README.md, internals.md, CHANGELOG.md,
ADR-001 + сквозной adr-0045) — образцовы, но .env.example и CLAUDE.md не обновлены (P1),
а витрина docs/overview/ (ORCH-011) не отражает новый механизм (P2). Плюс две незначительные
оси-уточнения (P2).
Findings
P0 — Blocker
- (нет)
P1 — Must fix
-
.env.exampleне содержит новых ключей конфигурацииORCH_TRANSITION_LEASE_ENABLEDиORCH_TRANSITION_LEASE_REPOS(добавлены вsrc/config.py:transition_lease_enabled/transition_lease_repos). ORCH-101 нормативно объявил.env.example«каноном 100% ключей старта», и все сопоставимые kill-switch'и там присутствуют (ORCH_SERIAL_GATE_ENABLED:220,ORCH_CHECKOUT_HYGIENE_ENABLED:349,ORCH_COVERAGE_GATE_ENABLED:511). Изменение конфигурации без отражения в каноническом env-файле — нарушение оси «документация = golden source» (доступ оператора к kill-switch'у). Fix: добавить обе строки в.env.example(с дефолтамиtrue/пусто) рядом с блоком прочих gate-флагов. Ссылка: правило документирования CLAUDE.md §2 («конфигурация → env-канон»), ORCH-101 (adr-0036). -
CLAUDE.mdне дополнен паспорт-секцией ORCH-114. ORCH-114 — крупный кросс-каттинговый механизм (новая durable-таблица, новый leafsrc/transition_lease.py, врезки вadvance_stage/job_reaper/reconciler/обоих webhook'ах/main.lifespan, новый эндпоинт, новый инвариант владения переходом). Конвенция паспорта универсальна: каждая сопоставимая фича несёт секцию вCLAUDE.md(ORCH-112/110/098/094/093/090/089/088/027/019…), а футер прямо гласит «Поддерживается агентами при каждой доработке». Для self-hosting это критично: будущий агент, правящийadvance_stage/reaper/webhooks, обязан найти инвариант ORCH-114 в первом обязательном к чтению доке (ORCH-078 трассировка опирается на паспорт как индекс). Fix: добавить секцию ORCH-114 вCLAUDE.mdпо образцу ORCH-112/113 (механизм, инвариант, флаги, ADR-ссылки). Ссылка: CLAUDE.md правила §1, §2 + футер; ORCH-078 (TRACEABILITY).
P2 — Should fix
-
Витрина системы
docs/overview/не обновлена (ORCH-011). Добавлена durable-таблицаtransition_leaseи read-only блокtransition_leaseвGET /queue, но:tech-data-model.md(раздел «Вспомогательные таблицы», строки 46–49) перечисляетrepo_freeze/coverage_baseline/tracker_messages/lessons— безtransition_lease;tech-observability.md(перечень блоков/queue, стр. 22–23) иtech-architecture.md(список компонентов с job-reaper, стр. 46) тоже не упоминают механизм. Индекс витрины прямо требует «изменил функциональность платформы → обнови витринуdocs/overview/в том же PR» (docs/overview/README.md:66). Понижено до P2 (не стадия/гейт/агент/интеграция → машинные проверкиtests/test_system_docs.pyэто не ловят), но completeness-норму витрины нарушает. Fix: добавить строкуtransition_leaseв таблицуtech-data-model.md, упоминание блока вtech-observability.md, компонент вtech-architecture.md. -
Расхождение код ↔ ADR D4 по CAS на rollback-записях. ADR-001 D4 (таблица) предписывает rollback-записям
_handle_*_rollbackCAS (столбец «да») как защиту rollback↔done (BR-6). В коде rollback-записи на side-effectful рёбрах остались голымupdate_task_stage(task_id, "development")—_handle_merge_gate_rollback:1246,_handle_security_gate:1323,_handle_coverage_gate:1411,_handle_image_freshness:1491. Корректность не нарушена: эти хендлеры вызываются строго внутриadvance_stage(стр. 378–407) под удерживаемым lease → единственный владелец → конкурентного противоречия нет. Но налицо буквальное расхождение реализации с собственным ADR. Fix (на выбор): либо провести эти записи черезtransition_lease.commit_stage_cas(...)(как в forward/bypass-путях), либо уточнить ADR D4, что под lease CAS на in-region rollback избыточен (чтобы доки соответствовали коду). Ссылка: ADR-001 D4/D5, BR-6, AC-6. -
Изоляция тестов: модуль
tests/test_orch114_transition_ownership.pyпротекает в процесс-widesettings.db_path. Module-levelos.environ.setdefault("ORCH_DB_PATH", …)(стр. 22) при первом импорте инстанцируетSettingsсdb_path=test_orch114.db, а позднейшийos.environ["ORCH_DB_PATH"]=…вtests/test_webhooks.py:9уже не влияет (settings создан) → при прогоне двух модулей вместе (pytest tests/test_orch114_transition_ownership.py tests/test_webhooks.py) 4 существующих webhook-теста падают (assert 'architecture' == 'analysis'и др.). Полныйpytest tests/зелёный (промежуточные модули перетирают состояние; плагина random-ordering нет) → CI/coverage-gate не ломаются, поэтому P2, не блокер. Но developer/reviewer, гоняющие подмножество, получат ложные падения. Fix: изолировать db_path модуля через conftest-fixture/собственный tmp без правки процесс-wide env (паттернfresh_dbуже есть — достаточно убрать module-levelsetdefault).
P3 — Nice to have
reconciler/plane._try_advance_stageзовутis_held_by_live_owner(task_id)без предварительногоapplies(repo)(в отличие от reaper). Для out-of-scope, но включённого репо (enduro при дефолте) это лишний безвредныйSELECT(строк нет →False, defer не возникает). Функционально корректно; при желании — добавить дешёвыйapplies-гард ради нулевого оверхеда.
Документация
Обновлено (образцово):
docs/architecture/README.md— новый компонент в списке, отдельная секция «Единое владение side-effectful переходами», строка таблицы БДtransition_lease, API-таблица (POST /transition-lease/release), описание блока/queue.docs/architecture/internals.md— DDLtransition_lease, lifespan-recovery, секция reaper.CHANGELOG.md— подробная запись ORCH-114 в[Unreleased].- ADR:
docs/work-items/ORCH-114/06-adr/ADR-001-…+ сквознойdocs/architecture/adr/adr-0045-…— полные, со сверкой по коду. - Work-item доки
02-trz/03-acceptance-criteria/08-data-requirements/10-tech-risks— на месте.
Нужно обновить (см. findings):
.env.example— добавитьORCH_TRANSITION_LEASE_ENABLED/ORCH_TRANSITION_LEASE_REPOS(P1).CLAUDE.md— добавить паспорт-секцию ORCH-114 (P1).docs/overview/(tech-data-model.md/tech-observability.md/tech-architecture.md) — отразить таблицу/блок/компонентtransition_lease(P2).
Verdict rationale
Любой P1 → REQUEST_CHANGES. Кода-корректность и инварианты конвейера — без P0/P1; блокирует
частичная незавершённость документации golden-source (.env.example, CLAUDE.md). После
закрытия двух P1 (и желательно P2) задача готова к повторному ревью — реализация по существу
зрелая.