--- result: PASS work_item: ORCH-115 stage: testing author_agent: tester status: pass created_at: 2026-06-16 model_used: claude-opus-4-8 type: test-report work_item_id: ORCH-115 --- # Test Report — ORCH-115 — детерминированный staging-раннер вместо LLM-деплойера ## Окружение - Python: 3.12.13 - pytest: 8.3.3 (plugins: cov-5.0.0, anyio-4.13.0, asyncio-0.23.8) - Worktree (изолированный, ветка задачи): `/repos/_wt/orchestrator/feature_ORCH-115-orch-replace-llm-deployer-with` - Ветка: `feature/ORCH-115-orch-replace-llm-deployer-with` - Дата: 2026-06-16 - Review verdict (`12-review.md`): **APPROVED** (P0/P1 — нет) ✅ предусловие стадии выполнено ## Команды - Полный регресс: `pytest tests/ -q --tb=short` - Целевой сьют + анти-дрейф LLM: `pytest tests/test_orch115_staging_runner.py tests/test_llm_call_site_inventory.py tests/test_llm_determinization_docs.py -v` - Покрытие leaf: `pytest tests/test_orch115_staging_runner.py --cov=src.staging_runner --cov-report=term-missing` - Smoke (read-only): `curl -s http://localhost:8500/{health,status,queue}` ## Результаты — покрытие плана тестов (`04-test-plan.yaml`) Каждый TC сопоставлен с критериями `03-acceptance-criteria.md` и подтверждён конкретными тест-функциями. | TC ID | Тип | Описание (кратко) | AC | Тест-функции | Результат | |-------|-----|-------------------|----|--------------|-----------| | TC-01 | unit | `applies(repo)`: kill-switch / скоуп / not-self / never-raise→False | AC-6/AC-7 | `test_tc01_applies_killswitch_and_scope`, `test_tc01_applies_never_raises` | PASS | | TC-02 | unit | Маппинг exit-кода `0→SUCCESS`, иначе/None→`FAILED` (контракт `self_deploy.map_exit_code_to_status`) | AC-3 | `test_tc02_map_exit_code` | PASS | | TC-03 | unit | Рендер `15-staging-log.md`: `staging_status:` UPPERCASE + 52c-схема; INFRA-WAIVED в тело | AC-2 | `test_tc03_log_render_schema_and_infra_waived` | PASS | | TC-04 | integration | Лог читается **неизменённым** `_parse_staging_status` для SUCCESS/FAILED | AC-2 | `test_tc04_gate_parser_unchanged` | PASS | | TC-05 | integration | `launch_job` перехватывает до `_spawn`, нет `agent_runs`, `mark_job` ведёт строку | AC-1 | `test_tc05_launch_job_intercepts_before_spawn` | PASS | | TC-06 | integration | Дискриминатор стадии: `deploy` (prod) и not-self репо НЕ перехватываются | AC-1 | `test_tc06_stage_discriminator_prod_not_intercepted`, `test_tc06_non_self_repo_not_intercepted` | PASS | | TC-07 | integration | SUCCESS/FAILED → `advance_stage(finished_agent="deployer")` как у LLM | AC-4 | `test_tc07_advance_initiated_like_llm[0-SUCCESS]`, `[1-FAILED]` | PASS | | TC-08 | integration | Kill-switch `=False` → прежний LLM-путь через `_spawn` (байт-в-байт) | AC-6 | `test_tc08_killswitch_falls_back_to_spawn` | PASS | | TC-09 | unit | Анти-дрейф NFR-1: `STAGE_TRANSITIONS`/`QG_CHECKS`/`staging_status:`/схема БД неизменны | AC-5 | `test_tc09_pipeline_contract_unchanged` | PASS | | TC-10 | integration | never-raise/fail-safe: ненулевой→FAILED+advance; таймаут→DEFER; бюджет исчерпан→FAILED; раннер не падает | AC-7 | `test_tc10_nonzero_exit_is_failed_and_advances`, `test_tc10_timeout_defers_without_advance`, `test_tc10_tool_error_budget_exhausted_fails_closed`, `test_tc10_run_gate_never_raises`, `test_tc10_launcher_contains_runner_fault` | PASS | | TC-11 | unit | Таймаут `staging_runner_timeout_s`; малформ→дефолт+WARNING; передаётся в `proc_group` | AC-9 | `test_tc11_resolve_timeout_default_on_bad_value`, `test_tc11_timeout_passed_to_proc_group` | PASS | | TC-12 | unit | Self-hosting safety: нет запрещённых литералов (рестарт 8500 / `up` / `--build` / force-push) | AC-8 | `test_tc12_command_has_no_dangerous_literals` | PASS | | TC-13 | integration | Наблюдаемость: блок `staging_runner` в `/queue` + структурный лог-вердикт (различает код-фейл/tool-error) | AC-10 | `test_tc13_snapshot_shape`, `test_tc13_queue_endpoint_includes_block`, `test_tc13_structured_verdict_log_distinguishes_outcomes`, `test_tc13_snapshot_never_raises` | PASS | | TC-14 | integration | Анти-дрейф LLM-карты: `llm-call-sites.md`(A6)/roadmap/policy обновлены, анти-дрейф зелёный | AC-11 | `test_llm_call_site_inventory.py` (9 тестов), `test_llm_determinization_docs.py` (3 теста) | PASS | **Итог по плану: 14/14 TC выполнены и PASS.** Каждый AC (AC-1…AC-12) покрыт; AC-12 (полный регресс) подтверждён прогоном всего `tests/`. ## Smoke API (read-only, prod 8500) - `GET /health` → `{"status":"ok","service":"orchestrator"}` ✅ - `GET /status` → отвечает, активные задачи перечислены (включая ORCH-115 на `testing`) ✅ - `GET /queue` → отвечает; блок **`serial_gate`** присутствует (ORCH-088) ✅; блок **`auto_labels`** присутствует ✅. Полный набор ключей: `auto_labels, bug_fast_track, build_cache_prune, checkout_hygiene, counts, coverage, disk_monitor, fs_ownership, lessons, max_concurrency, merge_gate, merge_verify, poll_interval, post_deploy, reaper, recent, reconcile, resilience, serial_gate, stop, task_deps, transition_lease`. > Примечание: read-only блок `staging_runner` (FR-7) на боевом 8500 ещё отсутствует — это ожидаемо, > т.к. ORCH-115 не задеплоен в прод. Наличие блока в коде ветки подтверждено тестами TC-13 > (`test_tc13_queue_endpoint_includes_block`). Это **не** регресс смока: обязательный для смока > блок `serial_gate` присутствует. ## Покрытие нового кода `src/staging_runner.py` — **83%** (211 стэйтментов, 36 непокрытых). Непокрытые строки — исключительно defensive `except`-ветви контракта never-raise (согласовано с `12-review.md`). ## Вывод pytest Полный регресс: ``` ........................................................................ [100%] 2105 passed, 1 warning in 93.61s (0:01:33) ``` Целевой сьют ORCH-115 + анти-дрейф LLM: ``` tests/test_orch115_staging_runner.py ......................... (24 passed) tests/test_llm_call_site_inventory.py ......................... (9 passed) tests/test_llm_determinization_docs.py ...................... (3 passed) ======================== 37 passed, 1 warning in 1.80s ========================= ``` Единственное предупреждение — `PydanticDeprecatedSince20` (class-based `config`), не относится к ORCH-115, присутствовало до изменения. ## Итог **PASS** — полный регресс зелёный (2105 passed), целевой сьют (24 теста) и анти-дрейф LLM-карты (12 тестов) зелёные, все 14 TC выполнены и сопоставлены с AC, smoke read-only OK (`serial_gate` и `auto_labels` присутствуют в `/queue`). Машинный вердикт: `result: PASS` → задача переходит на `deploy-staging`.