165 lines
13 KiB
Markdown
165 lines
13 KiB
Markdown
---
|
||
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 не стартует; артефакты `01–04` не появляются;
|
||
орк не может писать в 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) |
|