Files
orchestrator/docs/work-items/ORCH-116/04-test-plan.yaml
claude-bot 50c48c2c03
All checks were successful
CI / test (push) Successful in 1m8s
analyst(ET): auto-commit from analyst run_id=738
2026-06-16 02:29:50 +03:00

117 lines
8.4 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
work_item: ORCH-116
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-16
model_used: claude-opus-4-8
title: "Детерминированный test-раннер вместо LLM-тестера (стадия testing)"
framework: pytest
scope: >
Покрывает Phase 1: перехват tester-джоба на стадии testing до _spawn, исполнение
тест-контракта (pytest через proc_group + опц. read-only smoke), маппинг exit-кода
в result: PASS|FAIL, запись/push 13-test-report.md, инициацию существующего гейта
check_tests_passed, two-level outcome (tool-error DEFER, анти-ORCH-110), kill-switch/
скоуп/backward-compat для репо без тест-контракта, never-raise/fail-safe, изоляцию
процесса/таймаут (tree-kill), гибрид (LLM не в control-path вердикта), наблюдаемость,
и анти-дрейф инвариант (STAGE_TRANSITIONS/QG_CHECKS/check_tests_passed/_parse_tests_verdict/
схема БД не тронуты). Вне покрытия: Phase 2 (project test contract для не-self репо,
off-control-path LLM-триаж), ORCH-115 staging/deploy-раннер, LLM-роли reviewer/developer,
живой Claude CLI и живой прод-стенд (мокируются).
notes: >
Тесты не требуют живого Claude CLI или сети: subprocess/pytest-run (proc_group) и
advance_stage мокируются; пьюр-маппинг и рендер frontmatter тестируются напрямую;
smoke-GET мокируются. Полный регресс tests/ должен оставаться зелёным. Анти-дрейф
(TC-09) защищает критический инвариант NFR-1. Эталон реализации/покрытия —
tests/test_orch115_staging_runner.py (ORCH-115).
tests:
- id: TC-01
type: unit
description: "applies(repo): enabled=False -> False (откат к LLM); пустой CSV -> True только для orchestrator; непустой CSV -> membership; репо без резолвимого тест-контракта -> False (BR-9 backward-compat); ошибка -> False (never-raise, fail-safe)."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-02
type: unit
description: "Маппинг exit-кода: 0 -> PASS; 1/2/любой ненулевой -> FAIL; None/нечисло/ошибка запуска -> FAIL (fail-closed). Токены PASS/FAIL согласованы с _parse_tests_verdict; второй несогласованный маппинг не вводится."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-03
type: unit
description: "Рендер 13-test-report.md: frontmatter содержит result: PASS|FAIL (UPPERCASE) + 52c-схему (work_item/stage=testing/author_agent=test-runner/status/created_at/model_used=n/a); хвост stdout pytest и smoke-итог копируются в тело."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-04
type: integration
description: "Сгенерированный раннером 13-test-report.md читается НЕИЗМЕНЁННЫМ _parse_tests_verdict -> корректный (bool, reason) для PASS и FAIL (контракт артефакта/гейта check_tests_passed неизменен)."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-05
type: integration
description: "launch_job перехватывает tester-джоб на стадии testing для in-scope репо ДО _spawn (как D1/D2/ORCH-115): _spawn НЕ вызывается, agent_runs не создаётся, возвращается None, jobs-строка ведётся mark_job. _spawn мокирован."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-06
type: integration
description: "Дискриминатор: tester-джоб на стадии НЕ testing (защита) и любой не-tester джоб НЕ перехватываются раннером; should_intercept never-raise -> False при DB-сбое (fall-through к _spawn)."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-07
type: integration
description: "После PASS-вердикта раннер инициирует advance_stage(finished_agent='tester') ровно как завершившийся LLM-tester (advance_stage мокирован/наблюдается) -> check_tests_passed -> testing->deploy-staging; после FAIL — существующий откат testing->development + developer-retry (stage_engine.py:849)."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-08
type: integration
description: "Kill-switch: test_runner_enabled=False -> на testing для orchestrator вызывается _spawn (прежний LLM-путь байт-в-байт), раннер не активируется."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-09
type: unit
description: "Анти-дрейф NFR-1: STAGE_TRANSITIONS (src/stages.py), реестр/имена QG_CHECKS, check_tests_passed/_parse_tests_verdict и токены result:/verdict:/status: неизменны; в схеме БД нет новой таблицы/колонки от ORCH-116. Структурная проверка."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-10
type: integration
description: "Two-level outcome (анти-ORCH-110): сюита НЕ исполнилась (spawn-error/таймаут/returncode None) -> bounded DEFER (re-queue tester-джоба + restart-safe маркер), БЕЗ отката на development и БЕЗ расхода developer-retry; на исчерпании test_runner_infra_max_retries -> fail-closed FAIL + advance + INFRA-alert. Никогда тихий advance/ложный green."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-11
type: unit
description: "never-raise/fail-safe: pytest-run бросает/таймаутит/worktree-ошибка -> раннер не падает, исход FAIL (fail-closed) или bounded DEFER, никогда тихий advance/ложный green; воркер/очередь не клинятся. Все публичные функции test_runner.py never-raise."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-12
type: unit
description: "Изоляция/таймаут: pytest исполняется в worktree ветки задачи через proc_group.run_in_process_group (tree-kill); test_runner_timeout_s применяется; малформ/непозитив -> дефолт 900 + WARNING (never-break); reaper_max_running_s не правится."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-13
type: unit
description: "Self-hosting safety: в командах раннера нет запрещённых литералов (рестарт 8500 / docker compose up orchestrator / --build / force-push main / правки .env); smoke-запросы строго read-only GET (/health,/status,/queue); лог пушится только в фичеветку."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-14
type: integration
description: "Наблюдаемость + гибрид: GET /queue содержит блок test_runner (enabled/repos/target/счётчики runs/pass/fail/tool_error/deferred); на прогон пишется один структурный лог-вердикт, различающий код-фейл и tool-error; LLM не вызывается для вынесения result: в happy/fail-path."
module: tests/test_orch116_test_runner.py
expected: PASS
- id: TC-15
type: integration
description: "Анти-дрейф LLM-карты: llm-call-sites.md (A5)/roadmap (rank 2)/policy обновлены под реализацию (инвариант 'ровно один first_slice=yes' цел); tests/test_llm_call_site_inventory.py и tests/test_llm_determinization_docs.py остаются зелёными после правок."
module: tests/test_llm_call_site_inventory.py
expected: PASS