182 lines
15 KiB
Markdown
182 lines
15 KiB
Markdown
---
|
||
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` отработала, артефакты `01–04` в ветке);
|
||
- итог процедуры — однозначный вердикт (все шаги 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 ТЗ (инварианты) |
|