---
type: test-report
work_item_id: ORCH-088
result: PASS
---

# Test Report — ORCH-088 (Per-repo serial gate, Этап 1: serial e2e)

## Окружение
- Python: 3.12.13
- pytest: 8.3.3 (plugins: anyio-4.13.0, asyncio-0.23.8; mode=AUTO)
- Repo / ветка: `orchestrator` / `feature/ORCH-088-orch-88-10-20`
- Дата: 2026-06-09T08:19Z

## Результаты

### Полный регресс
`python -m pytest tests/ -v --tb=short` → **1114 passed, 1 warning, 31.52s**.
Единственное предупреждение — известный `PydanticDeprecatedSince20` в `src/config.py:5`
(не относится к ORCH-088).

### Профильные сюиты ORCH-088 (24 теста, 0 fail)
`test_serial_gate*`, `test_queue_endpoint` → **24 passed, 1.39s**.

### Сопоставление с тест-планом `04-test-plan.yaml`

| TC ID | Описание | Тест | Результат |
|-------|----------|------|-----------|
| TC-01 | gate закрыт при активной задаче (claim не берёт analyst B) | `test_serial_gate::test_gate_closed_when_repo_has_active_task` | PASS |
| TC-02 | `serial_gate_applies`: enabled+пустой CSV/членство/вне CSV | `test_serial_gate::test_serial_gate_applies_scopes` | PASS |
| TC-03 | job'ы уже активной задачи gate'ом не блокируются | `test_serial_gate::test_non_analyst_job_of_active_task_passes` | PASS |
| TC-04 | автостарт B после A.stage='done' | `test_serial_gate_e2e::test_next_starts_automatically_when_predecessor_done` | PASS |
| TC-05 | очередь из 3 задач — строго по одной, FIFO по jobs.id | `test_serial_gate_e2e::test_three_tasks_processed_one_at_a_time_fifo` | PASS |
| TC-06 | restart-safe: активная задача из БД | `test_serial_gate_e2e::test_restart_safe_active_task_from_db` | PASS |
| TC-07 | freeze переживает рестарт | `test_serial_gate_freeze::test_freeze_survives_restart` | PASS |
| TC-08 | per-repo: orchestrator не блокирует enduro-trails | `test_serial_gate::test_per_repo_isolation` | PASS |
| TC-09 | freeze orchestrator не влияет на enduro-trails | `test_serial_gate_freeze::test_freeze_is_per_repo` | PASS |
| TC-10 | post-deploy DEGRADED → durable freeze + Telegram-алерт | `test_serial_gate_freeze::test_post_deploy_degraded_sets_freeze_and_alerts` | PASS |
| TC-11 | freeze гейтит даже без задач stage<done (BR-7) | `test_serial_gate_freeze::test_freeze_gates_even_without_unfinished_task` | PASS |
| TC-12 | ручное снятие freeze → следующая стартует | `test_serial_gate_freeze::test_manual_unfreeze_lets_next_start` | PASS |
| TC-13 | ветка B не создаётся пока gate закрыт (отсрочка среза) | `test_serial_gate_branch::test_branch_cut_deferred_when_gate_applies` | PASS |
| TC-14 | база B = origin/main с кодом A (merge-base ancestor) | `test_serial_gate_branch::test_deferred_branch_base_contains_predecessor` | PASS |
| TC-15 | kill-switch off → claim инертен, нулевая регрессия | `test_serial_gate::test_kill_switch_off_is_inert` | PASS |
| TC-16 | репо вне CSV → gate не применяется | `test_serial_gate::test_repo_outside_csv_not_gated` | PASS |
| TC-17 | ошибка БД в claim → fail-OPEN, не падает | `test_serial_gate::test_build_clause_error_fails_open` | PASS |
| TC-18 | ошибка freeze → fail-CLOSED | `test_serial_gate_freeze::test_is_repo_frozen_fails_closed` | PASS |
| TC-19 | snapshot() shape + never-raise | `test_serial_gate::test_snapshot_shape_and_never_raises` | PASS |
| TC-20 | GET /queue: блок serial_gate, существующие ключи не тронуты | `test_queue_endpoint::test_queue_has_serial_gate_block_and_keeps_existing_keys` + `::test_queue_serial_gate_reflects_freeze` | PASS |
| TC-21 | STAGE_TRANSITIONS / QG_CHECKS не изменены | `test_serial_gate::test_registries_unchanged` | PASS |
| TC-22 | миграция repo_freeze идемпотентна | `test_serial_gate_freeze::test_repo_freeze_migration_idempotent` | PASS |

Дополнительно покрыт kill-switch-путь среза ветки:
`test_serial_gate_branch::test_branch_cut_immediate_when_kill_switch_off` — PASS.

**Покрытие тест-плана: 22/22 TC выполнены, все PASS.**

### Сопоставление с критериями приёмки `03-acceptance-criteria.md`
| AC | Покрывающие TC | Результат |
|----|----------------|-----------|
| AC-1 (gate закрыт при активной) | TC-01 | PASS |
| AC-2 (автостарт по done) | TC-04, TC-05 | PASS |
| AC-3 (restart-safe) | TC-06, TC-07 | PASS |
| AC-4 (per-repo) | TC-08, TC-09 | PASS |
| AC-5 (rollback-freeze + алерт) | TC-10, TC-11, TC-12 | PASS |
| AC-6 (нет stale-base) | TC-13, TC-14 | PASS |
| AC-7 (kill-switch / нулевая регрессия) | TC-15, TC-16 | PASS |
| AC-8 (fail-open claim) | TC-17 | PASS |
| AC-9 (fail-closed freeze) | TC-18 | PASS |
| AC-10 (наблюдаемость /queue) | TC-19, TC-20 | PASS |
| AC-11 (инварианты неизменны) | TC-21, TC-22 | PASS |

## Smoke test API (prod 8500, read-only)
- `GET /health` → `{"status":"ok","service":"orchestrator"}`
- `GET /status` → 200, отдаёт активные задачи (валидный JSON)
- `GET /queue` → 200, валидный JSON; присутствуют блоки `reconcile`/`reaper`/
  `post_deploy`/`merge_verify`/`task_deps`/`recent`.

Примечание: блок `serial_gate` в ответе прод-`/queue` (8500) **отсутствует**, т.к. на
проде сейчас работает код до ORCH-088 (фича ещё не задеплоена — это и есть тестируемая
задача). Наличие и форма нового блока подтверждены интеграционным тестом TC-20 через
TestClient на коде ветки. Деструктивных операций на прод-контейнере не выполнялось.

## Вывод pytest (хвост)
```
======================= 1114 passed, 1 warning in 31.52s =======================
```
Профильные сюиты:
```
======================== 24 passed, 1 warning in 1.39s =========================
```

## Итог
**PASS** — полный регресс зелёный (1114 passed), все 22 TC тест-плана выполнены и PASS,
все 11 AC покрыты, smoke API OK. Задача готова к переходу на стадию `deploy-staging`.
