26 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-104 | analysis | analyst | ready-for-review | 2026-06-11 | claude-opus-4-8 |
02 — ТЗ (TRZ): ORCH-104 — Установочный скрипт Lite-тиража (интерактивный installer)
Work Item: ORCH-104 · Repo: orchestrator · Стадия: analysis
ТЗ описывает что должно измениться и где (модули/контракты/артефакты). Как (имя/режимы скрипта, эвристики discovery, степень автоматизации отдельных шагов) — решает архитектор в
06-adr/. Тип изменения — scripts + docs + tests (паттерн ORCH-009/103): рантаймsrc/**байт-в-байт.
1. Сводка изменения
Ввести единый операторский установочный скрипт Lite-тиража: один файл в scripts/,
который интерактивно проводит внешнего оператора по маршруту docs/deployment/LITE_SETUP.md
§2–§12 — сканирует предусловия хоста и предлагает доустановить недостающее, обнаруживает
инсталляции Plane/Gitea (при нескольких — даёт выбрать), запрашивает обязательные ключи в
момент установки с немедленной верификацией, автодетектит хост-параметры, собирает
.env/.env.watchdog от канонов, поднимает Lite-контур, регистрирует проект заказчика
кирпичом onboard_project.py и выдаёт итоговый вердикт PASS/MANUAL/FAIL с exit-кодами
0/2/1. Паттерн — bootstrap_bundle.py (ORCH-103): step-движок check→ensure, stdlib-only,
no-delete, manual-checkpoint с верификацией, идемпотентный повтор. Канон LITE_SETUP.md не
форкается — скрипт становится в нём рекомендованным быстрым путём, ручной маршрут сохраняется.
2. Задействованные модули / пути
| Путь | Действие | Роль в задаче |
|---|---|---|
scripts/setup_lite.py (имя-кандидат; финал — архитектор) |
создать | единый установочный CLI: step-движок, скан, discovery, интерактивный сбор, сборка конфигов, запуск, отчёт |
scripts/gen_secrets.py |
переиспользовать, не менять | кирпич выпуска webhook-секретов (субпроцесс — паттерн AC-7 ORCH-103: канон-знания только субпроцессами кирпичей) |
scripts/onboard_project.py |
переиспользовать, не менять | кирпич регистрации проекта: Plane-проект + 22 статуса + лейблы, Gitea-репо + webhook, merged-ORCH_PROJECTS_JSON |
docs/deployment/LITE_SETUP.md |
обновить | скрипт = рекомендованный быстрый путь; ручной маршрут остаётся каноном-fallback; размещение не ломает пиннинг «13 разделов в порядке» ЛИБО тест обновляется синхронно |
tests/test_setup_lite_script.py (имя-кандидат) |
создать | анти-дрейф + unit чистых функций (по образцу tests/test_bootstrap_script.py) |
tests/test_lite_setup_doc.py |
обновить при необходимости | если меняется пиннингуемая структура LITE_SETUP.md (разделы/кирпичи) |
CHANGELOG.md |
обновить | запись feat: |
docs/overview/ |
обновить при необходимости | если витрина описывает маршрут Lite-тиража (таблица соответствия — в индексе витрины, правило агентов №2/ORCH-011) |
src/**, docker-compose.yml, Dockerfile, .env.example, .env.watchdog.example |
НЕ менять | каноны-источники: скрипт их только читает (шаблоны env, состав сервисов) |
3. Функциональные требования
FR-1 — Единая точка входа, режимы, идемпотентность (BR-1, BR-5)
- Один файл; запуск
python3 scripts/setup_lite.py …из корня чекаута репоorchestratorна голом python3 (до venv и доdocker compose up). - Обязательны как минимум: read-only режим диагностики (ноль мутаций: скан предусловий +
discovery + план шагов — аналог
planORCH-103) и установочный интерактивный режим (аналогapply); желателенverify(read-only пост-проверка). Дефолтный режим и имена — решение архитектора (OQ-1) с учётом паттерна D5 ORCH-009/103 («plan — дефолт») и бизнес-цели «одна команда». - Step-движок check→ensure: каждый шаг сперва проверяет «уже сделано?» и при PASS
пропускается → повторный запуск идемпотентен; «resume» после manual-step = просто повторный
запуск (паттерн
bootstrap_bundle.run_apply). - Exit-коды (контракт):
0— все шаги PASS;2— остановка на manual-step / незавершённое предусловие;1— ошибка. - Каждая мутация хоста — с явного согласия пользователя (per-action consent); отказ от согласия → честный MANUAL-шаг с печатью эквивалентной команды, не молчаливый пропуск.
FR-2 — Скан предусловий с офером установки (BR-2; LITE_SETUP §2, §7)
- Проверяемый перечень (каждый пункт — отдельный вердикт
OK | MISSING | WARN | MANUAL):- ОС/арх:
uname -sm= Linux x86_64 (иное → WARN «вне контура Lite»); docker --version,docker compose version(v2),git --version,python3 --version,node --version;- дистрибутив claude-code (
npm root -g→ каталог@anthropic-ai/claude-code) и аутентификация CLI (читаемость~/.claude/.credentials.jsonuid'ом из п.5); - группа docker (
getent group docker→ gid дляORCH_DOCKER_GID); - uid/gid пользователя-владельца и каталога репозиториев (
ORCH_HOST_REPOS_DIR, инвариант ORCH-040: владелец =ORCH_RUN_UID:ORCH_RUN_GID); - каталог ssh-ключей (
ORCH_HOST_SSH_DIR): существование/ключи; - свободность портов (прод/staging, дефолты 8500/8501).
- ОС/арх:
- Для каждого
MISSING: определить пакетный менеджер хоста (например apt/dnf/yum/zypper — точный набор фиксирует архитектор) → предложить конкретную команду установки → выполнить её ТОЛЬКО с явного согласия; для node+claude-code — оферnpm install -g @anthropic-ai/claude-code; для ssh-ключей — оферssh-keygen(+ печать pubkey как manual-step «добавить в Gitea», §2.4/§6.2). - Неопределимый дистрибутив/менеджер, отказ пользователя, sudo-недоступность → честный MANUAL с готовыми командами и ссылкой на § LITE_SETUP; молчаливый пропуск запрещён.
- Интерактивный OAuth-логин claude CLI скрипт не выполняет — только верифицирует результат (§7.2) и выдаёт manual-step.
FR-3 — Discovery инсталляций Plane/Gitea (BR-4)
- Источник — локальный Docker: перечисление контейнеров, группировка в «инсталляции» по
метке compose-проекта (
com.docker.compose.project), опознание по именам образов (Plane:makeplane/*-семейство; Gitea:gitea/*) и published-портам; точные эвристики/паттерны — ADR. Из кандидата выводятся предлагаемые URL (ORCH_PLANE_API_URL/ORCH_PLANE_WEB_URL;ORCH_GITEA_URL/ORCH_GITEA_PUBLIC_URL). - Поведение по числу найденных: 0 → ручной ввод URL + честная подсказка «Lite не устанавливает Plane/Gitea; нет инфраструктуры — см. Bundled (BUNDLED_SETUP.md)»; 1 → префилл по умолчанию (с подтверждением); ≥2 → нумерованный список (проект, образы, порты) + выбор. Пункт «ввести вручную» доступен всегда.
- Best-effort, never-block: docker недоступен / ошибка перечисления / не-docker инсталляция (native/k8s) → ручной ввод, не FAIL.
- Discovery заполняет только кандидаты URL; токены всегда вводит пользователь (FR-4); выбранный кандидат всё равно проходит верификацию FR-4.
FR-4 — Интерактивный сбор обязательных ключей с немедленной верификацией (BR-3)
- Покрывается карта обязательных ключей нового хоста — §4.2 LITE_SETUP (группы: Plane,
Gitea, webhook-секреты, Telegram,
ORCH_PROJECTS_JSON, хост-параметры, порты). - Секретные значения вводятся скрыто (
getpass-класс ввода) и никогда не печатаются (ни в stdout, ни в лог; только имена ключей) — паттерн NFR-3 ORCH-103. - Немедленная верификация каждого введённого значения фактическим вызовом:
- Plane:
GET $ORCH_PLANE_API_URL/api/v1/workspaces/<slug>/projects/cX-API-Key→ 200; - Gitea:
GET $ORCH_GITEA_URL/api/v1/userc токеном → 200 (+ владелец →ORCH_GITEA_OWNER); - Telegram:
getMe→"ok":true; helper определения chat-id черезgetUpdates; - публичный URL оркестратора (для webhook'ов) — синтаксическая валидация + предупреждение, что достижимость со стороны Plane/Gitea проверится на smoke.
- Plane:
- Неуспех верификации → re-prompt с диагнозом (ограниченное число попыток — паттерн
manual_checkpoint(max_tries=3)), затем честный MANUAL/остановка exit 2 — не бесконечный цикл и не молчаливое принятие. - non-TTY (нет интерактива): честный отказ с подсказкой ЛИБО неинтерактивная альтернатива (флаги/answers-file — механизм решает архитектор, OQ-2); зависание недопустимо.
FR-5 — Автодетект хост-параметров и когерентность портов (BR-2, BR-6)
- Автоматически определяются и НЕ спрашиваются у пользователя (только подтверждение):
ORCH_RUN_UID/ORCH_RUN_GID(uid/gid владельцаORCH_HOST_REPOS_DIR/ текущего пользователя),ORCH_DOCKER_GID(getent group docker),ORCH_HOST_NODE_BIN(which node),ORCH_HOST_CLAUDE_CODE_DIR(npm root -g),ORCH_AGENT_HOME_DIR/ORCH_HOST_CLAUDE_DIR/ORCH_HOST_CLAUDE_JSON(HOME пользователя из §2.2),ORCH_DEPLOY_HOST_REPO_PATH(корень чекаута). - Порты: busy-check (
ss/socket) прод- и staging-портов; занят → предложить альтернативу. Смена прод-порта → синхронно согласовать тройкуORCH_DEPLOY_PROD_TARGET_PORT⇄WATCHDOG_METRICS_URL⇄ORCH_POST_DEPLOY_BASE_URL(§2.5/§4.2).ORCH_STAGING_PORT== прод-порт → отказ fail-closed (инвариант ORCH-058, усилен ORCH-101).
FR-6 — Сборка .env / .env.watchdog (BR-5; LITE_SETUP §4)
.envсобирается от канона.env.example(принцип ORCH-101: дефолт = боевое значение; записываются только собранные отличия нового хоста)..env.watchdog— от.env.watchdog.example(ключиWATCHDOG_TG_BOT_TOKEN/WATCHDOG_TG_CHAT_IDкладутся только туда — ловушка файла-носителя §4.3).- Webhook-секреты — кирпичом
gen_secrets.py(свежий выпуск; боевые секреты не используются — stateless §12 / REPLICATION §3). - Существующий
.env/.env.watchdog→ отказ (exit 2, внятное сообщение); перезапись — только явный force-флаг (паттернgen_secrets --force/--force-secretsORCH-103). Подсказки-дефолты промптов — из.env.example/автодетекта, никогда из боевых значений. - После сборки — резолв-проверка
docker compose config(PASS/FAIL, §4 «Проверка»).
FR-7 — Подключения и машинная охрана нормативов (BR-3, BR-6)
- Plane (§5): наличие workspace/доступность API верифицируются (FR-4); статусы/лейблы
вручную НЕ создаются (только кирпич onboarding, §5.3). Webhook (§5.4, каверза Plane CE):
Path A (UI) = manual-checkpoint с инструкцией и верификацией; Path Б (SQL в Postgres Plane)
= только с явного согласия + подтверждённый пользователем контейнер БД Plane +
пост-верификация (
SELECT url, is_active FROM webhooks); выбор степени автоматизации — ADR (OQ-3). Молчаливый пропуск запрещён. - Gitea (§6): токен верифицирован (
/api/v1/user); branch protection наmain: непустойbranch_protections→ FAIL шага с лечением (норматив §6.4 / ADR D10 ORCH-009 / INV-4); скрипт правила сам не удаляет (no-delete) — только инструкция. Per-repo webhook и репо создаёт кирпич onboarding (FR-9), не сам скрипт. - Telegram (§8): два независимых бота; идентичные токены орка и watchdog → отказ шага (C-1 ORCH-100 «ЗАПРЕЩЕНО» — машинная проверка, не примечание).
- LLM (§7): верификация дистрибутива/нод-бинаря/читаемости кредов uid'ом контейнера;
наличие
ORCH_AGENT_MODEL_DEFAULT/ORCH_AGENT_EFFORT_DEFAULTв собранном.env(§7.3).
FR-8 — Запуск Lite-контура и health (BR-6; LITE_SETUP §9, §12)
- С согласия:
docker compose up -d --build; проверка состава: запущены ровноorchestrator+orchestrator-watchdog,orchestrator-stagingНЕ поднят (строго заprofiles: [staging]). - Health-чек контрактов:
/health→ 200"status":"ok";/queue→ штатный JSON;/metrics→"schema_version": 1(порт — фактический из конфига). - Stateless-проверка чистоты (§12): счётчики jobs нулевые, ни одной задачи чужих проектов;
нарушение → FAIL с лечением «пересобрать
data/с нуля».
FR-9 — Регистрация проекта заказчика кирпичом onboarding (BR-6, BR-7; LITE_SETUP §10)
- Скрипт собирает параметры проекта (имя/описание/repo/prefix/stack/test-cmd/порты/
webhook-url из публичного URL оркестратора) и строит аргументы вызова
onboard_project.pyдетерминированной чистой функцией (тестируемо без сети). - Последовательность:
plan→ показать пользователю → согласие →apply→verify(субпроцессы; exit 2 кирпича = остались ручные шаги → транслировать как MANUAL). Степень автоматизации vs «печать готовой команды» — ADR (OQ-6; прецедент драйва —bootstrap_bundle.step_onboard). ORCH_PROJECTS_JSONиз отчётаapplyвписывается в.env(с согласия); затем управляемый рестарт только собственного свежеподнятого контура по процедуре §10: проверка тихого окна (/queueбез running-job) →docker compose up -d --force-recreate orchestrator→ пост-проверка/health+/queue.
FR-10 — Итоговый отчёт (BR-1, BR-6)
- Финальная сводная таблица всех шагов: PASS/FAIL/MANUAL; для каждого MANUAL — что сделать и ссылка на § LITE_SETUP; для FAIL — диагноз и лечение (зеркало §13 траблшутинга).
- Smoke первой задачи (§11: issue → «To Analyse» → артефакты
01–04) выдаётся как завершающая manual-инструкция (вердикт «тираж PASS» — за оператором).
FR-11 — Документация: канон не форкается (BR-7)
docs/deployment/LITE_SETUP.md: скрипт вводится как рекомендованный быстрый путь (врезка/подраздел в начале маршрута); ручной маршрут §2–§13 сохраняется как канон и fallback для MANUAL-шагов. Размещение либо не ломает пиннингtest_doc_exists_with_all_13_sections_in_order, либо тест обновляется в том же PR.- Норматив сопровождения (NFR-5 ORCH-102) расширяется симметрично: «меняешь шаги тиража → обнови LITE_SETUP.md и установочный скрипт в том же PR».
4. Изменения API
Нет. Эндпоинты оркестратора не добавляются и не меняются; скрипт — потребитель
существующих read-only контрактов (/health, /queue, /metrics) и внешних API
(Plane/Gitea/Telegram).
5. Изменения схемы БД
Нет. БД оркестратора не затрагивается (создаётся пустой при первом старте — штатно); БД Plane заказчика — только опциональная webhook-вставка Path Б §5.4 (FR-7, с согласия).
6. Требования к новым/изменённым QG checks
Нет. Скрипт — операторский инструмент вне рантайма и вне конвейера;
STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict ключи — байт-в-байт.
7. Совместимость / регресс
- Kill-switch не нужен: активация — только явный запуск CLI человеком (паттерн ORCH-009/102/103); рантайм не несёт ни одной новой кодовой ветки.
- Полный существующий регресс
pytest tests/ -qостаётся зелёным;test_lite_setup_doc.py— зелёный (с синхронным обновлением при правке структуры дока). - Обратимость: задача добавляет файлы
scripts/+tests/+ правку дока; откат = revert PR, поведение платформы не меняется в обе стороны. - Скрипт не вносит хост-литералов в
src/**(вне сканаtest_no_host_hardcodes.pyпо определению, т.к.src/**не трогается).
8. Конфигурация
Новых ключей Settings/.env.example не вводится. Скрипт читает каноны
.env.example/.env.watchdog.example как шаблоны и пишет целевые .env/.env.watchdog
(FR-6). Платформенные константы (SELF_HOSTING_REPO="orchestrator", имена сервисов, layout
контейнера) не параметризуются (норматив REPLICATION §1).
9. Наблюдаемость
- Структурный stdout-лог прогона (шаг → вердикт → диагноз) + итоговая таблица (FR-10).
- Exit-код = машинный итог прогона (
0/2/1) — пригоден для обвязки/CI заказчика. - Опциональный файл-отчёт прогона — на усмотрение архитектора (ADR).
10. Артефакты pipeline (создать/обновить в ТОМ ЖЕ PR)
docs/work-items/ORCH-104/06-adr/ADR-001-<slug>.md— решения: имя/режимы скрипта, эвристики discovery, политика оферов установки, автоматизация webhook Path Б и onboarding, механизм non-TTY (архитектор).docs/deployment/LITE_SETUP.md— быстрый путь (FR-11).tests/test_setup_lite_script.py(+ правкаtests/test_lite_setup_doc.pyпри необходимости).CHANGELOG.md— записьfeat:; витринаdocs/overview/— если затронуто описание тиража.
11. Инварианты (не нарушать)
src/**, корневойdocker-compose.yml,Dockerfile,STAGE_TRANSITIONS,QG_CHECKS,check_*, machine-verdict ключи, схема БД — байт-в-байт.- stdlib-only; модули платформы не импортируются; канон-знания — только субпроцессами
кирпичей (
gen_secrets.py,onboard_project.py). - No-delete: ни одной удаляющей операции (файлы, контейнеры, ветки, правила) — лечение всегда инструкцией.
- Никогда не push/force-push/иные операции в
main(INV-4); не рестартить чужие/боевые контейнеры; мутации — только с явного согласия. - Секреты: свежие, скрытый ввод, не печатаются; существующие
.env*молча не перетираются. - Stateless: данные/задачи/секреты исходного хоста не переносятся ни одним шагом.
12. Открытые вопросы для архитектора (не блокируют анализ)
- OQ-1: имя скрипта и набор/дефолт режимов: строгий паттерн D5 (
plan— дефолт, мутации только вapply) vs «запуск без аргументов = wizard» (бизнес-цель «одна команда»). Возможный компромисс: wizard-дефолт, где фаза скана всегда read-only, а мутации — за per-action consent. - OQ-2: механизм неинтерактивного прогона (флаги / answers-file / env-переменные) и точное поведение в non-TTY.
- OQ-3: webhook Plane: автоматизировать ли Path Б (SQL) или строго manual-checkpoint; критерий выбора/подтверждения контейнера Postgres Plane.
- OQ-4: политика оферов установки: исполнять команды пакетного менеджера из скрипта (с согласия) vs только печатать (безопаснее); набор поддерживаемых менеджеров.
- OQ-5: размещение быстрого пути в LITE_SETUP.md (врезка в §1 vs новый раздел с правкой пиннинга «13 разделов») и судьба нумерации.
- OQ-6: степень драйва onboarding: субпроцесс plan→apply→verify изнутри скрипта
(прецедент
bootstrap_bundle.step_onboard) vs печать готовой команды.