--- result: PASS # PASS | FAIL — машинный вердикт, UPPERCASE work_item: ORCH-057 stage: testing author_agent: tester status: pass created_at: 2026-06-10 model_used: claude-opus-4-8 type: test-report work_item_id: ORCH-057 --- # Test Report — ORCH-057 Нормализация legacy root-owned файлов при миграции на uid 1000 (детект + защита worktree). Review-вердикт `12-review.md` — **APPROVED**, P0/P1 findings нет. ## Окружение - Python: 3.12.13 - pytest: 8.3.3 (plugins: cov-5.0.0, anyio-4.13.0, asyncio-0.23.8) - Дата: 2026-06-10 - Worktree: `/repos/_wt/orchestrator/feature_ORCH-057-bug-follow-up-orch-040-normali` (ветка `feature/ORCH-057-bug-follow-up-orch-040-normali`, тесты прогнаны из рабочего дерева именно этой задачи, НЕ из общего `/repos/orchestrator`) ## Smoke API (read-only, прод-контейнер 8500 не тронут) | Эндпоинт | Результат | |----------|-----------| | `GET /health` | `{"status":"ok","service":"orchestrator"}` — OK | | `GET /status` | OK — задача ORCH-057 (id 83) видна на стадии `testing` | | `GET /queue` | OK — присутствуют блоки `serial_gate` (ORCH-088) ✓ и `auto_labels` (ORCH-089) ✓ | > Примечание: блок `fs_ownership` (ORCH-057) на прод-контейнере 8500 **отсутствует** — > это ожидаемо: ORCH-057 ещё не задеплоен, прод исполняет предыдущий образ. Read-only блок > `fs_ownership` присутствует и протестирован в коде ветки (TC-12, `test_api_queue.py` PASS). > Это НЕ регресс смока: обязательные блоки `serial_gate` + `auto_labels` на месте. ## Результаты ### Полный регресс `pytest tests/ -q` → **1507 passed, 1 warning in 52.22s** (warning — Pydantic V2 deprecation, предсуществующий, не относится к ORCH-057). Прод-контейнер не трогался. ### Профильные сюиты `pytest tests/test_git_worktree_perm.py tests/test_fs_normalize.py tests/test_fs_normalize_startup.py tests/test_api_queue.py -v` → **25 passed** — покрывают TC-01…TC-12. ### Сопоставление с тест-планом (04-test-plan.yaml) | TC ID | Описание | Тест-функция | Результат | |-------|----------|--------------|-----------| | TC-01 | `ensure_worktree` на git-fatal Permission denied → actionable RuntimeError | `test_git_worktree_perm::test_tc01_permission_git_fatal_becomes_actionable`, `test_tc01_makedirs_permission_error_becomes_actionable` | PASS | | TC-02 | не-прав-ошибка сохраняет прежний raw-контракт | `test_git_worktree_perm::test_tc02_non_permission_error_keeps_prior_contract`, `test_tc02_killswitch_off_keeps_raw_contract_even_for_permission` | PASS | | TC-03 | `scan_ownership` на дереве с uid≠target → mismatch=True + корни | `test_fs_normalize::test_tc03_scan_detects_mismatch` | PASS | | TC-04 | `scan_ownership` на чистом дереве → mismatch=False (идемпотентно) | `test_fs_normalize::test_tc04_clean_tree_no_mismatch` | PASS | | TC-05 | never-raise при недоступном/несуществующем корне → WARNING | `test_fs_normalize::test_tc05_never_raise_on_missing_root`, `test_tc05_never_raise_on_walk_error` | PASS | | TC-06 | `applies(repo)`: пустой CSV → self-hosting only; непустой — по списку | `test_fs_normalize::test_tc06_applies_empty_csv_self_hosting_only`, `test_tc06_applies_explicit_csv` | PASS | | TC-07 | kill-switch OFF → scan/normalize инертны (1:1 как до ORCH-057) | `test_fs_normalize::test_tc07_killswitch_off_scan_inert`, `test_tc07_killswitch_off_normalize_inert` | PASS | | TC-08 | `normalize` без прав → no-op + честный лог, НЕ исключение | `test_fs_normalize::test_tc08_normalize_without_rights_is_noop_not_error` | PASS | | TC-09 | TTL-кэш: повтор в окне TTL не пере-сканирует; ключ по roots+uid | `test_fs_normalize::test_tc09_ttl_cache_avoids_rescan`, `test_tc09_cache_keyed_by_roots_and_uid` | PASS | | TC-10 | startup-хук: mismatch → send_telegram + WARNING; ошибка детекта never-fatal | `test_fs_normalize_startup::test_tc10_startup_mismatch_warns_and_telegrams`, `test_tc10_startup_detect_error_never_fatal`, `test_tc10_startup_clean_no_telegram` | PASS | | TC-11 | гейт claim'а: mismatch без прав → внятный исход ДО launch, не сырой git-fatal | `test_fs_normalize_startup::test_tc11_launch_permission_failure_is_actionable_not_raw` | PASS | | TC-12 | `GET /queue` блок `fs_ownership` отдаёт поля и не 5xx-ит при выключенном флаге | `test_api_queue::test_tc12_queue_exposes_fs_ownership_block`, `test_tc12_queue_no_5xx_when_disabled`, `test_fs_normalize_check_endpoint` | PASS | Доп. целевые тесты (сверх плана, усиливают покрытие): `test_classify_worktree_error_markers`, `test_is_permission_failure_from_exc`, `test_snapshot_shape` — PASS. ### Сопоставление с критериями приёмки (03-acceptance-criteria.md) | AC | Покрыто | Результат | |----|---------|-----------| | AC-1 — конвейер стартует без ручного chown / внятная блокирующая ошибка | TC-01, TC-11 | PASS | | AC-2 — `ensure_worktree` actionable-ошибка при отказе доступа, не-прав сохраняет контракт | TC-01, TC-02 | PASS | | AC-3 — детект несоответствия владельца (mismatch на грязной, no-op на чистой) | TC-03, TC-04, TC-05 | PASS | | AC-4 — наблюдаемость детекта (WARNING + Telegram + `GET /queue`) | TC-10, TC-12 | PASS | | AC-5 — self-hosting безопасность, нулевая регрессия enduro, зелёный регресс | TC-06, TC-07, TC-08 + 1507 passed | PASS | | AC-6 — инварианты конвейера (STAGE_TRANSITIONS/QG_CHECKS/check_*/machine-key/схема БД) | полный регресс зелёный, guard-тесты пройдены | PASS | | AC-7 — документированная процедура нормализации (INFRA.md + ADR) | проверено reviewer (12-review.md), вне scope pytest | PASS (док.) | ## Вывод pytest ``` ============================= test session starts ============================== platform linux -- Python 3.12.13, pytest-8.3.3, pluggy-1.6.0 rootdir: /repos/_wt/orchestrator/feature_ORCH-057-bug-follow-up-orch-040-normali plugins: cov-5.0.0, anyio-4.13.0, asyncio-0.23.8 collected 25 items (профильные сюиты) ... 25 passed, 1 warning in 2.19s Полный регресс: 1507 passed, 1 warning in 52.22s ``` ## Итог **PASS** — все 12 TC выполнены и сопоставлены с тест-планом и критериями приёмки; профильные сюиты 25 passed; полный регресс 1507 passed; smoke (`/health`, `/status`, `/queue` c блоками `serial_gate` + `auto_labels`) — зелёный. Задача переходит на `deploy-staging`.