analyst(ET): auto-commit from analyst run_id=608
This commit is contained in:
211
docs/work-items/ORCH-102/01-brd.md
Normal file
211
docs/work-items/ORCH-102/01-brd.md
Normal file
@@ -0,0 +1,211 @@
|
||||
---
|
||||
work_item: ORCH-102
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-10
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 01 — BRD: ORCH-102 — ORCH-10a Lite-тираж: перенос орк+watchdog + полная инструкция донастройки окружения
|
||||
|
||||
Work Item: **ORCH-102** · Repo: **orchestrator** (self-hosting) · Стадия: analysis
|
||||
Заказчик: Слава · Эпик: **ORCH-10** (домен D5 «Масштаб», `docs/epics/self-evolution.md`) · Тип: **A — Lite**
|
||||
|
||||
---
|
||||
|
||||
## 1. Бизнес-контекст и проблема
|
||||
|
||||
### 1.1. Цель эпика ORCH-10
|
||||
Тираж платформы — РАЗДАЧА текущей функциональности нескольким заказчикам **на тест**.
|
||||
Решения Владельца 10.06 (приняты как требования, см. §1.4): ДВА типа тиража, ОБА **stateless**
|
||||
(наши задачи/данные/секреты НЕ переносим — чистый старт):
|
||||
|
||||
- **Тип A (Lite)** — переносим ТОЛЬКО орк+watchdog на новую инфру; окружение
|
||||
(Plane / Gitea / LLM / Telegram) заказчик донастраивает сам **по чёткой инструкции**.
|
||||
- **Тип B (Bundled)** — весь стек одним комплектом (отдельная задача эпика, вне ORCH-102).
|
||||
|
||||
### 1.2. Проблема, которую закрывает ORCH-102
|
||||
Фундамент **10-common (ORCH-101) уже в `main`**: все хост-значения параметризованы env
|
||||
(`docker compose config` без переменных = боевое поведение 1:1), секреты выпускаются заново
|
||||
(`scripts/gen_secrets.py`), есть smoke-процедура с PASS/FAIL (`docs/operations/REPLICATION.md` §4)
|
||||
и анти-регресс `tests/test_no_host_hardcodes.py`. **Технически** платформа разворачивается на
|
||||
чужом хосте без правки кода.
|
||||
|
||||
**Операционно** — нет: знания размазаны по 4+ документам, каждый из которых писался для
|
||||
оператора НАШЕГО хоста, а не для заказчика на чистой инфре:
|
||||
|
||||
| Документ | Что покрывает | Чего не хватает для Lite |
|
||||
|----------|---------------|--------------------------|
|
||||
| `docs/operations/REPLICATION.md` | карта env, секреты, smoke | явно НЕ описывает установку/подключение Plane/Gitea (анти-скоуп Р-5 ORCH-101) |
|
||||
| `docs/operations/ONBOARDING.md` | онбординг проекта (статусы/лейблы/репо/kit/реестр) | предполагает уже работающий оркестратор и наш хост |
|
||||
| `docs/operations/SETUP_WEBHOOKS.md` | формат вебхуков Plane/Gitea | примеры с боевыми URL (`mva154`), не generic |
|
||||
| `docs/operations/INFRA.md` | топология/рестарты нашего хоста | не инструкция «с нуля» |
|
||||
|
||||
Заказчик сегодня **не может развернуть Lite без доп-вопросов** — отсутствует единый сквозной
|
||||
маршрут «голый хост → работающий конвейер». Главный продукт ORCH-102 — **ИНСТРУКЦИЯ**
|
||||
`docs/deployment/LITE_SETUP.md` (golden source в репо), закрывающая этот разрыв.
|
||||
|
||||
### 1.3. Установленные факты (проверено по репо, не изобретать)
|
||||
- **ORCH-101 смержен** (`git log`: merge #122) — ветка задачи уже содержит фундамент: env-карта
|
||||
§2 REPLICATION.md, `gen_secrets.py`, `.env.example` = канон 100% ключей старта (включая блок
|
||||
`WATCHDOG_*`), smoke §4, тесты `test_no_host_hardcodes/test_infra_parametrization/test_secrets_gen/test_replication_smoke`.
|
||||
- **`docker-compose.yml` УЖЕ является compose-подмножеством Lite:** ровно три сервиса —
|
||||
`orchestrator`, `orchestrator-watchdog`, `orchestrator-staging` (последний строго за
|
||||
`profiles: [staging]`); сервисов Plane/Gitea в compose НЕТ. Дефолтный `docker compose up -d`
|
||||
поднимает ровно орк+watchdog. AC-2 достижим без форка compose — нужны фиксация в доке и
|
||||
анти-дрейф тест.
|
||||
- **Plane CE не отдаёт webhook через публичный API** — на нашем хосте webhook создан напрямую в
|
||||
PostgreSQL / через UI (`SETUP_WEBHOOKS.md`). Инструкция Lite обязана дать заказчику оба пути
|
||||
(UI и DB) для ЕГО инсталляции Plane.
|
||||
- **Точная модель статусов**: 22 канонических имени с группами (источник —
|
||||
`plane_sync._PLANE_NAME_TO_KEY`; таблица — `ONBOARDING.md` §1; создаёт
|
||||
`scripts/onboard_project.py apply`). Код-критичные fail-closed: `Confirm Deploy`, `STOP`
|
||||
(группа `cancelled`); в терминальных группах — только Done/Cancelled/STOP.
|
||||
- **Branch protection на `main` нормативно ЗАПРЕЩЁН** (ORCH-009 ADR D10: required-approvals /
|
||||
status-checks ломают PR-merge API merge-актора → ложные HOLD). **Pre-receive хуков в платформе
|
||||
НЕТ** — защита держится конвенцией + скоупом токенов. Формулировка бизнес-запроса
|
||||
«pre-receive хуки» конфликтует с этим нормативом → вопрос архитектору (ТЗ §3.8 А-1);
|
||||
рекомендация: раздел Gitea фиксирует канон (репо+токен+webhook+«protection НЕ включать»).
|
||||
- **Гэп watchdog-конфига:** compose читает `.env.watchdog` (`required: false`), но
|
||||
`.env.watchdog.example` в репо НЕТ (есть только `.env.example`/`.env.staging.example`);
|
||||
ключи `WATCHDOG_*` задокументированы внутри `.env.example`. Инструкции нужен однозначный
|
||||
рецепт настройки watchdog-бота (форма — вопрос архитектору А-4).
|
||||
- **Платформенные конвенции тиража** (REPLICATION.md §1, нормативно): репо платформы обязан
|
||||
называться `orchestrator` (`SELF_HOSTING_REPO`); имена сервисов/профиля — константы;
|
||||
контейнерный layout (`/app/data`, `/repos`, `/opt/claude-code`) не параметризуется.
|
||||
- **Прецедент приёмки smoke**: ORCH-101 AC-3 — воспроизводимость подтверждается прогоном на
|
||||
текущей инфре (staging-песочница `ORCH_STAGING_PORT`=8501 + sandbox-проект), без нового железа.
|
||||
|
||||
### 1.4. Решения Владельца (10.06) — приняты как требования
|
||||
| # | Решение |
|
||||
|---|---------|
|
||||
| D-1 | Тиражей ДВА типа: A (Lite) и B (Bundled); ORCH-102 реализует ТОЛЬКО A. |
|
||||
| D-2 | Оба типа **stateless**: наши задачи/данные/секреты не переносятся; на целевой инфре чистый старт. |
|
||||
| D-3 | Lite = перенос ТОЛЬКО орк+watchdog; окружение (Plane/Gitea/LLM/Telegram) заказчик донастраивает по инструкции. |
|
||||
| D-4 | Главный продукт задачи = **инструкция** `docs/deployment/LITE_SETUP.md` — golden source в репо. |
|
||||
| D-5 | Зависимость: ORCH-102 ← **10-common (ORCH-101)** — выполнена (смержен), блокеров нет. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Объём (scope)
|
||||
|
||||
### 2.1. В объёме
|
||||
- **Инструкция `docs/deployment/LITE_SETUP.md`** — полная пошаговая (каждый шаг = команда +
|
||||
проверка), покрывающая сквозной маршрут: предусловия хоста (зависимости, uid/gid) → перенос
|
||||
кода орк+watchdog → конфиг (`.env` с нуля + секреты) → подключение Plane (workspace/проект,
|
||||
точная модель статусов, API-токен, webhook+HMAC) → подключение Gitea (репо, токен, webhook,
|
||||
норматив защиты `main`) → LLM-доступ (claude CLI / ключи моделей) → Telegram (бот трекера +
|
||||
watchdog-бот + chat-id) → запуск compose-подмножества → регистрация проекта
|
||||
(`ORCH_PROJECTS_JSON`, `src/projects.py`) → health-чек → smoke (из 10-common) → траблшутинг.
|
||||
- **Фиксация compose-подмножества** (AC-2): документировано и защищено структурным тестом, что
|
||||
дефолтный запуск = ровно орк+watchdog, без Plane/Gitea-контейнеров.
|
||||
- **Stateless-нормативы** в инструкции (AC-3): чистая БД, новые секреты, явный запрет переноса
|
||||
наших задач/данных/секретов.
|
||||
- **Smoke на чистом окружении** (AC-4): воспроизводимая процедура/чек-лист (переиспользование
|
||||
REPLICATION.md §4) + зафиксированный приёмочный прогон.
|
||||
- **Анти-дрейф тесты** структуры/полноты инструкции и compose-подмножества; полный pytest
|
||||
зелёный; `CHANGELOG.md`; перекрёстные ссылки (REPLICATION.md §1 границы, README — по объёму).
|
||||
|
||||
### 2.2. Вне объёма (явно, не делать)
|
||||
- **Тип B (Bundled)** — весь стек одним комплектом: отдельная задача эпика.
|
||||
- **Установка самих Plane / Gitea / Telegram / LLM-аккаунтов** — заказчик ставит по официальной
|
||||
документации вендоров; ORCH-102 покрывает только ПОДКЛЮЧЕНИЕ к оркестратору (анти-скоуп-крип,
|
||||
зеркало Р-5 ORCH-101).
|
||||
- **Изменения рантайма/конвейера**: ожидаемый объём — docs+tests; `src/**` не трогается;
|
||||
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи / схема БД — байт-в-байт.
|
||||
- **Перенос данных**: ни БД, ни задач, ни worktree, ни секретов (D-2).
|
||||
- **Новая автоматизация** поверх существующих CLI (`gen_secrets.py`, `onboard_project.py`):
|
||||
новые скрипты не вводятся без решения архитектора.
|
||||
- **Коммерческая механика раздачи** (доступ заказчика к коду, лицензии, поддержка) —
|
||||
операторский/владельческий уровень; в инструкции — параметризованный источник кода.
|
||||
- **Введение pre-receive хуков / branch protection** — запрещено действующим нормативом
|
||||
ORCH-009 ADR D10 (см. §1.3); пересмотр только явным ADR архитектора.
|
||||
|
||||
---
|
||||
|
||||
## 3. Заинтересованные стороны
|
||||
- **Владелец (Слава)** — раздаёт платформу заказчикам на тест; принимает инструкцию как продукт.
|
||||
- **Заказчик-тестер (новый оператор)** — целевой читатель LITE_SETUP.md: разворачивает Lite на
|
||||
своей инфре без доп-вопросов; технически грамотен (linux/docker), платформу видит впервые.
|
||||
- **Оператор текущего прода** — прогоняет приёмочный smoke на staging-песочнице; его прод
|
||||
(общий для enduro-trails) не должен быть затронут.
|
||||
- **Будущая задача 10b (Bundled)** — переиспользует разделы Lite-инструкции; границы фиксируются
|
||||
в REPLICATION.md §1.
|
||||
|
||||
---
|
||||
|
||||
## 4. Бизнес-требования (BR)
|
||||
|
||||
| ID | Требование | Связь |
|
||||
|----|------------|-------|
|
||||
| BR-1 | Существует `docs/deployment/LITE_SETUP.md` — **полная пошаговая** инструкция Lite-тиража: по ней человек, не видевший платформу, разворачивает орк+watchdog и донастраивает окружение **без доп-вопросов**; **каждый шаг несёт команду и проверку** (ожидаемый результат / PASS-FAIL). | AC-1, FR-1, D-4 |
|
||||
| BR-2 | Инструкция покрывает ВСЕ системы донастройки: Plane (workspace/проект, точная модель статусов — 22 имени с группами, API-токен, webhook+HMAC с учётом ограничения Plane CE), Gitea (репо, токен с нужными scope, per-repo webhook, норматив «branch protection `main` НЕ включать»), LLM (claude CLI: дистрибутив/node/аутентификация/`ORCH_CLAUDE_BIN`/модели), Telegram (бот трекера + ОТДЕЛЬНЫЙ watchdog-бот + получение chat-id), регистрацию проекта (`ORCH_PROJECTS_JSON` через `onboard_project.py`), health-чек, smoke. | AC-1, FR-4 |
|
||||
| BR-3 | Разворачивается **compose-подмножество только орк+watchdog**: дефолтный `docker compose up -d` поднимает ровно `orchestrator`+`orchestrator-watchdog`; Plane/Gitea-контейнеров в compose нет; staging-сервис — строго за профилем. Свойство зафиксировано в доке и защищено структурным тестом. | AC-2, FR-2 |
|
||||
| BR-4 | **Stateless**: инструкция предписывает чистую БД (создаётся пустой при первом старте), выпуск НОВОГО комплекта секретов (`gen_secrets.py` + чек-лист внешних токенов), и нигде не предписывает перенос наших задач/данных/секретов; в самой доке — только плейсхолдеры, ни одного реального секрета/боевого токена. | AC-3, FR-3 |
|
||||
| BR-5 | **Smoke на чистом окружении** существует как воспроизводимая процедура/чек-лист с PASS/FAIL (переиспользование REPLICATION.md §4, без форка); приёмочный прогон выполнен на чистом контуре (минимум — staging-песочница + sandbox-проект, прецедент ORCH-101 AC-3) и зафиксирован в артефактах задачи. | AC-4, FR-5 |
|
||||
| BR-6 | **Канон не форкается**: канонические таблицы (модель статусов, карта env, формат вебхуков) инструкция даёт ссылкой на golden source (`ONBOARDING.md`/`REPLICATION.md`/`SETUP_WEBHOOKS.md`) либо с анти-дрейф тестом при неизбежном дублировании; копируемые команды инструкции — generic (плейсхолдеры вместо боевых URL/путей). | AC-1/AC-6, FR-4, NFR-4 |
|
||||
| BR-7 | Полный `pytest tests/ -q` зелёный; запись в `CHANGELOG.md`; перекрёстные доки обновлены (REPLICATION.md §1 «границы» — строка Type A → ссылка/статус; README/CLAUDE.md — по фактическому объёму, правило агентов №2/№6). | AC-5, FR-6/FR-7 |
|
||||
| BR-8 | Полнота/структура инструкции защищена **структурным pytest** (анти-дрейф, по образцу `tests/test_replication_smoke.py`): исчезновение обязательного раздела/кирпича/env-ключа из дока или дрейф compose-подмножества ломает CI. | AC-6, FR-6 |
|
||||
|
||||
---
|
||||
|
||||
## 5. Нефункциональные требования (NFR)
|
||||
|
||||
| ID | Требование |
|
||||
|----|------------|
|
||||
| NFR-1 | **Self-hosting безопасность:** задача docs+tests; прод-контейнер `orchestrator` не перезапускается; прод-выкат — только штатным конвейером (staging 8501 → ручной Confirm Deploy). |
|
||||
| NFR-2 | **Нулевая регрессия:** поведение рантайма не меняется (ожидаемо ноль изменений `src/**`); `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/схема БД — байт-в-байт; существующие тесты (включая `test_no_host_hardcodes`, `test_replication_smoke`) остаются зелёными. |
|
||||
| NFR-3 | **Секрет-гигиена:** ни в инструкции, ни в тестах — ни одного реального секрета/токена/боевого webhook-секрета; только плейсхолдеры и ссылки на `gen_secrets.py`; security-гейт (ORCH-022) зелёный. |
|
||||
| NFR-4 | **Единый источник истины:** инструкция — маршрутизатор поверх канонов, не их копия; неизбежные дубли защищены анти-дрейф тестом (сверка с кодом/каноном импортом, не строкой). |
|
||||
| NFR-5 | **Поддерживаемость golden source:** LITE_SETUP.md версионируется в репо и поддерживается агентами при каждой доработке, меняющей шаги тиража (правило агентов №2 — дока в том же PR). |
|
||||
| NFR-6 | **Копируемость команд:** каждый код-блок инструкции выполняется на чистом хосте дословно после подстановки явно перечисленных плейсхолдеров (`<...>`); никаких неявных «подразумевается, что…». |
|
||||
|
||||
---
|
||||
|
||||
## 6. Допущения и ограничения
|
||||
- **Поддерживаемый контур** (фиксируется в предусловиях инструкции): Linux x86_64, Docker Engine +
|
||||
Compose v2, git, python3; пользователь с правами docker; диск/память по минимальным требованиям
|
||||
(значения уточнит архитектор/инструкция). Иные ОС/архитектуры — вне гарантии Lite.
|
||||
- **Заказчик сам ставит** Plane CE, Gitea, заводит Telegram-ботов и LLM-доступ (Claude
|
||||
CLI-аутентификация / ключи) — по официальным докам вендоров; наша инструкция начинается с
|
||||
«системы установлены и доступны по сети».
|
||||
- **Имя репо платформы — `orchestrator`** (норматив REPLICATION.md §1 / `SELF_HOSTING_REPO`);
|
||||
инструкция не предлагает его менять.
|
||||
- **Источник кода** для заказчика (clone-URL/архив) — решение Владельца; в инструкции —
|
||||
параметризованный шаг (А-6 в ТЗ).
|
||||
- «Без доп-вопросов» (AC-1) операционализируется проверяемо: (а) каждый шаг несёт
|
||||
команду+проверку, (б) приёмочный smoke-прогон по инструкции на чистом контуре зафиксирован,
|
||||
(в) траблшутинг покрывает типовые отказы первичной настройки.
|
||||
- Терминология бизнес-запроса «pre-receive хуки» трактуется по факту платформы (§1.3):
|
||||
канонический механизм защиты — конвенция + скоуп токенов + запрет branch protection;
|
||||
окончательная формулировка раздела Gitea — за архитектором (А-1).
|
||||
|
||||
---
|
||||
|
||||
## 7. Критерии успеха (резюме; детали — 03-acceptance-criteria.md)
|
||||
- AC-1: `docs/deployment/LITE_SETUP.md` — полная пошаговая, человек разворачивает без
|
||||
доп-вопросов (каждый шаг — команда/проверка).
|
||||
- AC-2: compose-подмножество только орк+watchdog (без Plane/Gitea-контейнеров).
|
||||
- AC-3: stateless — чистая БД, ни одной нашей задачи/секрета.
|
||||
- AC-4: smoke на чистом окружении проходит (минимум — воспроизводимая процедура/чек-лист).
|
||||
- AC-5: pytest зелёный; CHANGELOG.
|
||||
- AC-6 (детализация): анти-дрейф тесты структуры дока/compose; канон не форкается.
|
||||
- AC-7 (детализация): self-hosting безопасность, инварианты конвейера не тронуты.
|
||||
|
||||
---
|
||||
|
||||
## 8. Риски (детали — 10-tech-risks.md, заполняет архитектор)
|
||||
- R-1 — **Дрейф инструкции**: платформа развивается, шаги устаревают → структурные тесты (BR-8)
|
||||
+ правило golden source (NFR-5).
|
||||
- R-2 — **Форк канона**: скопированная таблица статусов/env разъедется с кодом → ссылки/анти-дрейф
|
||||
(BR-6, NFR-4).
|
||||
- R-3 — **Непроверяемость «без доп-вопросов»** → операционализация через §6 (команда+проверка,
|
||||
smoke-прогон, траблшутинг).
|
||||
- R-4 — **Гетерогенность хостов заказчиков** (rootless docker, иной uid, нет node) → явный
|
||||
поддерживаемый контур + предусловия с проверками (`getent group docker`, владение
|
||||
`ORCH_HOST_REPOS_DIR`).
|
||||
- R-5 — **Конфликт «pre-receive» с нормативом ADR D10** → вопрос А-1 архитектору; до решения —
|
||||
канон платформы.
|
||||
- R-6 — **Утечка секрета через примеры дока** → NFR-3, security-гейт, тест на отсутствие
|
||||
секретоподобных значений.
|
||||
270
docs/work-items/ORCH-102/02-trz.md
Normal file
270
docs/work-items/ORCH-102/02-trz.md
Normal file
@@ -0,0 +1,270 @@
|
||||
---
|
||||
work_item: ORCH-102
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-10
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 02 — ТЗ (TRZ): ORCH-102 — ORCH-10a Lite-тираж: перенос орк+watchdog + полная инструкция донастройки окружения
|
||||
|
||||
Work Item: **ORCH-102** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
> ТЗ описывает **что** должно измениться и **где** (документы/контракты/тесты), выведено из BRD и
|
||||
> фактического кода (аудит выполнен по репо на ветке задачи; ORCH-101 уже в `main`). **Как**
|
||||
> (точная разбивка разделов дока, форма анти-дрейф тестов, исходы вопросов §3.8) — решает
|
||||
> архитектор в `06-adr/`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Сводка изменения
|
||||
|
||||
**Docs-first задача** (паттерн ORCH-077/092: документы + тесты, рантайм не трогается).
|
||||
Создаётся главный продукт — инструкция `docs/deployment/LITE_SETUP.md` (golden source Lite-тиража,
|
||||
новый раздел `docs/deployment/`), которая собирает существующие кирпичи 10-common
|
||||
(REPLICATION/ONBOARDING/SETUP_WEBHOOKS/INFRA, `gen_secrets.py`, `onboard_project.py`, smoke §4)
|
||||
в один сквозной маршрут «голый хост → работающий конвейер» для заказчика. Дополнительно:
|
||||
структурные анти-дрейф тесты (полнота дока, compose-подмножество, stateless/секрет-гигиена),
|
||||
перекрёстные ссылки и CHANGELOG.
|
||||
|
||||
Ожидаемый дифф: `docs/**`, `tests/**`, `CHANGELOG.md` (+ опционально `.env.watchdog.example` —
|
||||
исход А-4). **`src/**` — ноль изменений**; конвейер
|
||||
(`STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/схема БД) — байт-в-байт.
|
||||
|
||||
---
|
||||
|
||||
## 2. Задействованные модули / пути
|
||||
|
||||
| Путь | Действие |
|
||||
|------|----------|
|
||||
| `docs/deployment/LITE_SETUP.md` | **создать** — главный продукт (полная пошаговая инструкция Lite; новый каталог `docs/deployment/`) |
|
||||
| `docs/operations/REPLICATION.md` | изменить: §1 таблица границ — строка «Type A — Lite» → статус ✅ ORCH-102 + ссылка на LITE_SETUP.md |
|
||||
| `tests/test_lite_setup_doc.py` | **создать** — структурные анти-дрейф проверки дока + compose-подмножества (образец: `tests/test_replication_smoke.py`) |
|
||||
| `.env.watchdog.example` | создать **по исходу А-4** (канон конфигурации sidecar-watchdog для нового хоста; сейчас примера нет, compose читает `.env.watchdog` `required: false`) |
|
||||
| `docs/operations/INFRA.md` | изменить при необходимости: перекрёстная ссылка на deployment-раздел (по фактическому объёму) |
|
||||
| `README.md` | изменить: обзорный док — способность Lite-тиража (правило агентов №6: не выдавать открытое за решённое и наоборот) |
|
||||
| `CLAUDE.md` | изменить: блок ORCH-102 в паспорте — по фактическому объёму (правило №2) |
|
||||
| `CHANGELOG.md` | изменить: запись ORCH-102 |
|
||||
| `src/**`, `docker-compose.yml`, `Dockerfile`, `scripts/**` | **НЕ менять** (читаются инструкцией/тестами как источник истины; любое отклонение — только через ADR архитектора) |
|
||||
|
||||
Кирпичи, которые инструкция **переиспользует по ссылке** (не форкает, BR-6/NFR-4):
|
||||
`docs/operations/REPLICATION.md` (карта env §2, секреты §3, smoke §4),
|
||||
`docs/operations/ONBOARDING.md` (статусы §1, слои Gitea/kit/реестр §2–5),
|
||||
`docs/operations/SETUP_WEBHOOKS.md` (формат вебхуков, Plane CE-каверза),
|
||||
`scripts/gen_secrets.py`, `scripts/onboard_project.py` (plan/apply/verify),
|
||||
`.env.example` (канон 100% ключей), `GET /health|/queue|/metrics`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Функциональные требования
|
||||
|
||||
### FR-1 — Документ `docs/deployment/LITE_SETUP.md`: состав и форма
|
||||
|
||||
Привязка: BR-1, BR-2. Нормативный перечень разделов (порядок = маршрут оператора; финальную
|
||||
разбивку/нумерацию решает архитектор, состав — обязательный минимум):
|
||||
|
||||
1. **Рамка Lite** — что разворачиваем (орк+watchdog), что заказчик ставит сам (Plane/Gitea/
|
||||
Telegram/LLM), границы vs 10-common vs Bundled (ссылка на REPLICATION.md §1), платформенные
|
||||
конвенции (репо `orchestrator`, имена сервисов, контейнерный layout — не менять).
|
||||
2. **Предусловия хоста** («зависимости, uid/gid» из бизнес-запроса): поддерживаемый контур
|
||||
(Linux x86_64, Docker Engine + Compose v2, git, python3); node + дистрибутив claude-code на
|
||||
хосте (`ORCH_HOST_NODE_BIN`, `ORCH_HOST_CLAUDE_CODE_DIR` — пути под маунты); пользователь и
|
||||
владение каталогами: `ORCH_RUN_UID/GID` = uid владельца `ORCH_HOST_REPOS_DIR` (инвариант
|
||||
ORCH-040), `ORCH_DOCKER_GID` — `getent group docker`; ssh-ключи деплой-хука
|
||||
(`ORCH_HOST_SSH_DIR`); свободные порты (`ORCH_DEPLOY_PROD_TARGET_PORT`=8500,
|
||||
`ORCH_STAGING_PORT`=8501). Каждое предусловие — команда проверки.
|
||||
3. **Перенос кода орк+watchdog**: получение чекаута репо `orchestrator` на хост в
|
||||
`ORCH_DEPLOY_HOST_REPO_PATH` (источник кода — параметризованный шаг, исход А-6); НИКАКИХ
|
||||
данных/БД/`.env` с боевого хоста (D-2). Watchdog отдельно не переносится — код в `watchdog/`
|
||||
того же репо, образ собирается локально compose'ом.
|
||||
4. **Конфигурация**: `.env` строится с нуля от `.env.example` (канон); webhook-секреты —
|
||||
`python3 scripts/gen_secrets.py [--write]`; карта переменных — ссылкой на REPLICATION.md §2;
|
||||
в доке явно — **обязательные ключи нового хоста**: `ORCH_PLANE_API_URL/WEB_URL/WORKSPACE_SLUG`,
|
||||
`ORCH_PLANE_API_TOKEN`, `ORCH_GITEA_URL/PUBLIC_URL/OWNER`, `ORCH_GITEA_TOKEN`, оба
|
||||
webhook-секрета, `ORCH_TELEGRAM_BOT_TOKEN/CHAT_ID`, `ORCH_PROJECTS_JSON` (обязателен:
|
||||
встроенный fallback несёт UUID исходного хоста), хост-параметры `ORCH_AGENT_HOME_DIR`/
|
||||
`ORCH_HOST_*`/`ORCH_RUN_*`/`ORCH_DOCKER_GID`, когерентность портов
|
||||
(`ORCH_DEPLOY_PROD_TARGET_PORT` ⇄ `WATCHDOG_METRICS_URL` ⇄ `ORCH_POST_DEPLOY_BASE_URL`).
|
||||
5. **Подключение Plane** (инсталляция заказчика): создать workspace/проект; **точная модель
|
||||
статусов** — 22 канонических имени с группами: создаёт `onboard_project.py apply`, таблица —
|
||||
ссылкой на ONBOARDING.md §1 (без форка; fail-closed `Confirm Deploy`/`STOP` упомянуть явно);
|
||||
выпуск API-токена (Workspace Settings → API tokens) + команда проверки; **webhook+HMAC**:
|
||||
URL `…/webhook/plane`, секрет из `gen_secrets.py`, заголовок `X-Plane-Signature`; каверза
|
||||
Plane CE «webhook не экспонирован в /api/v1» — оба пути (UI и прямой SQL, generic-вариант
|
||||
команд SETUP_WEBHOOKS.md с плейсхолдерами).
|
||||
6. **Подключение Gitea** (инсталляция заказчика): репо (`onboard_project.py` или вручную),
|
||||
токен (scope `repo`, `admin:repo_hook`) + проверка, per-repo webhook (events
|
||||
`push`/`pull_request`/`status`, `X-Gitea-Signature`, **ОДИН глобальный секрет на все репо**);
|
||||
норматив защиты `main` — по исходу А-1 (канон: branch protection НЕ включать, ORCH-009 ADR D10).
|
||||
7. **LLM-доступ (claude CLI)**: дистрибутив claude-code и node на хосте (пути = маунты compose),
|
||||
`ORCH_CLAUDE_BIN`; аутентификация CLI на хосте (каталог `ORCH_HOST_CLAUDE_DIR` +
|
||||
`ORCH_HOST_CLAUDE_JSON` — монтируются в контейнер; команда первичного логина/проверки —
|
||||
`claude --version` / минимальный вызов); конфигурация моделей — `ORCH_AGENT_MODEL_*` /
|
||||
`ORCH_AGENT_EFFORT_*` (резолв ORCH-41; дефолты канона — в `.env.example`).
|
||||
8. **Telegram**: бот трекера (BotFather `/newbot` → `ORCH_TELEGRAM_BOT_TOKEN`), получение
|
||||
`chat_id` (воспроизводимая команда, например через `getUpdates`), проверка `getMe`;
|
||||
**отдельный** watchdog-бот (`WATCHDOG_TG_BOT_TOKEN/CHAT_ID` — независимый канал, C-1
|
||||
ORCH-100, токен орка переиспользовать запрещено) — размещение ключей по исходу А-4
|
||||
(`.env.watchdog`).
|
||||
9. **Запуск compose-подмножества**: `docker compose config` (резолв без ошибок) →
|
||||
`docker compose up -d --build` → поднимаются ровно `orchestrator` + `orchestrator-watchdog`
|
||||
(AC-2); staging-профиль — опционально/когда нужен (исход А-5); health-чек:
|
||||
`GET /health` → 200 `"status":"ok"`, `GET /queue`/`GET /metrics` → штатный JSON
|
||||
(`schema_version: 1`).
|
||||
10. **Регистрация проекта заказчика**: `onboard_project.py plan → apply → verify`
|
||||
(Plane-проект+статусы+лейблы `autoApprove`/`autoDeploy`/`Bug`, Gitea-репо+webhook, kit,
|
||||
merged `ORCH_PROJECTS_JSON`) → внести строку в `.env` → управляемый рестарт → проверка
|
||||
`/health`+`/queue` (маршрут ONBOARDING.md, ссылкой; в Lite-доке — последовательность команд).
|
||||
11. **Smoke** (AC-4): чек-лист REPLICATION.md §4 (шаги 0–5, опционально 6 до `done`) —
|
||||
переиспользовать ссылкой + Lite-специфичные предусловия; критерий «конвейер доехал»:
|
||||
задача в БД → analyst-job в `/queue` → артефакты `01–04` в ветке задачи.
|
||||
12. **Stateless-проверка** (AC-3): первый старт создаёт пустую БД (`data/` чист); `GET /queue` —
|
||||
нулевые счётчики, ни одной задачи `ORCH-*`/`ET-*`; явная нормативная строка «данные/задачи/
|
||||
секреты боевого хоста НЕ переносятся».
|
||||
13. **Траблшутинг** первичной настройки: минимум — webhook 401/HMAC mismatch; «задача не
|
||||
появилась» (реестр/`ORCH_PROJECTS_JSON`/webhook); claude CLI не аутентифицирован/не найден;
|
||||
`docker.sock` permission denied (`ORCH_DOCKER_GID`); права `/repos` (uid mismatch,
|
||||
ORCH-040/057); Telegram молчит (токен/chat-id). Каждый пункт — симптом → команда
|
||||
диагностики → лечение.
|
||||
|
||||
**Форма (NFR-6, BR-1):** каждый шаг — исполняемая команда (fenced code block) + явная проверка
|
||||
(«Проверка:» / PASS-FAIL / ожидаемый вывод); все хост-специфичные значения в командах — только
|
||||
плейсхолдеры `<...>` или `$ENV_VAR` (боевые `mva154`/`82.22.50.71`/реальные токены — запрещены);
|
||||
язык — русский (канон доков платформы).
|
||||
|
||||
### FR-2 — Compose-подмножество (AC-2)
|
||||
|
||||
Привязка: BR-3. Зафиксировать (в доке + тестом), что Lite-развёртывание использует
|
||||
существующий `docker-compose.yml` БЕЗ форка:
|
||||
|
||||
- множество сервисов файла — ровно `{orchestrator, orchestrator-watchdog, orchestrator-staging}`;
|
||||
- `orchestrator-staging` строго за `profiles: [staging]` → дефолтный `docker compose up -d`
|
||||
поднимает ровно орк+watchdog;
|
||||
- сервисов/образов Plane/Gitea в compose НЕТ (и тест не даст появиться молча);
|
||||
- форма фиксации (существующий файл vs отдельный lite-вариант) — исход А-2; ТЗ-рекомендация:
|
||||
существующий файл (он уже является подмножеством — факт BRD §1.3), отдельный файл не плодить.
|
||||
|
||||
### FR-3 — Stateless-нормативы (AC-3)
|
||||
|
||||
Привязка: BR-4. Инструкция обязана: (а) предписывать чистый старт — пустой `data/` (БД создаётся
|
||||
`init_db()` при первом старте), `.env` только с нуля; (б) предписывать выпуск НОВЫХ секретов
|
||||
(`gen_secrets.py` + чек-лист REPLICATION.md §3.2) и нести норматив «боевые секреты/данные/задачи
|
||||
не копируются»; (в) содержать проверку чистоты (FR-1 п.12); (г) сама не содержать реальных
|
||||
секретов (NFR-3; проверяется тестом FR-6 и security-гейтом ORCH-022).
|
||||
|
||||
### FR-4 — Покрытие донастройки окружения без форка канона (AC-1)
|
||||
|
||||
Привязка: BR-2, BR-6. Per-system разделы FR-1 п.5–8 обязаны быть полными (заказчик не ходит за
|
||||
ответами вовне репо), при этом канонические данные даются ссылкой на golden source:
|
||||
|
||||
| Данные | Golden source | В LITE_SETUP.md |
|
||||
|--------|---------------|------------------|
|
||||
| 22 статуса + группы | `plane_sync._PLANE_NAME_TO_KEY` / ONBOARDING.md §1 | ссылка + критичные fail-closed имена (`Confirm Deploy`, `STOP`) |
|
||||
| Карта env / хост-параметры | REPLICATION.md §2 / `.env.example` | ссылка + список обязательных ключей нового хоста |
|
||||
| Формат вебхуков / Plane CE-каверза | SETUP_WEBHOOKS.md | ссылка + generic-команды с плейсхолдерами |
|
||||
| Онбординг проекта | ONBOARDING.md / `onboard_project.py` | ссылка + последовательность команд Lite-маршрута |
|
||||
| Smoke | REPLICATION.md §4 | ссылка + Lite-предусловия |
|
||||
|
||||
Если архитектор решит дублировать таблицу (читаемость) — дубль защищается анти-дрейф тестом
|
||||
(сверка импортом из `src/plane_sync.py` / парсингом `.env.example`), не строковой копией.
|
||||
|
||||
### FR-5 — Smoke на чистом окружении (AC-4)
|
||||
|
||||
Привязка: BR-5. Состав: (а) в LITE_SETUP.md — smoke-раздел (FR-1 п.11) как воспроизводимый
|
||||
чек-лист с PASS/FAIL на каждый шаг; (б) приёмочный прогон процедуры на чистом контуре — минимум
|
||||
staging-песочница (порт `ORCH_STAGING_PORT`, изолированная БД `./data/staging`) + одноразовый
|
||||
sandbox-проект (прецедент ORCH-101 AC-3 / ONBOARDING.md §5.2), без нового железа; (в) результат
|
||||
прогона фиксируется в артефактах задачи (`13-test-report.md` / `15-staging-log.md`); (г) прогон
|
||||
на реальном новом хосте — желателен, но НЕ требование приёмки (нет железа в контуре задачи).
|
||||
|
||||
### FR-6 — Анти-дрейф тесты (BR-8)
|
||||
|
||||
Привязка: BR-3, BR-6, BR-8. Новый `tests/test_lite_setup_doc.py` (структурный, без сети/LLM;
|
||||
образец — `tests/test_replication_smoke.py`):
|
||||
|
||||
1. док существует по канонному пути; несёт обязательные разделы/кирпичи FR-1 (минимум:
|
||||
`gen_secrets.py`, `onboard_project.py`, `docker compose`, `/health`, `/queue`, `/metrics`,
|
||||
`ORCH_PROJECTS_JSON`, webhook-секреты, `X-Plane-Signature`/`X-Gitea-Signature`,
|
||||
`getent group docker`, `Confirm Deploy`/`STOP`, Telegram-боты обоих каналов, маркеры
|
||||
PASS/FAIL/«Проверка»);
|
||||
2. каждый env-ключ `ORCH_*`/`WATCHDOG_*`, упомянутый в доке, существует в `.env.example`
|
||||
(анти-опечатка/анти-дрейф канона);
|
||||
3. compose-подмножество: парсинг `docker-compose.yml` — ровно 3 сервиса, staging за профилем,
|
||||
ни одного сервиса/образа `plane*`/`gitea*` (AC-2);
|
||||
4. stateless/секрет-гигиена: нормативная строка «не копиру…» присутствует; в доке нет
|
||||
секретоподобных значений (эвристика по образцу security-паттернов) и боевых литералов
|
||||
(`mva154`, `duckdns`, `82.22.50.71`) в копируемых код-блоках;
|
||||
5. перекрёстность: REPLICATION.md §1 ссылается на LITE_SETUP.md; `CHANGELOG.md` несёт ORCH-102.
|
||||
|
||||
Точная нарезка по тест-модулям — за developer (план — `04-test-plan.yaml`); существующие тесты
|
||||
не правятся (кроме согласованных структурных дополнений).
|
||||
|
||||
### FR-7 — Перекрёстная документация (BR-7)
|
||||
|
||||
Привязка: BR-7. REPLICATION.md §1 (строка Type A — Lite → ✅ + ссылка); README.md — способность
|
||||
Lite-тиража в обзоре (правило №6); CLAUDE.md — по фактическому объёму; CHANGELOG.md — запись.
|
||||
INFRA.md — ссылка на deployment-раздел при необходимости.
|
||||
|
||||
---
|
||||
|
||||
## 3.8. Вопросы архитектору (решаются в `06-adr/`, не в ТЗ)
|
||||
|
||||
- **А-1 — «pre-receive хуки» vs норматив ADR D10 (ORCH-009):** бизнес-запрос упоминает
|
||||
pre-receive хуки, но в платформе их нет, а branch protection на `main` нормативно запрещён
|
||||
(ломает PR-merge API merge-актора). Что фиксирует раздел Gitea? Рекомендация ТЗ: канон —
|
||||
репо+токен+webhook+явный норматив «branch protection НЕ включать»; pre-receive не вводить;
|
||||
отклонение — только отдельным ADR с анализом совместимости с merge-актором (ORCH-093/INV-4).
|
||||
- **А-2 — форма compose-подмножества:** существующий `docker-compose.yml` (уже = подмножество)
|
||||
+ документация/тест vs отдельный `docker-compose.lite.yml`. Рекомендация: существующий, без
|
||||
форка (нулевой дрейф, AC-2 держит тест).
|
||||
- **А-3 — размещение дока:** бизнес-запрос фиксирует `docs/deployment/LITE_SETUP.md` (новый
|
||||
раздел `docs/deployment/`); REPLICATION.md живёт в `docs/operations/`. Подтвердить layout
|
||||
(deployment как витрина тиража vs operations) и перекрёстные ссылки; отступление от пути
|
||||
бизнес-запроса — только явным решением.
|
||||
- **А-4 — канон watchdog-конфига нового хоста:** compose читает `.env.watchdog`
|
||||
(`required: false`), примера-файла нет; ключи `WATCHDOG_*` канонизированы в `.env.example`.
|
||||
Добавить `.env.watchdog.example` (симметрия с `.env.staging.example`) или документировать
|
||||
шаг «создай `.env.watchdog` с двумя ключами» в LITE_SETUP? Рекомендация: example-файл +
|
||||
упоминание в доке (меньше шансов перепутать файл-носитель).
|
||||
- **А-5 — staging-контур в Lite-инструкции:** обязателен ли запуск `orchestrator-staging` у
|
||||
заказчика? Рекомендация: опционален — нужен только если заказчик регистрирует проект
|
||||
`orchestrator` (self-hosting развитие платформы); для «раздачи на тест» базовый контур =
|
||||
prod-инстанс + watchdog; в доке — явная вилка.
|
||||
- **А-6 — источник кода для заказчика:** clone-URL (зеркало/доступ к нашему Gitea) vs архив.
|
||||
В доке — параметризованный шаг `git clone <ORCHESTRATOR_GIT_URL>`; конкретику источника
|
||||
фиксирует Владелец (вне репо).
|
||||
|
||||
---
|
||||
|
||||
## 4. Изменения API
|
||||
|
||||
Нет. Существующие `GET /health` / `/queue` / `/metrics` переиспользуются инструкцией read-only;
|
||||
новые эндпоинты не вводятся.
|
||||
|
||||
## 5. Изменения схемы БД
|
||||
|
||||
Нет.
|
||||
|
||||
## 6. Требования к новым/изменённым QG checks
|
||||
|
||||
Нет. `QG_CHECKS`/`check_*`/machine-verdict ключи не меняются. Новые структурные тесты (FR-6) —
|
||||
обычный pytest: попадают в существующие гейты (`check_ci_green`/`check_tests_passed`/merge-gate
|
||||
re-test/coverage-гейт ORCH-027) автоматически, без регистрации нового QG.
|
||||
|
||||
## 7. Совместимость / регресс
|
||||
|
||||
- **Нулевая регрессия (NFR-2):** дифф — docs+tests (+опц. `.env.watchdog.example`); рантайм не
|
||||
меняется; kill-switch не требуется (нечего выключать); полный `pytest tests/ -q` зелёный,
|
||||
существующие структурные тесты (`test_no_host_hardcodes`, `test_replication_smoke`,
|
||||
`test_infra_parametrization`, `test_onboarding_*`) не ослабляются.
|
||||
- **Обратимость:** удаление дока/тестов возвращает состояние 1:1 (никаких миграций/состояния).
|
||||
- **Self-hosting (NFR-1):** прод-контейнер не рестартится; выкат — штатный конвейер
|
||||
(deploy-staging 8501 → ручной Confirm Deploy). Для enduro-trails изменение инертно.
|
||||
- **Секрет-гигиена (NFR-3):** в доке/тестах только плейсхолдеры; security-гейт (ORCH-022,
|
||||
`17-security-report.md`) обязан остаться `PASS`.
|
||||
- **Инварианты соседних маркеров (правило №9):** ORCH-101 (дефолт = боевое значение; канон
|
||||
`.env.example`; конвенции тиража REPLICATION §1), ORCH-009 (ADR D10 — без branch protection;
|
||||
onboarding-CLI ничего не удаляет), ORCH-100 (независимый Telegram-канал watchdog, C-1),
|
||||
ORCH-040 (uid/gid/HOME группа), ORCH-058 (staging ≠ прод-порт), INV-4 (мерж только через
|
||||
PR-merge API) — инструкция обязана им следовать, а не противоречить.
|
||||
181
docs/work-items/ORCH-102/03-acceptance-criteria.md
Normal file
181
docs/work-items/ORCH-102/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,181 @@
|
||||
---
|
||||
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 ТЗ (инварианты) |
|
||||
146
docs/work-items/ORCH-102/04-test-plan.yaml
Normal file
146
docs/work-items/ORCH-102/04-test-plan.yaml
Normal file
@@ -0,0 +1,146 @@
|
||||
work_item: ORCH-102
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-10
|
||||
model_used: claude-opus-4-8
|
||||
title: "ORCH-10a Lite-тираж: инструкция LITE_SETUP + compose-подмножество — план тестов"
|
||||
framework: pytest
|
||||
scope: >
|
||||
Покрывается: существование и полнота docs/deployment/LITE_SETUP.md (нормативные
|
||||
разделы FR-1, форма «команда+проверка», generic-команды без боевых литералов),
|
||||
согласованность упомянутых env-ключей с каноном .env.example, структурная
|
||||
фиксация compose-подмножества (ровно орк+watchdog, staging за профилем, без
|
||||
Plane/Gitea-сервисов), stateless-нормативы и секрет-гигиена дока, перекрёстные
|
||||
ссылки (REPLICATION.md §1, CHANGELOG), воспроизводимый smoke-чек-лист и его
|
||||
приёмочный прогон на чистом контуре, полный регресс. Вне покрытия: реальный
|
||||
e2e-тираж на новом железе заказчика (заменён прогоном на staging-песочнице —
|
||||
прецедент ORCH-101 AC-3), установка Plane/Gitea как таковых, задача 10b
|
||||
(Bundled), перенос данных (stateless по решению 10.06).
|
||||
notes: >
|
||||
Задача docs-first: ожидаемый дифф — docs/** + tests/** + CHANGELOG.md
|
||||
(+ .env.watchdog.example при исходе А-4); src/** не меняется. Имя нового
|
||||
тест-модуля tests/test_lite_setup_doc.py — предложение analyst; developer может
|
||||
переименовать/разбить, сохранив покрытие TC (образец структурных док-тестов —
|
||||
tests/test_replication_smoke.py). Тесты детерминированы, без сети/LLM.
|
||||
Полный регресс tests/ обязан остаться зелёным; STAGE_TRANSITIONS/QG_CHECKS/
|
||||
check_*/machine-verdict не меняются — новые тесты входят в существующие гейты
|
||||
(check_ci_green / merge-gate re-test / coverage-гейт ORCH-027) автоматически.
|
||||
TC-09 — процедурная приёмка AC-4: прогон фиксируется tester'ом в
|
||||
13-test-report.md / 15-staging-log.md, а не автоматизируется в pytest.
|
||||
|
||||
tests:
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: >
|
||||
LITE_SETUP.md существует по канонному пути (docs/deployment/, исход А-3 —
|
||||
синхронизировать с ADR) и несёт ВСЕ нормативные разделы FR-1: рамка/границы
|
||||
Lite, предусловия хоста (зависимости, uid/gid, getent group docker), перенос
|
||||
кода, конфигурация (.env с нуля + gen_secrets.py + ORCH_PROJECTS_JSON),
|
||||
Plane (статусы/токен/webhook+HMAC), Gitea (репо/токен/webhook), LLM
|
||||
(claude CLI), Telegram (трекер + watchdog-бот + chat-id), запуск+health-чек,
|
||||
регистрация проекта, smoke, stateless-проверка, траблшутинг (AC-1 / FR-1).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: >
|
||||
Форма «каждый шаг — команда/проверка»: нормативные разделы содержат fenced
|
||||
code blocks с исполняемыми командами и явные маркеры проверки
|
||||
(PASS/FAIL/«Проверка:»); ключевые кирпичи присутствуют: docker compose,
|
||||
/health, /queue, /metrics, gen_secrets.py, onboard_project.py,
|
||||
X-Plane-Signature, X-Gitea-Signature (AC-1 / FR-1, NFR-6).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: >
|
||||
Согласованность env-канона: каждый ключ ORCH_*/WATCHDOG_*, упомянутый в
|
||||
LITE_SETUP.md, существует в .env.example; обязательный набор нового хоста
|
||||
упомянут явно (ORCH_PROJECTS_JSON, ORCH_PLANE_WEBHOOK_SECRET,
|
||||
ORCH_GITEA_WEBHOOK_SECRET, ORCH_PLANE_API_TOKEN, ORCH_GITEA_TOKEN,
|
||||
ORCH_TELEGRAM_BOT_TOKEN, ORCH_TELEGRAM_CHAT_ID, WATCHDOG_TG_BOT_TOKEN,
|
||||
WATCHDOG_TG_CHAT_ID) (AC-1, AC-6 / FR-1.4, FR-6.2).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: >
|
||||
Compose-подмножество (AC-2): docker-compose.yml парсится; множество сервисов
|
||||
ровно {orchestrator, orchestrator-watchdog, orchestrator-staging};
|
||||
orchestrator-staging строго за profiles: [staging] (дефолтный up -d поднимает
|
||||
ровно орк+watchdog); ни одного сервиса/образа plane*/gitea*; LITE_SETUP.md
|
||||
документирует состав дефолтного запуска (AC-2 / FR-2).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: >
|
||||
Stateless и секрет-гигиена (AC-3): док несёт нормативную строку «боевые
|
||||
данные/задачи/секреты не копируются» и предписывает чистую БД + выпуск
|
||||
новых секретов (gen_secrets.py); проверка чистоты инстанса (первый GET
|
||||
/queue без задач) описана; в копируемых код-блоках нет боевых литералов
|
||||
(mva154, duckdns, 82.22.50.71) и секретоподобных значений — только
|
||||
плейсхолдеры <...>/$ENV_VAR (AC-3 / FR-3, NFR-3).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: >
|
||||
Канон не форкается (AC-6): раздел Plane-статусов ссылается на golden source
|
||||
(ONBOARDING.md §1 / onboard_project.py) и явно упоминает fail-closed имена
|
||||
Confirm Deploy и STOP; при наличии дубля таблицы статусов в доке — дубль
|
||||
сверяется с plane_sync._PLANE_NAME_TO_KEY импортом (22 имени, нулевой
|
||||
дрейф); карта env и smoke даны ссылкой на REPLICATION.md (AC-6 / FR-4,
|
||||
NFR-4).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-07
|
||||
type: unit
|
||||
description: >
|
||||
Раздел Gitea соответствует инвариантам платформы: события
|
||||
push/pull_request/status, ОДИН глобальный webhook-секрет на все репо,
|
||||
и норматив защиты main согласован с исходом А-1 ADR задачи (канон: branch
|
||||
protection НЕ включать — ADR D10 ORCH-009; инструкция не предписывает
|
||||
запрещённого) (AC-1, AC-7 / FR-1.6, §3.8 А-1).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-08
|
||||
type: unit
|
||||
description: >
|
||||
Перекрёстная документация (AC-5): REPLICATION.md §1 (границы 10-common vs
|
||||
Lite vs Bundled) ссылается на LITE_SETUP.md / отмечает Lite реализованным;
|
||||
CHANGELOG.md содержит запись ORCH-102 (AC-5 / FR-7).
|
||||
module: tests/test_lite_setup_doc.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-09
|
||||
type: integration
|
||||
description: >
|
||||
Приёмочный smoke-прогон по LITE_SETUP.md на чистом контуре (минимум:
|
||||
staging-песочница ORCH_STAGING_PORT с изолированной БД ./data/staging +
|
||||
одноразовый sandbox-проект; прецедент ORCH-101 AC-3): чек-лист REPLICATION
|
||||
§4 шаги 0–5 — конфиг резолвится, /health 200, /queue+/metrics штатны,
|
||||
onboard verify зелёный, тестовая задача дошла до артефактов 01–04; вердикт
|
||||
и контур зафиксированы в 13-test-report.md / 15-staging-log.md. Процедурная
|
||||
приёмка (исполняет tester по чек-листу), не pytest-модуль (AC-4 / FR-5).
|
||||
module: tests/manual/lite-smoke-checklist (процедура; протокол в 13/15)
|
||||
expected: PASS
|
||||
|
||||
- id: TC-10
|
||||
type: integration
|
||||
description: >
|
||||
Полный регресс: pytest tests/ -q зелёный; существующие структурные тесты
|
||||
(test_no_host_hardcodes, test_replication_smoke, test_infra_parametrization,
|
||||
test_onboarding_*) не ослаблены/не правлены под задачу; дифф не трогает
|
||||
src/** (или каждое отклонение обосновано ADR), STAGE_TRANSITIONS/QG_CHECKS/
|
||||
machine-verdict/схему БД (AC-5, AC-7 / NFR-2).
|
||||
module: tests/
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user