Files
orchestrator/docs/work-items/ORCH-102/03-acceptance-criteria.md

182 lines
15 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-102
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-10
model_used: claude-opus-4-8
---
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-102 — ORCH-10a Lite-тираж
Work Item: **ORCH-102** · Repo: **orchestrator** · Стадия: analysis
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам
репозитория. AC-1…AC-5 — дословно из бизнес-запроса (уточнены до проверяемости);
AC-6…AC-7 — детализация скоупа (анти-дрейф / инварианты).
---
## AC-1 — `docs/deployment/LITE_SETUP.md`: полная пошаговая, без доп-вопросов
**Условие:** инструкция существует и покрывает сквозной маршрут Lite-тиража; каждый шаг —
команда/проверка; человек, не видевший платформу, разворачивает по ней без доп-вопросов.
- **PASS:**
- файл `docs/deployment/LITE_SETUP.md` существует (путь — по исходу А-3; отклонение от пути
бизнес-запроса зафиксировано в ADR задачи);
- покрыты ВСЕ разделы нормативного перечня ТЗ §FR-1: рамка Lite/границы; предусловия хоста
(зависимости, uid/gid: `ORCH_RUN_UID/GID`, `ORCH_DOCKER_GID` через `getent group docker`,
владение `ORCH_HOST_REPOS_DIR`); перенос кода (чекаут `orchestrator`, без данных);
конфигурация (`.env` с нуля от `.env.example` + `gen_secrets.py`, обязательные ключи нового
хоста включая `ORCH_PROJECTS_JSON`); Plane (workspace/проект, точная модель статусов с
fail-closed `Confirm Deploy`/`STOP`, API-токен, webhook+HMAC `X-Plane-Signature` + каверза
Plane CE); Gitea (репо, токен со scope, per-repo webhook `X-Gitea-Signature`, один глобальный
секрет, норматив защиты `main` по исходу А-1); LLM (claude CLI: дистрибутив/node/аутентификация/
`ORCH_CLAUDE_BIN`/модели ORCH-41); Telegram (бот трекера + отдельный watchdog-бот +
получение chat-id); запуск compose + health-чек (`/health`, `/queue`, `/metrics`);
регистрация проекта (`onboard_project.py``ORCH_PROJECTS_JSON` → управляемый рестарт);
smoke; stateless-проверка; траблшутинг (≥ 5 типовых отказов: симптом → диагностика → лечение);
- **каждый** нормативный шаг несёт исполняемую команду (fenced code block) И явную проверку
результата (маркер «Проверка:» / PASS-FAIL / ожидаемый вывод);
- копируемые команды generic: хост-специфика только плейсхолдерами `<...>`/`$ENV_VAR`;
боевых литералов (`mva154`, `duckdns`, `82.22.50.71`, реальные токены) в код-блоках нет;
- «без доп-вопросов» подтверждено операционально: приёмочный smoke-прогон по инструкции
выполнен на чистом контуре и зафиксирован (см. AC-4) + траблшутинг покрывает типовые отказы.
- **FAIL:** файла нет; ИЛИ отсутствует любой нормативный раздел FR-1; ИЛИ есть шаг без
команды/проверки («настройте webhook» без как-проверить); ИЛИ в копируемых командах боевые
URL/пути/секреты; ИЛИ инструкция отсылает за обязательным шагом во внешний (вне репо) источник.
---
## AC-2 — Compose-подмножество: только орк+watchdog
**Условие:** Lite разворачивает ровно `orchestrator`+`orchestrator-watchdog`; Plane/Gitea-контейнеров
нет; свойство зафиксировано и защищено.
- **PASS:**
- `docker compose config --services` (без активных профилей, пустой env) →
ровно `orchestrator` и `orchestrator-watchdog`;
- `orchestrator-staging` присутствует в файле строго за `profiles: [staging]` (дефолтный
`up -d` его не поднимает);
- в `docker-compose.yml` нет сервисов/образов Plane/Gitea (ни `plane*`, ни `gitea*`);
- LITE_SETUP.md документирует это свойство (что поднимется после `up -d` и почему staging
опционален — исход А-5);
- структурный тест compose-подмножества (TC-04) существует и зелёный;
- если по исходу А-2 введён отдельный lite-compose — он покрыт тем же тестом, а existing
`docker-compose.yml` не форкается без обоснования в ADR.
- **FAIL:** дефолтный запуск поднимает что-то кроме орк+watchdog; ИЛИ staging вне профиля;
ИЛИ в compose появился Plane/Gitea-сервис; ИЛИ свойство не задокументировано; ИЛИ тест
отсутствует/красный.
---
## AC-3 — Stateless: чистая БД, ни одной нашей задачи/секрета
**Условие:** инструкция предписывает чистый старт и не допускает переноса наших данных/секретов;
сама дока секретов не содержит.
- **PASS:**
- LITE_SETUP.md нормативно фиксирует: БД создаётся пустой при первом старте (`data/` чист,
переносить нечего); `.env`/`.env.staging`/`.env.watchdog` собираются с нуля; явная строка
«данные/задачи/секреты боевого хоста НЕ переносятся» (зеркало REPLICATION.md §5);
- секреты — только выпуск НОВЫХ: `gen_secrets.py` (webhook) + чек-лист внешних токенов
(ссылка на REPLICATION.md §3); ни один шаг не предписывает копирование боевого секрета;
- инструкция содержит проверку чистоты развёрнутого инстанса: первый `GET /queue` — нулевые
счётчики jobs, ни одной задачи (`ORCH-*`/`ET-*`) в системе;
- в самом доке и тестах задачи нет реальных секретоподобных значений (только плейсхолдеры);
security-гейт (ORCH-022, `17-security-report.md`) — `PASS`.
- **FAIL:** любой шаг предписывает/допускает перенос БД/задач/боевого `.env`/секрета; ИЛИ нет
нормативной stateless-строки; ИЛИ нет проверки чистоты; ИЛИ в доке обнаружен реальный
секрет/боевой токен; ИЛИ security-гейт `FAIL`.
---
## AC-4 — Smoke на чистом окружении проходит
**Условие:** smoke существует как воспроизводимая процедура/чек-лист и подтверждён прогоном.
- **PASS:**
- LITE_SETUP.md несёт smoke-раздел: чек-лист с явным PASS/FAIL на каждый шаг, построенный на
REPLICATION.md §4 (ссылка, без форка процедуры): конфиг резолвится → `/health`
`/queue`+`/metrics` → тестовый проект (`onboard_project.py plan/apply/verify`) → тестовая
задача → «конвейер доехал» (минимум: `analysis` отработала, артефакты `0104` в ветке);
- итог процедуры — однозначный вердикт (все шаги PASS ⇒ тираж PASS);
- приёмочный прогон выполнен на чистом контуре — минимум staging-песочница
(`ORCH_STAGING_PORT`, изолированная БД `./data/staging`) + одноразовый sandbox-проект
(прецедент ORCH-101 AC-3 / ONBOARDING.md §5.2) — и зафиксирован в артефактах задачи
(`13-test-report.md` и/или `15-staging-log.md`: дата, контур, шаги, вердикт);
- процедура нигде не требует боевых данных/секретов (stateless, согласовано с AC-3).
- **FAIL:** smoke-раздела нет; ИЛИ шаги без явных PASS/FAIL («посмотреть, что всё ок»); ИЛИ
процедура форкает REPLICATION.md §4 с расхождениями; ИЛИ заявленный прогон не зафиксирован в
артефактах; ИЛИ прогон провален и не разобран.
---
## AC-5 — pytest зелёный; CHANGELOG; перекрёстные доки
**Условие:** регресс чист, документация согласована (правила агентов №2/№6).
- **PASS:**
- полный `pytest tests/ -q` зелёный (включая новые структурные тесты задачи и существующие
`test_no_host_hardcodes` / `test_replication_smoke` / `test_infra_parametrization` /
`test_onboarding_*` — не ослаблены и не правлены под задачу без согласования);
- `CHANGELOG.md` содержит запись ORCH-102;
- `docs/operations/REPLICATION.md` §1: строка «Type A — Lite» обновлена (статус ✅/ссылка на
LITE_SETUP.md) — границы 10-common vs Lite vs Bundled остаются честными;
- `README.md`/`CLAUDE.md` обновлены, если фактический объём того требует (новая операторская
способность — Lite-тираж; README не выдаёт нерешённое за решённое и наоборот).
- **FAIL:** любой тест красный; ИЛИ нет записи в CHANGELOG; ИЛИ REPLICATION.md §1 продолжает
числить Lite «отдельной задачей» без ссылки; ИЛИ обзорные доки противоречат факту.
---
## AC-6 — Канон не форкается; анти-дрейф защита
**Условие:** инструкция — маршрутизатор поверх golden source'ов, её полнота защищена тестом.
- **PASS:**
- канонические данные (22 статуса, карта env, формат вебхуков, онбординг, smoke) даны ссылкой
на golden source (`ONBOARDING.md` §1 / `REPLICATION.md` §2§4 / `SETUP_WEBHOOKS.md`); при
дублировании таблицы — анти-дрейф тест сверяет дубль с источником истины (импорт из
`src/plane_sync.py` / парсинг `.env.example`), не строковой копией;
- `tests/test_lite_setup_doc.py` существует и проверяет минимум: наличие дока; обязательные
кирпичи (ТЗ FR-6.1); согласованность упомянутых env-ключей с `.env.example` (FR-6.2);
compose-подмножество (FR-6.3); stateless-норматив и отсутствие боевых литералов/секретов в
код-блоках (FR-6.4); перекрёстность REPLICATION→LITE_SETUP и запись CHANGELOG (FR-6.5);
- тест детерминирован (повторные прогоны стабильны, без сети/LLM).
- **FAIL:** таблица статусов/env скопирована без анти-дрейф сверки; ИЛИ тест отсутствует/не
ловит исчезновение обязательного раздела/кирпича; ИЛИ упомянутый в доке env-ключ отсутствует
в `.env.example`; ИЛИ тест флапает/ходит в сеть.
---
## AC-7 — Self-hosting безопасность и неизменность конвейера
**Условие:** задача не дестабилизирует общий прод и не меняет рантайм.
- **PASS:**
- дифф задачи — `docs/**`, `tests/**`, `CHANGELOG.md` (+ согласованные обзорные доки,
+ `.env.watchdog.example` при исходе А-4); `src/**` не изменён — либо каждое отклонение
обосновано в ADR задачи;
- `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи / схема БД —
без изменений;
- прод-контейнер `orchestrator` в рамках задачи не перезапускается; выкат — только штатным
конвейером (deploy-staging 8501 → ручной Confirm Deploy);
- инструкция не противоречит инвариантам платформы: ADR D10 ORCH-009 (без branch protection),
C-1 ORCH-100 (watchdog-бот ≠ бот орка), ORCH-040 (uid/gid/HOME группа), ORCH-058
(staging-порт ≠ прод-порт), INV-4 (мерж только через PR-merge API), конвенции тиража
REPLICATION.md §1 (репо `orchestrator`, имена сервисов).
- **FAIL:** немотивированные правки `src/**`/compose/Dockerfile; ИЛИ дифф трогает машину
стадий/QG/вердикты/схему БД; ИЛИ рестарт прода вне штатного деплой-пути; ИЛИ шаг инструкции
предписывает запрещённое инвариантами (включить branch protection, переиспользовать токен орка
для watchdog, скопировать боевой секрет и т.п.).
---
## Сводная матрица AC ↔ BR/FR
| AC | Покрывает |
|----|-----------|
| AC-1 | BR-1, BR-2 / FR-1, FR-4, NFR-6 |
| AC-2 | BR-3 / FR-2 |
| AC-3 | BR-4 / FR-3, NFR-3 |
| AC-4 | BR-5 / FR-5 |
| AC-5 | BR-7 / FR-7, NFR-2 |
| AC-6 | BR-6, BR-8 / FR-6, NFR-4, NFR-5 |
| AC-7 | NFR-1, NFR-2 / §7 ТЗ (инварианты) |