diff --git a/docs/work-items/ORCH-065/13-test-report.md b/docs/work-items/ORCH-065/13-test-report.md new file mode 100644 index 0000000..5a649df --- /dev/null +++ b/docs/work-items/ORCH-065/13-test-report.md @@ -0,0 +1,92 @@ +--- +type: test-report +work_item_id: ORCH-065 +result: PASS +--- + +# Test Report — ORCH-065 + +Тема: job-reaper + проактивный реклейм stale/dead merge-lease + идемпотентная +финализация merge. Прогон полного регресса в ветке +`feature/ORCH-065-bug-zombie-jobs-merge-lease-ru`. Review-вердикт — APPROVED (v3). + +## Окружение +- Python: 3.12.13 +- pytest: 8.3.3 +- Ветка: feature/ORCH-065-bug-zombie-jobs-merge-lease-ru (worktree) +- Прод (8500): health `200 {"status":"ok"}` — НЕ перезапускался (self-hosting инвариант соблюдён) +- Дата: 2026-06-07 + +## Smoke API (прод 8500, read-only) +| Endpoint | Результат | +|----------|-----------| +| `GET /health` | 200 `{"status":"ok","service":"orchestrator"}` | +| `GET /status` | 200, активные задачи отдаются (ORCH-065 в `testing`, ET-013 в `development`) | +| `GET /queue` | 200, counts/resilience/reconcile/post_deploy присутствуют | + +Примечание: блок `reaper` в `/queue` прода (8500) ОТСУТСТВУЕТ — ожидаемо, т.к. прод +исполняет ещё не задеплоенный (до-ORCH-065) код. Контракт блока `reaper` проверен +тестом TC-18 (`tests/test_queue.py::test_tc18_queue_endpoint_has_reaper_block`) +против кода ветки — PASS. Curl недоступен в окружении, smoke выполнен через +`urllib.request` (read-only, без побочных эффектов на прод). + +## Результаты по тест-плану (04-test-plan.yaml) + +| TC ID | Тип | Модуль | Покрывает | Результат | +|-------|-----|--------|-----------|-----------| +| TC-01 | unit | test_job_reaper.py | AC-1 (реап мёртвого job без рестарта) | PASS | +| TC-02 | unit | test_job_reaper.py | AC-3 (живой агент не реапится) | PASS | +| TC-03 | unit | test_job_reaper.py | FR-1.3 (устойчивость reaper_dead_ticks) | PASS | +| TC-04 | unit | test_job_reaper.py | FR-1.1/AC-1 (backstop reaper_max_running_s) | PASS | +| TC-05 | unit | test_job_reaper.py | AC-4 (исход по результату: done/queued/failed) | PASS | +| TC-06 | unit | test_job_reaper.py | AC-5 (атомарность reap-UPDATE guard) | PASS | +| TC-07 | unit | test_job_reaper.py | AC-14 (kill-switch reaper_enabled=false) | PASS | +| TC-08 | unit | test_job_reaper.py | AC-9 (never-raise per-job) | PASS | +| TC-09 | integration | test_queue.py | AC-2 (разблокировка очереди concurrency=1) | PASS | +| TC-10 | unit | test_merge_lease_reclaim.py | AC-6 (реклейм lease мёртвого pid) | PASS | +| TC-11 | unit | test_merge_lease_reclaim.py | AC-7 (реклейм по TTL сохранён) | PASS | +| TC-12 | unit | test_merge_lease_reclaim.py | AC-8 (живой lease не трогается) | PASS | +| TC-13 | unit | test_merge_lease_reclaim.py | AC-9 (условность self-hosting/no-op) | PASS | +| TC-14 | unit | test_merge_lease_reclaim.py | AC-9 (never-raise при ошибке lease-файла) | PASS | +| TC-15 | unit | test_merge_lease_reclaim.py | AC-14 (kill-switch lease_reclaim_enabled=false) | PASS | +| TC-16 | unit | test_merge_gate.py | AC-11 (идемпотентность при уже слитом PR) | PASS | +| TC-17 | integration | test_merge_gate_race.py | AC-10 (докатывание незавершённого merge) | PASS | +| TC-18 | integration | test_queue.py | AC-15 (блок reaper в /queue) | PASS | +| TC-19 | unit | test_config.py | AC-13 (контракты STAGE_TRANSITIONS/QG_CHECKS неизменны) | PASS | +| TC-20 | unit | test_config.py | §5/AC-14 (новые настройки reaper_*/lease_reclaim_*) | PASS | +| TC-21 | unit | test_job_reaper.py | FR-2.1/AC-6 (стартовый реклейм в lifespan) | PASS | + +Все 21 TC из плана — PASS. + +## Сопоставление с критериями приёмки (03-acceptance-criteria.md) +- A (AC-1…AC-5): job-reaper — покрыты TC-01..TC-06, TC-09 → PASS +- B (AC-6…AC-9): lease-reclaim — покрыты TC-10..TC-15 → PASS +- C (AC-10, AC-11): идемпотентная финализация — TC-16, TC-17 → PASS +- D (AC-12 прод не трогается, AC-13 контракты, AC-14 kill-switches): TC-07, TC-15, TC-19, TC-20 + smoke прода без рестарта → PASS +- E (AC-15 /queue, AC-16 логи/алерты): TC-18 → PASS +- F (AC-17 документация): review подтвердил обновление README/internals/ADR-001/adr-0011/CHANGELOG/.env.example (APPROVED) → PASS +- G (AC-18 регресс зелёный): `pytest tests/` 747 passed → PASS + +## Вывод pytest + +### Целевые модули плана +``` +$ python -m pytest tests/test_job_reaper.py tests/test_merge_lease_reclaim.py \ + tests/test_merge_gate.py tests/test_merge_gate_race.py \ + tests/test_queue.py tests/test_config.py -q +92 passed, 1 warning in 3.40s +``` + +### Полный регресс +``` +$ python -m pytest tests/ -v --tb=short +======================= 747 passed, 1 warning in 15.47s ======================== +``` +(1 warning — PydanticDeprecatedSince20 в src/config.py, не связан с ORCH-065, +предсуществующий.) + +## Итог +**PASS.** Полный регресс — 747 passed, 0 failed. Все 21 TC тест-плана зелёные, +все критерии приёмки (AC-1…AC-18) подтверждены. Smoke прода — health/status/queue +200 OK, прод-контейнер не перезапускался (self-hosting инвариант соблюдён). +Задача готова к переходу на стадию `deploy-staging`.