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

15 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-102 analysis analyst ready-for-review 2026-06-10 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.pyORCH_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 ТЗ (инварианты)