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

165 lines
13 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-103
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-11
model_used: claude-opus-4-8
---
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-103 — Bundled-тираж: весь стек одним комплектом + bootstrap-скрипт
Work Item: **ORCH-103** · Repo: **orchestrator** · Стадия: analysis
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
(что считается провалом). AC-1…AC-5 — из постановки Владельца (сохранены 1:1 по смыслу);
AC-6…AC-9 — производные обязательные. AC-1/AC-2/AC-3 в части e2e — **ручная приёмка** на
чистом тестовом хосте/VM по BUNDLED_SETUP.md (в CI docker/LLM не гоняются); остальное
проверяется по файлам репозитория и структурным тестам.
---
## AC-1 — Единый bundle поднимает ВЕСЬ стек; bootstrap доводит одной командой/визардом
**Условие:** на чистом Linux-хосте с docker+compose по шагам BUNDLED_SETUP.md: одна команда
`docker compose -f <bundle-compose> … up -d` поднимает все сервисы стека (орк + watchdog +
Gitea + Plane-стек); затем ОДИН запуск bootstrap-скрипта доводит инсталляцию до рабочего
состояния (init Gitea/Plane → онбординг sandbox-проекта → git-доступ агентов → конфиг орка →
health). Интерактивные manual-step чекпоинты допустимы только там, где Plane CE API не
позволяет автоматизацию, каждый — с инструкцией и проверкой результата.
- **PASS:** все контейнеры bundle в состоянии Up/healthy; bootstrap завершается `exit 0`;
`GET /health` орка — 200/ok, `GET /queue` и `GET /metrics` отдают валидный JSON;
`onboard_project.py verify` зелёный (22 статуса, лейблы, репо, webhook); ни одного
НЕдокументированного ручного действия (правка compose/конфигов руками сверх инструкции).
- **FAIL:** хотя бы один сервис не поднялся/в рестарт-цикле; bootstrap падает или завершается
с нерабочим конвейером; для доводки потребовались действия, отсутствующие в BUNDLED_SETUP.md;
manual-step пропускается молча без проверки результата.
---
## AC-2 — После bootstrap smoke проходит (тестовый проект + задача доезжает)
**Условие:** smoke-процедура BUNDLED_SETUP §smoke (шаги REPLICATION.md §4 поверх
bundle-инсталляции): создать issue в sandbox-проекте Plane → перевести в «To Analyse».
- **PASS:** webhook доезжает (job появляется в `GET /queue`); конвейер запускает analyst;
в рабочей ветке Gitea появляются артефакты `01-brd.md`/`02-trz.md`/`03-acceptance-criteria.md`/
`04-test-plan.yaml` (минимальный сигнал — шаг 5 REPLICATION §4); обратное направление
работает (орк пишет статус/коммент в Plane). Опционально-расширенно: задача доводится до
`done` (шаг 6).
- **FAIL:** webhook не доходит (нет job); analyst не стартует; артефакты `0104` не появляются;
орк не может писать в Plane/Gitea API (одностороння связность — R-4).
---
## AC-3 — Stateless: чистые Plane/Gitea/БД, новые секреты
**Условие:** инсталляция стартует с нуля и не содержит ничего нашего.
- **PASS:** все тома bundle созданы заново при первом `up` (чистые БД Plane/Gitea/орка:
`GET /queue` — нулевые счётчики, в Plane/Gitea нет наших задач/репо/пользователей); ВСЕ
секреты инсталляции сгенерированы на месте (`gen_secrets.py` + bundle-креды bootstrap);
в репо нет ни одного реального секрета/дефолтного пароля (структурный тест: секрет-эвристика
+ плейсхолдеры в bundle-конфиг-каноне); боевые данные/секреты/БД не копируются ни одним шагом
инструкции.
- **FAIL:** инструкция/скрипт предлагает перенос наших данных или переиспользование боевых
секретов; в репо обнаружен реальный секрет/дефолтный пароль/высокоэнтропийный литерал;
на свежей инсталляции видны чужие задачи/счётчики.
---
## AC-4 — BUNDLED_SETUP.md + требования к хосту задокументированы
**Условие:** `docs/deployment/BUNDLED_SETUP.md` существует и написан по канону тиражных доков
(ORCH-102).
- **PASS:** док несёт обязательные разделы FR-4 (рамка, **требования к хосту с явными цифрами
RAM/диск/CPU и картой портов**, предусловия, секреты, запуск, bootstrap с перечнем
manual-step, LLM, Telegram, онбординг, smoke, stateless-проверка, остановка/сброс,
траблшутинг); каждый исполняемый шаг = fenced-команда + «Проверка:» PASS/FAIL; явно указано
«Plane ≈ 14 контейнеров — ресурсоёмко»; цифры требований подтверждены замером на тестовом
развёртывании (не «с потолка»); хост-специфика — только плейсхолдеры; общие шаги — ссылками
на LITE_SETUP/ONBOARDING/REPLICATION (без копипасты канона).
- **FAIL:** дока нет/раздел «Требования к хосту» отсутствует или без цифр; шаги без
команд/проверок; FORBIDDEN-литералы (IP/`/home/slin`/`mva154`/`duckdns`) или секреты в
тексте/fenced-блоках; канон LITE_SETUP скопирован вместо ссылок.
---
## AC-5 — pytest зелёный; CHANGELOG
**Условие:** полный регресс и журнал изменений.
- **PASS:** `pytest tests/ -q` — 0 failed (включая существующие анти-дрейф
`test_lite_setup_doc.py`, `test_no_host_hardcodes.py`, канон-тесты ORCH-009 — без правки их
ассертов); `CHANGELOG.md` содержит запись `ORCH-103`.
- **FAIL:** хотя бы один тест красный; существующий анти-дрейф тест «починен» ослаблением
ассертов; CHANGELOG не обновлён.
---
## AC-6 — Корневой compose и рантайм не тронуты
**Условие:** изоляция от боевого контура (NFR-1/NFR-2, BR-1/BR-8).
- **PASS:** `git diff main` НЕ содержит изменений `src/**`, корневого `docker-compose.yml`,
`Dockerfile`, `.gitea/workflows/**`; bundle-compose — отдельный файл; множество сервисов
корневого compose неизменно (`orchestrator`/`orchestrator-watchdog`/`orchestrator-staging`);
ни один артефакт задачи не исполняется в нашем контуре автоматически (нет правок
деплой-хука/CI, нет cron/врезок).
- **FAIL:** любая правка рантайма/корневого compose/Dockerfile; сервисы `plane*`/`gitea*`
добавлены в корневой compose; артефакт bundle задействован в нашем прод/staging-контуре.
---
## AC-7 — Нулевой дрейф канонов: кирпичи переиспользованы
**Условие:** BR-6 — единственный источник истины для статусов/лейблов/секретов/smoke.
- **PASS:** bootstrap вызывает `scripts/gen_secrets.py` (webhook-секреты) и
`scripts/onboard_project.py` (статусы/лейблы/репо/вебхуки) — структурный тест подтверждает
ссылки; собственного списка статусов/лейблов в bundle-артефактах нет (упоминание числа
статусов в доке сверяется импортом `plane_sync._PLANE_NAME_TO_KEY` в тесте, не литералом);
smoke-раздел ссылается на REPLICATION §4.
- **FAIL:** bootstrap/док несут собственную копию канона (свой список статусов, свой генератор
webhook-секретов, свой smoke-чеклист с нуля) — дрейф при будущих изменениях канона.
---
## AC-8 — Идемпотентность и fail-safe bootstrap
**Условие:** BR-7 — повторный запуск и грязный хост.
- **PASS:** повторный запуск bootstrap на уже-инициализированном bundle завершается успешно
(ensure/skip, без дублей и без разрушения состояния); preflight на грязном/непригодном хосте
(существующие тома bundle, занятый порт, нехватка RAM/диска) → явный отказ с понятной
подсказкой ДО любых мутаций; delete-операций нет (teardown — только отдельный
явный режим/процедура, не часть обычного прогона); exit-коды: 0 — успех, 2 — manual-step/
предусловие, 1 — ошибка; секреты в логи не печатаются; повторный запуск не перетирает
существующие секреты без явного флага.
- **FAIL:** повторный запуск ломает/дублирует состояние; bootstrap молча переиспользует чужие
тома или продолжает после провального preflight; обычный прогон удаляет данные; секрет виден
в stdout/логе.
---
## AC-9 — Секрет-гигиена и переносимость новых артефактов
**Условие:** NFR-3/NFR-4/NFR-6 по файлам репо.
- **PASS:** структурные тесты подтверждают: в bundle-compose/доке/скрипте нет
FORBIDDEN-литералов (список — импорт из `test_no_host_hardcodes.py`) и высокоэнтропийных
литералов (hex ≥32 / alnum ≥40); все сторонние образы bundle-compose пиннованы (не `latest`);
все env-ключи, упомянутые в BUNDLED_SETUP.md, существуют в канонах (`.env.example`
bundle-конфиг-канон); сгенерированные на хосте конфиги — в `.gitignore`.
- **FAIL:** найден хост-литерал/секрет; образ без пина; ключ-фантом в доке (нет в канонах);
сгенерированный конфиг коммитится.
---
## Сводная матрица AC ↔ BR/FR
| AC | Покрывает | Способ проверки |
|----|-----------|-----------------|
| AC-1 | BR-1, BR-2 / FR-1, FR-2 | ручной e2e на тестовом хосте + структурные тесты (TC-01..04, TC-08) |
| AC-2 | BR-3 / FR-2, FR-6 | ручной e2e (smoke REPLICATION §4) |
| AC-3 | BR-4 / FR-3 | ручной e2e + структурные тесты (TC-06, TC-09) |
| AC-4 | BR-5 / FR-4 | структурный тест дока (TC-05) + ревью |
| AC-5 | BR-9 / FR-5, FR-6 | `pytest tests/ -q` (TC-12) + CHANGELOG (TC-11) |
| AC-6 | BR-1, BR-8 / NFR-1, NFR-2 | git diff + существующий анти-дрейф (TC-02) |
| AC-7 | BR-6 / FR-2, FR-3 | структурный тест bootstrap/дока (TC-07, TC-10) |
| AC-8 | BR-7 / FR-2 | unit-тесты чистых функций preflight/плана (TC-08) + ручной повторный прогон |
| AC-9 | NFR-3, NFR-4, NFR-6 / FR-1, FR-4 | структурные тесты гигиены (TC-03, TC-06, TC-09) |