--- type: test-report work_item_id: ORCH-026 result: PASS --- # Test Report — ORCH-026 Задача: «Управление зависимостями задач (B ждёт A) в очереди» + сериализация merge/деплоя одного репо. Ветка `feature/ORCH-026-b-a`. Review-вердикт: **APPROVED** (`12-review.md`). ## Окружение - Python: 3.12.13 - pytest: 8.3.3 - Ветка: `feature/ORCH-026-b-a` (HEAD `aaa4829`) - Прод-оркестратор (8500): `/health` → `{"status":"ok"}` (не перезапускался, self-hosting инвариант соблюдён) - Дата: 2026-06-08 ## Результаты по тест-плану (04-test-plan.yaml) ### Уровень A — сериализация merge/деплоя | TC ID | Описание | Тест-функция | Результат | |-------|----------|--------------|-----------| | TC-A01 | Proactive pre-merge rebase (всегда, даже когда не behind) | `test_orch026_premerge_rebase::test_always_rebases_even_when_not_behind` | PASS | | TC-A02 | Расширенное окно merge-lease, defer не откат; holder-aware release | `test_orch026_merge_serialize::test_second_task_same_repo_defers_not_rollback`, `test_holder_aware_release_keeps_foreign_lease` | PASS | | TC-A03 | Сериализация строго per-repo (orchestrator ≠ enduro-trails) | `test_orch026_merge_serialize::test_serialization_is_strictly_per_repo` | PASS | | TC-A04 | Restart-safe + реклейм мёртвого держателя lease | `test_orch026_merge_serialize::test_dead_holder_lease_is_reclaimed`, `test_stale_lease_age_reclaimed_on_acquire` | PASS | | TC-A05 | Anti-livelock defer: bounded бюджет, эскалация | `test_orch026_merge_serialize::test_defer_budget_is_bounded` | PASS | | TC-A06 | Условность/kill-switch: off + out-of-scope = no-op | `test_orch026_conditionality::test_out_of_scope_repo_is_noop_even_with_flag_on`, `test_premerge_rebase::test_flag_off_short_circuits_like_orch043` | PASS | | TC-A07 | Self-hosting safety: только `--force-with-lease` на ветку, STAGE_TRANSITIONS не тронуты | `test_orch026_conditionality::test_premerge_only_force_with_lease_on_branch`, `test_stage_transitions_unchanged` | PASS | | TC-A08 | Сквозной сценарий сериализации merge-окна | `test_orch026_serialize_integration::test_serialized_merge_window` | PASS | ### Уровень B — декларативные зависимости | TC ID | Описание | Тест-функция | Результат | |-------|----------|--------------|-----------| | TC-B01 | Декларация/резолв blocked-by; never-raise при недоступности | `test_orch026_task_deps::test_add_dependency_declares_and_resolves`, `test_add_dependency_never_raises_on_bad_input` | PASS | | TC-B02 | Гейт готовности: незавершённый depends-on → не ready; все done → ready | `test_orch026_task_deps::test_is_task_ready_blocked_then_ready`, `test_is_task_ready_no_deps_is_ready` | PASS | | TC-B03 | Детект циклов A→B→A и длиннее; ацикличный → нет | `test_orch026_dep_cycles::test_detect_two_node_cycle`, `test_detect_longer_cycle`, `test_acyclic_graph_has_no_cycle`, `test_detect_cycle_never_raises_on_garbage` | PASS | | TC-B04 | Цикл → Blocked + alert без падения воркера | `test_orch026_dep_cycles::test_handle_cycle_blocks_and_alerts`, `test_handle_cycle_never_raises_when_notify_fails` | PASS | | TC-B05 | claim_next_job не клеймит заблокированную (слот свободен), разблокируется при done | `test_orch026_task_deps::test_claim_skips_dep_blocked_job`, `test_claim_prefers_unblocked_job_over_blocked` | PASS | | TC-B06 | Видимость: строка ожидания в карточке; never-raise рендер | `test_orch026_dep_visibility::test_blocked_task_shows_waiting_line`, `test_render_never_raises_on_dep_error` | PASS | | TC-B07 | reconciler F-1 не разблокирует dep-заблокированную | `test_orch026_task_deps::test_reconciler_skip_helper_honours_block` | PASS | | TC-B08 | Сквозной: B стартует только после A→done; multiple predecessors | `test_orch026_deps_integration::test_b_waits_for_a_then_runs`, `test_multiple_predecessors_all_must_be_done`, `test_ingest_plane_relations_writes_db` | PASS | ### Общие / миграция / регресс | TC ID | Описание | Тест-функция | Результат | |-------|----------|--------------|-----------| | TC-G01 | Аддитивная миграция job_deps: идемпотентна, данные сохранены | `test_orch026_migration::test_job_deps_table_created`, `test_job_deps_indices_created`, `test_migration_idempotent_and_preserves_data` | PASS | | TC-G02 | Наблюдаемость GET /queue: read-only блок task_deps | `test_orch026_queue_observability::test_queue_endpoint_includes_task_deps`, `test_snapshot_*` | PASS | | TC-G03 | Регресс: полный pytest зелёный | `tests/` (991 passed) | PASS | ## Smoke test API (прод 8500) - `GET /health` → `{"status":"ok","service":"orchestrator"}` — OK - `GET /status` → активные задачи отдаются, ORCH-026 (id 58) в стадии `testing` — OK - `GET /queue` → counts/resilience/reconcile/reaper/merge_verify читаются; брейкер `closed`, preflight OK — OK - Примечание: блок `task_deps` в `/queue` прода 8500 ОТСУТСТВУЕТ — ожидаемо: прод-контейнер несёт текущую задеплоенную версию, ORCH-026 ещё не выкатан (self-hosting, деплой на поздних стадиях). Фича наблюдаемости верифицирована in-branch тестом `test_queue_endpoint_includes_task_deps` (PASS) через TestClient на коде ветки. ## Вывод pytest ``` tests/test_orch026_*.py — 50 passed, 1 warning in 1.56s tests/ — 991 passed, 1 warning in 26.52s ``` (единственный warning — PydanticDeprecatedSince20 в `src/config.py`, предсуществующий, не относится к ORCH-026) ## Покрытие критериев приёмки (03-acceptance-criteria.md) Все 16 критериев (AC-A1…A7, AC-B1…B5, AC-G1…G5) покрыты прохождением соответствующих TC и подтверждены review-вердиктом APPROVED. Регрессии merge-gate (ORCH-043), merge-verify (ORCH-073), reconciler (ORCH-053/068), reaper (ORCH-065) не обнаружено. ## Итог **PASS** — 50/50 новых ORCH-026-тестов зелёные, полный регресс 991 passed, smoke API OK, прод-контейнер не затронут. Задача готова к переходу на `deploy-staging`.