---
work_item: ORCH-057
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-10
model_used: claude-opus-4-8
---

# 03 — Критерии приёмки (Acceptance Criteria): ORCH-057 — нормализация legacy root-owned файлов

Work Item: **ORCH-057** · Repo: **orchestrator** · Стадия: analysis

Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам репозитория.

---

## AC-1 — Конвейер стартует без ручного chown (или внятная блокирующая ошибка)

**Условие:** после миграции контейнера на новый uid первый job не падает сырым git-фаталом на launch.
- **PASS:** при нормализованных правах worktree создаётся и агент стартует; при НЕнормализованных
  правах конвейер выдаёт понятную блокирующую ошибку с диагнозом и лечащей командой (НЕ сырой
  `fatal: could not create leading directories … Permission denied`).
- **FAIL:** на launch всплывает сырой git-fatal/Permission denied без диагноза причины и инструкции.

---

## AC-2 — `ensure_worktree` даёт actionable-ошибку при отказе доступа

**Условие:** `src/git_worktree.py::ensure_worktree` классифицирует ошибки прав.
- **PASS:** при `Permission denied`/`could not create leading directories`/`insufficient permission`
  поднимается `RuntimeError`, текст которого называет причину (legacy root-файлы в `/repos/_wt`/`.git`
  после миграции uid) и указывает команду/ссылку на процедуру; ошибки, не связанные с правами,
  сохраняют прежний контракт.
- **FAIL:** сырой git stderr пробрасывается без диагноза; либо подменяется смысл не-прав-ошибок;
  либо `ensure_worktree` падает необработанно.

---

## AC-3 — Детект несоответствия владельца

**Условие:** новый леаф `src/fs_normalize.py` обнаруживает файлы с `uid != target_uid` в корнях
(`/repos/_wt`, `<repo>/.git/objects`, `<repo>/.git/worktrees`, `data/runs`).
- **PASS:** на среде с root-файлами `scan_ownership` возвращает mismatch=True + затронутые корни;
  на чистой (`1000:1000`) среде — mismatch=False (no-op, идемпотентно); леаф never-raise.
- **FAIL:** mismatch не обнаружен на грязной среде / ложный mismatch на чистой / леаф бросает наружу.

---

## AC-4 — Наблюдаемость детекта

**Условие:** результат детекта виден оператору без падения задачи.
- **PASS:** при mismatch — структурный лог-WARNING (число/корни/лечащая команда) и Telegram (если
  включён); опц. read-only отражение в `GET /queue`.
- **FAIL:** mismatch обнаружен, но никак не сообщён; оператор узнаёт о проблеме только по упавшей задаче.

---

## AC-5 — Self-hosting безопасность и нулевая регрессия enduro-trails

**Условие:** изменение безопасно для общего инстанса.
- **PASS:** код не рестартит/не роняет прод, не трогает `main`/force-push/прод-образ; chown — только
  при наличии прав; при выключенном kill-switch поведение 1:1 как до ORCH-057; при пустом scope-CSV
  feature активен только для self-hosting (enduro-trails не затронут); регресс `pytest tests/ -q` зелёный.
- **FAIL:** любой рестарт/деградация прода из кода задачи; ненулевая регрессия enduro-trails;
  поведение меняется при выключенном флаге; падение всего регресса.

---

## AC-6 — Инварианты конвейера сохранены

**Условие:** изменение аддитивно.
- **PASS:** `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`, machine-verdict-ключи и схема БД —
  байт-в-байт прежние; новые флаги аддитивны и обратимы.
- **FAIL:** затронут любой exit/под-гейт, изменён machine-key, добавлена миграция схемы.

---

## AC-7 — Документированная процедура нормализации

**Условие:** процедура воспроизводима.
- **PASS:** `INFRA.md` содержит раздел «Миграция uid: обязательная нормализация legacy root-файлов»
  с точными командами (`_wt`, оба `.git`, `data/runs`) как обязательный шаг миграции; ADR ORCH-057
  фиксирует решение и ссылается на процедуру.
- **FAIL:** процедура отсутствует/абстрактна (как было в ORCH-040) либо не покрывает все корни.

---

## Сводная матрица AC ↔ FR/BR
| AC | Покрывает |
|----|-----------|
| AC-1 | BR-1 / FR-1, FR-3 |
| AC-2 | BR-1, BR-5 / FR-1 |
| AC-3 | BR-2 / FR-2 |
| AC-4 | BR-4 / FR-3 |
| AC-5 | NFR-1, NFR-2, NFR-5 / FR-4 |
| AC-6 | NFR-5 (инварианты) |
| AC-7 | BR-3 / FR-5 |
