Files
orchestrator/docs/work-items/ORCH-114/12-review.md

8.8 KiB
Raw Blame History

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
APPROVED ORCH-114 review reviewer approved 2026-06-15 claude-opus-4-8 review ORCH-114 2

Review ORCH-114 — Durable transition-ownership lease + expected-stage CAS

Summary

Повторное ревью (цикл 2). Прошлый вердикт был REQUEST_CHANGES из-за частичной незавершённости документации golden-source (два P1 + три P2/P3). Кода-корректность и инварианты конвейера уже тогда были без P0/P1. В этом цикле developer закрыл все ранее поднятые findings:

  • P1 .env.example → закрыт: добавлены ORCH_TRANSITION_LEASE_ENABLED=true / ORCH_TRANSITION_LEASE_REPOS= с подробной нормативной шапкой (рядом с блоком reaper-флагов).
  • P1 CLAUDE.md → закрыт: добавлена полноценная паспорт-секция «Единое владение side-effectful переходами: durable-lease + expected-stage CAS (ORCH-114)» (механизм, два слоя, инвариант, флаги, ADR-ссылки) — по образцу ORCH-112/113.
  • P2 витрина docs/overview/ → закрыта: tech-data-model.md (строка таблицы transition_lease), tech-observability.md (упоминание блока /queue), tech-architecture.md (компонент Transition-lease).
  • P2 расхождение код↔ADR D4 (CAS на rollback-записях) → закрыто: введён общий хелпер _rollback_stage_cas, и все четыре in-region rollback-записи (_handle_merge_gate_rollback/ _handle_security_gate/_handle_coverage_gate/_handle_image_freshness) теперь пишут development через тот же expected-stage CAS. Реализация совпала с собственным ADR D4; добавлены целевые тесты (TC-11 test_tc11_inregion_rollback_writes_use_cas, test_tc11_rollback_cas_lost_aborts_without_overwriting_done).
  • P2 изоляция тестов → закрыта: убран module-level os.environ.setdefault("ORCH_DB_PATH"), test_webhooks.py пинит собственный реестр per-test, добавлен autouse-fixture _disable_transition_lease (kill-switch off для всего suite по образцу _disable_merge_verify).

Архитектура реализована в точном соответствии с ADR-001 D1D10: durable-lease на входе (acquire/release в try/finally) + expected-stage CAS на записи (включая 6 путей в обход advance_stage), liveness по pid+boot_id без heartbeat, реклейм при рестарте (recover_on_startup в main.lifespan), reaper/reconciler/webhook defer при живом владельце, Tier-3 backstop добивает зависшего. src/transition_lease.py — чистый never-raise leaf (импортирует только db+config, лениво merge_gate.pid_alive/qg.checks/notifications).

Инварианты конвейера (AC-11): src/stages.py и src/qg/checks.py не тронуты (нет в диффе), STAGE_TRANSITIONS/QG_CHECKS встречаются в src-диффе только в комментарии; machine-verdict ключи не тронуты; БД аддитивна (одна таблица transition_lease, CREATE TABLE IF NOT EXISTS, без epoch-колонки). hot-path claim_next_job lease не консультирует (AC-10/fail-open).

Багфикс-трек (ORCH-019/BR-4): задача bug→escalate full-cycle. Регресс-тест-фиксатор присутствует: test_tc01_concurrent_entry_no_double_effect (зелёный с lease) + test_tc01_red_before_fix_demonstration (красный при kill-switch off — второй актор переисполняет все под-гейты, воспроизводя класс ORCH-111). Требование выполнено.

Прогоны (verified):

  • pytest tests/test_orch114_transition_ownership.py tests/test_webhooks.py50 passed (именно та комбинация двух модулей, что в прошлом цикле давала 4 падения — изоляция подтверждённо починена).
  • pytest tests/ (полный) — 2052 passed в детерминированном порядке → AC-9 (байт-в-байт при kill-switch off) и CI-green выполняются операционно; ORCH-113-тесты в наборе зелёные (контракт предшественника не сломан, ORCH-078).

Findings

P0 — Blocker

  • (нет)

P1 — Must fix

  • (нет)

P2 — Should fix

  • (нет)

P3 — Nice to have

  • Merge-lease не освобождается на (практически недостижимой) ветке CAS-lost в rollback'е coverage/image-freshness. В _handle_coverage_gate/_handle_image_freshness release_merge_lease стоит после _rollback_stage_cas, поэтому при проигранном CAS (return True) штатное освобождение merge-lease пропускается. Под держимым transition-lease эта ветка практически недостижима (единственный владелец → CAS почти всегда выигрывает; чтобы проиграть, нужен аномальный bypass-писатель, сдвинувший стадию с deploy-staging). Даже в этом крайнем случае утечка ограничена собственным TTL+reclaim merge-lease (ORCH-043/065). Корректность недвоения не нарушена. При желании — продублировать holder-aware release_merge_lease до CAS-проверки (или задокументировать намеренный аборт). Не блокер. Ссылка: ADR-001 D1/D4, ORCH-027/058 rollback.
  • reconciler/plane._try_advance_stage зовут is_held_by_live_owner(task_id) без предварительного applies(repo) (в отличие от reaper). Для out-of-scope, но включённого репо (enduro при дефолте) это безвредный лишний SELECT (строк нет → False). Функционально корректно; ради нулевого оверхеда можно добавить дешёвый applies-гард. (Перенос P3 из цикла 1 — остаётся косметикой.)

Документация

Обновлено и проверено (полно):

  • .env.exampleORCH_TRANSITION_LEASE_ENABLED / ORCH_TRANSITION_LEASE_REPOS (канон ключей старта, ORCH-101).
  • CLAUDE.md — паспорт-секция ORCH-114.
  • docs/overview/tech-data-model.md / tech-observability.md / tech-architecture.md (витрина системы, ORCH-011).
  • CHANGELOG.md — подробная запись ORCH-114 в [Unreleased].
  • docs/architecture/README.md + internals.md — компонент, секция, таблица БД, API-эндпоинт POST /transition-lease/release, блок /queue.
  • ADR: docs/work-items/ORCH-114/06-adr/ADR-001-… + сквозной docs/architecture/adr/adr-0045-… — полные, со сверкой по коду.
  • Work-item доки 02-trz/03-acceptance-criteria/04-test-plan/08-data-requirements/ 10-tech-risks — на месте.

Необновлённой документации при изменении src/ не выявлено. Пунктов README «Известные ограничения», закрываемых этим PR, нет.

Verdict rationale

Все P0/P1/P2 прошлого цикла закрыты; новых P0/P1 не выявлено по всем четырём осям (ТЗ/AC, ADR, качество кода + обязательный регресс-тест багфикс-трека, документация golden-source). Остаются только два P3-наблюдения (косметика/недостижимая граница), не блокирующие приёмку. Полный pytest tests/ зелёный (2052 passed), инварианты конвейера и схемы существующих таблиц — байт-в-байт. → APPROVED.