8.9 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-116 | architecture | architect | proposed | 2026-06-16 | claude-opus-4-8 |
10 — Технические риски: ORCH-116 — детерминированный test-раннер
Work Item: ORCH-116 · Repo: orchestrator · Стадия: architecture
Информационный (гейтом не парсится). Покрывает риски BRD §8 (R-1…R-7) + риски, выявленные архитектором по коду (TR-8…TR-11, специфичные для роли
tester/ стадииtesting).
Реестр рисков
| ID | Риск | Вер. | Влия. | Митигейшн |
|---|---|---|---|---|
| TR-1 (R-1) | Точка диспетчеризации «до _spawn» перехватывает не тот джоб |
Низ. | Выс. | should_intercept = agent=="tester" И applies(repo) И tasks.stage=="testing" (D1). Роль tester исполняет ТОЛЬКО testing (STAGE_TRANSITIONS["review"]["agent"]) → коллизии стадий нет; гард по стадии — defense-in-depth. never-raise → False → _spawn. Покрыто тестом перехвата/не-перехвата. |
| TR-2 (R-2) | После вердикта гейт не инициирован → задача зависает на testing |
Низ. | Выс. | D7: раннер вызывает advance_stage(current_stage="testing", finished_agent="tester") в run_test_gate (never-raise). finished_agent="tester" обязателен — FAIL-ветвь stage_engine.py:849 матчит по agent=="tester". Покрыто тестом PASS-advance и FAIL-rollback. |
| TR-3 (R-3) | Таймаут/изоляция pytest; утечка процессов (корень ORCH-109/110/111) | Сред. | Выс. | D3: pytest через proc_group.run_in_process_group (tree-kill SIGTERM→grace→SIGKILL); таймаут test_runner_timeout_s=900 (малформ→дефолт+WARNING); прогон в worktree ветки, не в общем клоне. Покрыто тестом изоляции/таймаута. |
| TR-4 (R-4) | Two-level outcome неверен: tool-error жжёт developer-retry (регресс ORCH-110) ИЛИ ложный green | Сред. | Выс. | D5: сюита исполнилась → verdict→advance; сюита НЕ исполнилась (spawn-error/таймаут/None) → bounded DEFER (re-queue tester-джоба, restart-safe маркер) → на исчерпании fail-closed FAIL+advance+alert. Никогда тихий advance/ложный green; не жжёт developer-retry на инфре. Покрыто тестом обоих уровней. |
| TR-5 (R-5) | Откат FAIL не совпадает с LLM-путём (developer-retry cap / extract_test_failures) |
Низ. | Сред. | D7 переиспользует существующий откат stage_engine.py:849-892 (тот же MAX_DEVELOPER_RETRIES, extract_test_failures, enqueue_job("developer", …)). Новой ветви маршрутизации нет. Покрыто тестом эквивалентности. |
| TR-6 (R-6) | LLM протаскивается обратно в поток управления вердикта (нарушение BR-8) | Низ. | Сред. | D11: детерминированный раннер — единственный продюсер result:; off-control-path триаж не реализуется и не добавляет ребро в STAGE_TRANSITIONS. Анти-дрейф LLM-карты (D12) + reviewer-ось AC-12. |
| TR-7 (R-7) | Backward-compat: репо без тест-контракта зависает без продюсера отчёта | Низ. | Выс. | D8: _has_test_contract(repo) (Phase 1 = self-hosting) — applies==False для не-self/без-контракта → should_intercept==False → прежний LLM-tester (fail-safe). Покрыто тестом для не-self репо. |
| TR-8 | 52c-status: ↔ парсер: ложный FAIL. _parse_tests_verdict читает вердикт из verdict:/status:/result: с negative-token-priority. 52c-status: failed ("FAILED") при result: PASS → негативный токен авторитетен → ложный FAIL здорового прогона. (Отсутствует в ORCH-115 — там гейт читает только staging_status:.) |
Сред. | Выс. | D6.1: status: ВСЕГДА выровнен по вердикту (success↔PASS / failed↔FAIL); "SUCCESS" — не негативный/не позитивный токен, позитив берётся из result: PASS. Обязательный unit-тест: _parse_tests_verdict(<тело раннера PASS>)==(True,…) и (FAIL)==(False,…) через неизменённый парсер. Reviewer: status:-литерал с негативным токеном при result: PASS → ≥P1. |
| TR-9 | Smoke против прод-8500 флапает. Разовый блип запущенного оркестратора (connection refused/таймаут) → FAIL → откат здоровой ветки + расход developer-retry. |
Сред. | Сред. | D3: bounded smoke-ретрай транзиентной недостижимости (несколько быстрых GET с коротким backoff) перед FAIL; «достижимо, но форма неверна» → немедленный FAIL. test_runner_smoke_enabled позволяет отключить smoke без отката раннера. pytest — первичный сигнал; developer-retry-cap поглощает остаточный шум. |
| TR-10 | DEFER re-queue'ит не тот агент. Копипаст из staging_runner мог бы re-queue'ить deployer-джоб → задача уйдёт в чужой обработчик. |
Низ. | Выс. | D5: DEFER re-queue'ит tester-джоб (enqueue_job("tester", …)), повторно входящий в этот раннер на стадии testing. Покрыто тестом DEFER (проверка роли re-queued джоба). |
| TR-11 | Дрейф LLM-карты/политики/витрины при реализации (NFR-6): инвариант «ровно один first_slice=yes» нарушен / avoidable=yes снят с tester / анти-дрейф-тесты красные. |
Сред. | Сред. | D12: точная спека правок (A5 → реализовано, но avoidable=yes/axis=C/needs-hybrid-fallback СОХРАНЯЮТСЯ; rank 2 tester → реализован, first_slice НЕ переключать — остаётся у rank 1/deployer). Правки атомарно с кодом в development + зелёные test_llm_call_site_inventory.py/test_llm_determinization_docs.py. Reviewer-ось AC-14 ≥P1. |
| TR-12 | Скоуп-дрейф: правка STAGE_TRANSITIONS/QG_CHECKS/check_tests_passed/_parse_tests_verdict/machine-verdict/схемы БД |
Низ. | Выс. | NFR-1: замена только продюсера. Анти-дрейф-тест на неизменность гейта/токенов/схемы (AC-6). Reviewer ловит как ≥P1. |
Сводный вывод
Доминирующий класс — корректность интеграции детерминированного раннера в существующий гейт
(finished_agent="tester", two-level outcome, эквивалентность отката) и две tester-специфичные
мины, которых не было в ORCH-115: (TR-8) коллизия 52c-status: с _parse_tests_verdict и
(TR-9) флап smoke против прод-8500. Обе закрыты архитектурно (D6.1 — жёсткое выравнивание status:
- unit-тест через неизменённый парсер; D3 — bounded smoke-ретрай + config-gate). Остаточный риск для
прод-конвейера (self-hosting) — низкий: leaf never-raise + kill-switch (мгновенный откат к
LLM-tester байт-в-байт), без правки гейта/стадии/схемы БД, граница с ORCH-112/114/115 соблюдена,
сквозной бюджет времени сохранён без правки
reaper_max_running_s.
Эскалация arch:major-change не требуется (нет новой стадии/QG/смены БД; новый компонент-leaf —
аддитивный, под kill-switch, по доказанному прецеденту ORCH-115). Возврат в анализ не требуется
(ТЗ удовлетворяется без нарушения принципов архитектуры).