Files
orchestrator/docs/work-items/ORCH-116/12-review.md
claude-bot e12b03b235
All checks were successful
CI / test (push) Successful in 1m16s
CI / test (pull_request) Successful in 1m23s
reviewer(ET): auto-commit from reviewer run_id=757
2026-06-16 10:11:33 +03:00

11 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-116 review reviewer approved 2026-06-16 claude-opus-4-8 review ORCH-116 4

Review ORCH-116 — детерминированный test-раннер вместо LLM-тестера

Машинный вердикт читается ТОЛЬКО из verdict: во frontmatter.

Summary

Реализация полностью соответствует ТЗ (02-trz.md), критериям приёмки (03-acceptance-criteria.md) и ADR-001 / adr-0050. ORCH-116 заменяет LLM-агента tester на стадии testing детерминированным leaf src/test_runner.py, перехватываемым в launch_job до _spawn — точное зеркало эталона src/staging_runner.py (ORCH-115). Критический инвариант NFR-1 соблюдён байт-в-байт: гейт check_tests_passed / _parse_tests_verdict, STAGE_TRANSITIONS, QG_CHECKS, machine-key result: и схема БД не тронуты (это замена продюсера артефакта, не гейта). Тонкая мина D6.1 (52c-status: ↔ парсер с negative-token-priority) обработана корректно и прибита тестом через неизменённый парсер. Документация обновлена в полном объёме (CLAUDE.md / CHANGELOG / README / internals / витрина docs/overview/ / LLM-карта/roadmap/policy / tester.md / .env.example). Все 4 оси — зелёные. Findings уровня P0/P1, относящихся к ORCH-116, нет.

Оси проверки

1. Соответствие ТЗ / AC — PASS

  • FR-1 / AC-1 перехват до _spawn: launcher.launch_job врезка if job.get("agent")=="tester" and test_runner.should_intercept(job): return self._run_test_runner_job(job) рядом с D1/D2/ORCH-115; _run_test_runner_job — зеркало _run_staging_runner_job, ведёт jobs через mark_job, возвращает None (нет agent_runs). ✔ (TC-05).
  • FR-2/3 / AC-3/AC-11 pytest в worktree через proc_group (tree-kill, _resolve_timeout fail-safe), маппинг map_exit_code_to_result поверх единого self_deploy.map_exit_code_to_status (без второго маппинга). ✔ (TC-02, TC-12).
  • FR-4 / AC-2 write_test_reportresult: UPPERCASE + 52c-схема, author_agent: test-runner / model_used: n/a, push только в фичеветку (без merge в main). ✔ (TC-03, TC-04).
  • FR-5 / AC-4 _advance вызывает advance_stage(current_stage="testing", finished_agent="tester") — FAIL-ветвь stage_engine.py:849 матчит по agent=="tester". ✔ (TC-07).
  • FR-6 / AC-5 two-level outcome: suite_ran=(returncode is not None) and (not timed_out); tool-error → bounded DEFER (re-queue именно tester-джоба + restart-safe маркер), на исчерпании → fail-closed FAIL + advance + INFRA-alert. ✔ (TC-10).
  • FR-7 / AC-7/AC-8 applies() = kill-switch + скоуп + _has_test_contract (репо без контракта → LLM-tester даже при ручном добавлении в CSV). ✔ (TC-01, TC-08).
  • FR-8 / AC-13 блок test_runner в GET /queue + счётчики + структурный лог, различающий code-fail / tool-error. ✔ (TC-14).
  • FR-9 / AC-12 гибрид: LLM вне control-path вердикта. ✔.

2. Соответствие ADR / инварианты — PASS

  • NFR-1 / AC-6: git diff origin/main...HEAD НЕ затрагивает src/stages.py, src/qg/, src/stage_engine.py, src/staging_runner.py, src/proc_group.py, src/transition_lease.py, src/git_worktree.py — проверено явно (пустой diff). ✔.
  • D6.1 (ключевая мина): _parse_tests_verdict (src/qg/checks.py:263-277) читает вердикт из трёх полей с приоритетом негативного токена. Раннер выравнивает status: по вердикту (PASS→success «SUCCESS» — не позитивный и не негативный токен → True берётся из result: PASS; FAIL→failed «FAILED» — негативный → False). Проверено вручную по логике парсера и тестом TC-04 (test_tc04_status_field_never_false_negatives_a_pass) через неизменённый парсер. ✔.
  • Граница O1: staging_runner (ORCH-115), transition_lease (ORCH-114), checkout_hygiene (ORCH-112) не модифицированы — соответствует требованию. ✔.
  • Трассировка: новые врезки корректно ссылаются на прецеденты D1/D2/ORCH-115; зафиксированные инварианты конвейера не сломаны. ✔.

