Files
orchestrator/docs/work-items/ORCH-101/03-acceptance-criteria.md
claude-bot 69aa6eacde
All checks were successful
CI / test (push) Successful in 1m9s
analyst(ET): auto-commit from analyst run_id=602
2026-06-10 20:02:14 +03:00

132 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
work_item: ORCH-101
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-10
model_used: claude-opus-4-8
---
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-101 — ORCH-10-common: расхардкод + секреты + smoke
Work Item: **ORCH-101** · Repo: **orchestrator** · Стадия: analysis
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам
репозитория. AC-1…AC-4 — дословно из бизнес-запроса (уточнены до проверяемости); AC-5…AC-8 —
детализация скоупа (секреты/инфра/анти-регресс/инварианты).
---
## AC-1 — Ноль хардкодов хоста/путей/портов в `src/**`
**Условие:** в коде `src/**` и `watchdog/**` (вне комментариев/докстрингов) нет хост-специфичных
литералов, обходящих конфиг; всё читается из env/конфига с дефолтами. Проверка — grep-тестом
(`tests/test_no_host_hardcodes.py`) и ревью по реестру `02-trz.md` §3.1.
- **PASS:**
- блокеры A1A4, A7 реестра закрыты: `grep -rn "git.mva154.duckdns.org\|/home/slin\|mva154.local" src/ watchdog/` не находит ни одного вхождения в исполняемом коде (докстринги/комментарии — допустимы);
- `src/plane_sync.py::notify_stage_change` строит ссылки Branch/PR из `settings.gitea_public_url` (fallback `gitea_url`) и `settings.gitea_owner`;
- env-словари акторов (`launcher` ×2, `self_deploy`, `post_deploy`) берут HOME и git-идентичность из `settings`;
- A5 (`_STAGING_PORT`) и A6 (`SELF_HOSTING_REPO`) либо конфигуризованы, либо явно обоснованы в ADR задачи как платформенные константы (решение архитектора зафиксировано);
- структурный тест `tests/test_no_host_hardcodes.py` существует, его allowlist пуст (или каждая запись обоснована комментарием), тест зелёный.
- **FAIL:** хотя бы один литерал `82.22.50.71` / `/home/slin` / `mva154` / `duckdns` в исполняемом коде `src/**`/`watchdog/**`; ИЛИ ссылка в Plane-комментарии всё ещё строится от захардкоженного `http://git.mva154.duckdns.org`; ИЛИ A5/A6 не конфигуризованы и не обоснованы в ADR; ИЛИ анти-регресс тест отсутствует/красный.
---
## AC-2 — Без регресса: на текущем хосте поведение 1:1
**Условие:** дефолты всех новых параметров равны текущим боевым значениям; pytest зелёный.
- **PASS:**
- каждый новый `Settings`-ключ / compose-переменная / `ARG` / shell-default имеет дефолт, равный значению, зашитому до задачи (`/home/slin`, `claude-bot@mva154.local`-адреса, gid 999, uid 1000, порты 8500/8501, пути node/claude-code и т.д.);
- `docker compose config` без заданных переменных окружения резолвится в эквивалент текущей конфигурации (volumes/user/group_add/environment/command совпадают по значениям);
- значения существующих дефолтов `src/config.py` (реестр §3.1 E) не изменены;
- полный `pytest tests/ -q` зелёный;
- `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи / схема БД — без изменений (диф не затрагивает их семантику).
- **FAIL:** хотя бы один дефолт отличается от текущего боевого значения; ИЛИ `docker compose config` при пустом окружении даёт иную эффективную конфигурацию; ИЛИ любой существующий тест красный; ИЛИ диф меняет машину стадий/реестр QG/схему БД.
---
## AC-3 — Smoke-процедура задокументирована и воспроизводима
**Условие:** существует документированная процедура «развёрнутый инстанс → тестовый проект +
задача → конвейер доехал» с явными PASS/FAIL-критериями; воспроизводимость подтверждена.
- **PASS:**
- в `docs/operations/` есть раздел/документ (предложение ТЗ: `REPLICATION.md`) с пошаговой smoke-процедурой: health-check инстанса → тестовый проект → тестовая задача → подтверждение продвижения конвейера (минимум: `analysis` отработала, артефакты `0104` созданы; расширенный режим — до `done`);
- каждый шаг имеет явный ожидаемый результат (PASS/FAIL), итог — однозначный вердикт;
- процедура не требует переноса данных/секретов с боевого хоста (stateless);
- воспроизводимость подтверждена хотя бы одним прогоном на текущей инфре (staging-песочница 8501 / sandbox-проект) — результат зафиксирован в артефактах задачи (например, `13-test-report.md` / `15-staging-log.md`);
- если введена скрипт-обвязка (`scripts/…`) — она запускается (`--help`/dry-run без ошибок) и покрыта тестом из `04-test-plan.yaml`.
- **FAIL:** процедуры нет; ИЛИ шаги без явных критериев («посмотреть, что всё ок»); ИЛИ процедура требует копирования боевых данных/секретов; ИЛИ заявленный прогон не зафиксирован; ИЛИ скрипт-обвязка падает на запуске.
---
## AC-4 — Доки (deployment-раздел) + CHANGELOG
**Условие:** документация обновлена в том же PR (правило агентов №2; reviewer проверяет — №6).
- **PASS:**
- deployment-раздел (см. AC-3) дополнительно содержит: карту всех новых env-переменных (имя, назначение, дефолт), процедуру/чек-лист секретов (см. AC-5), границы «10-common vs Lite vs Bundled»;
- карта переменных окружения в `docs/operations/INFRA.md` дополнена новыми ключами;
- `CHANGELOG.md` содержит запись ORCH-101;
- `CLAUDE.md`/`README.md` обновлены, если фактический объём изменений того требует (новые операторские способности/ограничения).
- **FAIL:** новый env-ключ отсутствует в карте env; ИЛИ нет записи в `CHANGELOG.md`; ИЛИ deployment-раздел не покрывает секреты/smoke; ИЛИ README выдаёт решённое за открытое (правило №6).
---
## AC-5 — Секреты: генерация новых, не копирование боевых
**Условие:** механизм выпуска нового комплекта секретов на новом хосте существует и безопасен.
- **PASS:**
- webhook-секреты (`ORCH_PLANE_WEBHOOK_SECRET`, `ORCH_GITEA_WEBHOOK_SECRET`) генерируются криптослучайно (≥ 32 байт энтропии; повторный запуск даёт другие значения);
- механизм никогда не перезаписывает существующий `.env` молча;
- чек-лист перечисляет все внешние токены (`ORCH_PLANE_API_TOKEN`, `ORCH_PLANE_BOT_*`, `ORCH_GITEA_TOKEN`, `ORCH_TELEGRAM_BOT_TOKEN`) с указанием, где их выпустить и куда вписать; явно сказано «боевые секреты не копируются»;
- `.env.example` покрывает 100% ключей, обязательных для старта (включая новые из AC-1/AC-2), секретные значения — только плейсхолдеры; реальные секреты в гит не попадают (`.gitleaks`/security-гейт зелёный);
- `.env.staging.example` согласован (если затронут).
- **FAIL:** секрет генерируется детерминированно/слабо; ИЛИ запуск механизма затирает существующий `.env`; ИЛИ в `.env.example` отсутствует обязательный ключ; ИЛИ в гит закоммичено реальное секретное значение; ИЛИ процедура предписывает копирование боевого секрета.
---
## AC-6 — Инфра-файлы параметризованы
**Условие:** `docker-compose.yml`, `Dockerfile`, `scripts/orchestrator-deploy-hook.sh` не требуют
правки под новый хост — только переменные.
- **PASS:**
- реестр §3.1 B/C/D закрыт: пути `/home/slin/...`, gid `999`, uid `1000:1000`, node/claude-code-пути, ssh-user, staging-порт в `command:`, `REPO=` в deploy-hook — параметризованы (`${VAR:-default}` / `ARG` / `"${REPO:-…}"`) с дефолтами = текущим значениям;
- связка «uid/gid/HOME/маунты `.claude`+`.ssh`/`useradd`» меняется согласованной группой переменных (инвариант ORCH-040 сохранён, `group_add` docker-gid не удалён);
- структурный тест параметризации (TC-06/TC-12 из `04-test-plan.yaml`) зелёный.
- **FAIL:** хотя бы одно значение реестра B/C/D осталось непараметризованным; ИЛИ группа ORCH-040 рассогласована (HOME ≠ маунт-таргеты при дефолтах); ИЛИ `group_add` удалён; ИЛИ структурный тест красный.
---
## AC-7 — Анти-регресс защита от возврата хардкодов
**Условие:** возврат хост-хардкода в `src/**` ломает CI.
- **PASS:** `tests/test_no_host_hardcodes.py` существует; сканирует `src/**`+`watchdog/**` на централизованный список запрещённых литералов (минимум: `82.22.50.71`, `/home/slin`, `mva154`, `duckdns`); исключает комментарии/докстринги/`tests/**`/`docs/**`; детерминирован (повторные прогоны стабильны); демонстрационно ловит подсадку литерала (негативная самопроверка в самом тесте или в тестах теста).
- **FAIL:** тест отсутствует; ИЛИ не ловит подсаженный в код литерал из списка; ИЛИ флапает; ИЛИ список литералов размазан по нескольким местам без единой точки правки.
---
## AC-8 — Self-hosting безопасность и инварианты соседних задач
**Условие:** задача не дестабилизирует общий прод и не ослабляет зафиксированные инварианты.
- **PASS:**
- в рамках задачи прод-контейнер `orchestrator` не перезапускается; прод-деплой — только штатно (staging 8501 → ручной `Confirm Deploy`);
- инвариант ORCH-058 сохранён: freshness/staging-путь не может быть переконфигурирован в прод-таргет (guard «staging-порт ≠ прод-порт» при конфигуризации A5 — либо A5 остался константой по ADR);
- INV-4 сохранён (никаких push/force-push в `main` мимо PR-merge API);
- маркеры `ORCH-NNN` в правленых блоках сохранены/обновлены корректно (правило №9).
- **FAIL:** диф содержит рестарт/останов прод-контейнера вне штатного деплой-пути; ИЛИ конфигурацией можно нацелить staging-rebuild на прод-порт; ИЛИ нарушен INV-4; ИЛИ правка помеченного блока стёрла инвариант соседнего ADR.
---
## Сводная матрица AC ↔ BR/FR
| AC | Покрывает |
|----|-----------|
| AC-1 | BR-1 / FR-1, FR-2, FR-6 |
| AC-2 | BR-5 / FR-1 (реестр E), FR-2, FR-3, NFR-6 |
| AC-3 | BR-4 / FR-5 |
| AC-4 | BR-7 / FR-7 |
| AC-5 | BR-3 / FR-4, NFR-3 |
| AC-6 | BR-2 / FR-3, NFR-4 |
| AC-7 | BR-6 / FR-6, NFR-5 |
| AC-8 | NFR-1, NFR-2, NFR-4 / FR-3 |