Files
orchestrator/docs/work-items/ORCH-104/02-trz.md
claude-bot 94a3f399f2
All checks were successful
CI / test (push) Successful in 58s
analyst(ET): auto-commit from analyst run_id=638
2026-06-11 20:19:18 +03:00

26 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-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 + план шагов — аналог plan ORCH-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):
    1. ОС/арх: uname -sm = Linux x86_64 (иное → WARN «вне контура Lite»);
    2. docker --version, docker compose version (v2), git --version, python3 --version, node --version;
    3. дистрибутив claude-code (npm root -g → каталог @anthropic-ai/claude-code) и аутентификация CLI (читаемость ~/.claude/.credentials.json uid'ом из п.5);
    4. группа docker (getent group docker → gid для ORCH_DOCKER_GID);
    5. uid/gid пользователя-владельца и каталога репозиториев (ORCH_HOST_REPOS_DIR, инвариант ORCH-040: владелец = ORCH_RUN_UID:ORCH_RUN_GID);
    6. каталог ssh-ключей (ORCH_HOST_SSH_DIR): существование/ключи;
    7. свободность портов (прод/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/ c X-API-Key → 200;
    • Gitea: GET $ORCH_GITEA_URL/api/v1/user c токеном → 200 (+ владелец → ORCH_GITEA_OWNER);
    • Telegram: getMe"ok":true; helper определения chat-id через getUpdates;
    • публичный URL оркестратора (для webhook'ов) — синтаксическая валидация + предупреждение, что достижимость со стороны Plane/Gitea проверится на smoke.
  • Неуспех верификации → 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_PORTWATCHDOG_METRICS_URLORCH_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-secrets ORCH-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_protectionsFAIL шага с лечением (норматив §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 → показать пользователю → согласие → applyverify (субпроцессы; 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» → артефакты 0104) выдаётся как завершающая 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 печать готовой команды.