3. Качество кода — PASS

  • never-raise соблюдён во всех публичных функциях (applies/should_intercept/run_test_gate/ snapshot/write_test_report/run_smoke — guarded; TC-01/TC-06/TC-11/TC-14 покрывают).
  • Лениво импортируются тяжёлые модули — leaf-чистота сохранена (импорт на уровне модуля только config/logging/proc_group).
  • Тесты содержательные (14 TC + анти-дрейф TC-15), без живого Claude CLI/сети; покрывают happy/FAIL/ tool-error/never-raise/kill-switch/scope/smoke/observability.
  • Это feature-трек (не Bug), регресс-тест-фиксатор (ORCH-019 BR-4) не требуется; покрытие тем не менее исчерпывающее.

4. Документация — PASS (обязательная проверка)

src/ изменён → документация обновлена в том же PR, проверено пофайлово:

  • CLAUDE.md — новый раздел «Детерминированный test-раннер (ORCH-116)». ✔
  • CHANGELOG.md — детальная запись [Unreleased]. ✔
  • docs/architecture/README.md — компонент Test-runner + блок roadmap «второй срез реализован». ✔
  • docs/architecture/internals.md — примечание о перехвате на testing. ✔
  • docs/architecture/llm-call-sites.md (A5), llm-determinization-roadmap.md (rank 2), llm-usage-policy.md (§5) — обновлены; инвариант «ровно один first_slice=yes» сохранён (deployer=yes, tester=no), анти-дрейф tests/test_llm_call_site_inventory.py / test_llm_determinization_docs.py — зелёные. ✔
  • Витрина docs/overview/ (ORCH-011): tech-pipeline.md / tech-agents.md / tech-quality-security.md обновлены; tests/test_system_docs.py зелёный. ✔
  • .openclaw/agents/tester.md — LLM-ветвь помечена fallback'ом (канон 52d цел). ✔
  • .env.example — все 7 ключей ORCH_TEST_RUNNER_*. ✔
  • ADR + сквозной adr-0050 присутствуют. ✔

Тесты (AC-15)

  • tests/test_orch116_test_runner.py + LLM анти-дрейф — 45 passed.
  • Полный регресс pytest tests/ -q2162 passed, 1 failed (84s). Единственный фейл — tests/test_orch123_staging_runner_exec.py::test_r2_held_deploy_staging_not_rolled_back (см. P2).

Findings

P0 — Blocker

  • (нет)

P1 — Must fix

  • (нет)

P2 — Should fix

  • [Вне ORCH-116, для отдельного follow-up] Pre-existing test-isolation flake в ORCH-123. В полном прогоне падает tests/test_orch123_staging_runner_exec.py::test_r2_held_deploy_staging_ not_rolled_back. Доказано, что это не дефект ORCH-116: (1) тест зелёный в изоляции и в своём файле; (2) фейл воспроизводится при прогоне полного сьюта без tests/test_orch116_test_runner.py (--ignore) → 1 failed; (3) ORCH-116 не трогает src/staging_runner.py (граница O1, корректно). Это загрязнение глобального состояния от соседнего теста в ORCH-123-коде (недавно влит в main). AC-15 в части «ORCH-116 не краснит ранее зелёные тесты» удовлетворён. Рекомендация: завести отдельный bug на изоляцию теста ORCH-123 — он вне области ORCH-116 и не должен блокировать этот PR.

P3 — Nice to have

  • run_smoke (src/test_runner.py:291) дублирует литерал "http://localhost:8500", который уже является дефолтом settings.post_deploy_base_url. Это безвредный defensive double-default (localhost/8500 НЕ в FORBIDDEN-списке test_no_host_hardcodes — нарушения нет); можно опереться только на дефолт config. Косметика.
  • Smoke-провал из-за транзиентного блипа прод-8500 после bounded-ретраев даёт FAIL → откат + расход developer-retry (формально инфра, трактуемая как код-фейл — родственно классу ORCH-110). Архитектор осознанно взвесил это в ADR (D3 + Consequences «−»): bounded smoke-ретрай + config-gate test_runner_smoke_enabled + developer-retry-cap; поведение эквивалентно прежнему LLM-tester (curl /health). Принято как задокументированный компромисс; не блокирует.

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

Обновлена в полном объёме в том же PR (см. ось 4). Изменение src/ сопровождено обновлением паспорта, чейнджлога, архитектурной карты, internals, витрины docs/overview/, LLM-карты/roadmap/ политики, промпта tester.md, .env.example и ADR (локальный + сквозной). Машинно-проверяемые факты витрины и LLM-карты держатся зелёными анти-дрейф-тестами. Требование «документация = golden source» выполнено → блокирующих документационных findings нет.

Вердикт

Нет P0/P1, относящихся к ORCH-116. Все четыре оси (ТЗ, ADR/инварианты, качество кода, документация) пройдены; критические инварианты сохранены байт-в-байт; покрытие исчерпывающее. APPROVED. Единственный красный тест полного сьюта — pre-existing flake ORCH-123 (P2), доказанно независимый от ORCH-116 и вне его области правки.