---
result: PASS   # PASS | FAIL — машинный вердикт, UPPERCASE
work_item: ORCH-112
stage: testing
author_agent: tester
status: pass
created_at: 2026-06-15
model_used: claude-opus-4-8
type: test-report
work_item_id: ORCH-112
---

# Test Report — ORCH-112

Гигиена shared deploy-базы: устойчивость self-deploy `git pull` к грязному дереву
(багфикс инцидента ORCH-111). Review-вердикт: **APPROVED** (`12-review.md`).

## Окружение
- 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-112-bug-failed-cancelled-task-arti/`
- Ветка: `feature/ORCH-112-bug-failed-cancelled-task-arti`
- Дата: 2026-06-15

## Smoke API (read-only)
| Endpoint | Результат |
|----------|-----------|
| `GET /health` | PASS — `{"status":"ok","service":"orchestrator"}` |
| `GET /status` | PASS — задача 102 ORCH-112 на стадии `testing`, ветка совпадает |
| `GET /queue` | PASS — блок `serial_gate` присутствует (ORCH-088); `auto_labels` присутствует |

Блок `checkout_hygiene`/`serial_gate`/`auto_labels` — все на месте в полезной нагрузке `/queue`,
регресса смока нет.

## Покрытие ТЗ (TC из 04-test-plan.yaml ↔ 03-acceptance-criteria)

| TC ID | Описание | AC | Тест | Результат |
|-------|----------|----|------|-----------|
| TC-01 | Регресс ORCH-111: грязный tracked `src/config.py` + untracked → база сходится к чистому `origin/main`, pull не падает (red→green) | AC-1 | `test_tc01_dirty_tracked_edit_converges_and_deploys` (+ `test_tc01b_bare_pull_aborts_without_hygiene_documents_incident`) | PASS |
| TC-02 | Untracked WIP-файлы не блокируют и не протекают в деплой | AC-2 | `test_tc02_untracked_wip_does_not_block` | PASS |
| TC-03 | Сохранность `.deploy-prev-image-*`/`deploy-hook.log`/sibling `.deploy-state-*`/`.merge-lease-*.json`/`.git/worktrees/*` (NFR-2) | AC-3 | `test_tc03_preserves_rollback_and_sibling_artifacts` | PASS |
| TC-04 | Happy-path: чистая база → fast-forward, exit-коды байт-в-байт | AC-4 | `test_tc04_clean_base_fast_forwards_no_op_hygiene` | PASS |
| TC-05 | Self-hosting safety: нет операций над `main`/force-push/рестарта прода; `git clean -fd` (никогда `-x`); leaf чист | AC-5 | `test_tc05_hook_clean_is_never_destructive`, `test_tc05_leaf_is_a_pure_leaf` | PASS |
| TC-06 | Kill-switch off → инертно; пустой CSV → self-hosting only; скоуп репо | AC-6 | `test_tc06_kill_switch_off_is_inert`, `test_tc06_empty_csv_is_self_hosting_only`, `test_tc06_csv_scope_limits_repos` | PASS |
| TC-07 | Сходимость после cancel/failed → следующий self-deploy чист | AC-7 | `test_tc07_convergence_then_next_deploy_is_clean` | PASS |
| TC-08 | Наблюдаемость: `read_report`/`alert_dirty`, Telegram best-effort/never-raise | AC-8 | `test_tc08_read_report_none_when_absent`, `test_tc08_read_report_parses_dirty_sentinel`, `test_tc08_alert_dirty_never_raises_on_send_failure` | PASS |
| TC-09 | Инвариант конвейера: `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/exit-code-контракт хука не тронуты | AC-9 | `test_tc09_pipeline_contracts_untouched`, `test_tc09_hook_exit_code_contract_intact` | PASS |
| TC-10 | Документация-инвариант: INFRA.md и architecture/README.md содержат правило «main checkout — deploy-база, не workspace» | AC-10 | `test_tc10_docs_state_deploy_base_invariant` | PASS |

Каждый TC из `04-test-plan.yaml` выполнен и сопоставлен с критерием приёмки `03-acceptance-criteria.md`.
TC-01 (обязательный red→green регресс инцидента ORCH-111) — зелёный; парный TC-01b документирует
аборт голого pull без гигиены.

## Вывод pytest

### Целевой модуль `tests/test_deploy_checkout_hygiene.py`
```
collected 17 items
... 17 passed, 1 warning in 7.51s
```

### Полный регресс `pytest tests/ -q`
```
2018 passed, 1 warning in 342.01s (0:05:42)
```
(единственный warning — Pydantic V2 deprecation в `src/config.py:8`, существующий, не связан с задачей)

## Итог
PASS — все 10 TC (17 тест-функций) зелёные, полный регресс 2018/2018 зелёный, smoke API OK
(`/health`, `/status`, `/queue` с блоками `serial_gate` и `auto_labels`). Задача готова к переходу
на `deploy-staging`.
