From 52e2e5fda19695ea9cf090fe81a73cf3f88e161e Mon Sep 17 00:00:00 2001 From: claude-bot Date: Fri, 12 Jun 2026 02:56:23 +0300 Subject: [PATCH] developer(ET): auto-commit from developer run_id=642 --- docs/architecture/README.md | 2 +- docs/deployment/LITE_SETUP.md | 38 ++++++++++++++++++++++++++++--- tests/test_lite_setup_doc.py | 42 +++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 0de0aab..0a56db0 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -245,7 +245,7 @@ Type B). Анти-дрейф — `tests/test_bundle_compose.py` / `test_bundled_ [adr-0038](adr/adr-0038-bundled-replication-canon.md), детально — `docs/work-items/ORCH-103/06-adr/ADR-001-bundled-stack-compose-and-bootstrap.md`. -**Интерактивный installer Lite (ORCH-104 — design).** Lite получает инструмент, симметричный +**Интерактивный installer Lite (ORCH-104).** Lite получает инструмент, симметричный Bundled-bootstrap'у: **`scripts/setup_lite.py`** — python stdlib-only wizard, автоматизирующий маршрут LITE_SETUP §2–§12 (скан предусловий с офером доустановки per-package consent'ом; discovery docker-инсталляций Plane/Gitea строго по image-префиксам с выбором пользователя; diff --git a/docs/deployment/LITE_SETUP.md b/docs/deployment/LITE_SETUP.md index 50bc5b0..ba57c89 100644 --- a/docs/deployment/LITE_SETUP.md +++ b/docs/deployment/LITE_SETUP.md @@ -6,6 +6,8 @@ > Хост-специфика в командах — только плейсхолдеры `<...>` и `$ENV_VAR`. > Тираж **stateless**: данные/задачи/секреты исходного (боевого) хоста **НЕ переносятся** > ни на одном шаге — всё создаётся заново (§12). +> **Быстрый путь — `scripts/setup_lite.py`** (§1.1): интерактивный installer проводит по +> §2–§12 за один прогон; ручной маршрут ниже остаётся каноном и fallback'ом. --- @@ -32,6 +34,35 @@ compose-файле, но строго за профилем `staging` и в ба - контейнерные пути (`/app/data`, `/repos`, `/opt/claude-code`) — layout контейнера, не хост-значения; не параметризуются. +### 1.1. Быстрый путь: `setup_lite.py` (рекомендуется) + +Вместо ручного прохода §2–§12 запустите **интерактивный installer** — он сканирует +предусловия хоста и предлагает доустановить недостающее, обнаруживает ваши инсталляции +Plane/Gitea (при нескольких — даёт выбрать), запрашивает обязательные ключи **в момент +установки с немедленной верификацией**, автодетектит хост-параметры, собирает +`.env`/`.env.watchdog` от канонов (свежие webhook-секреты — кирпичом `gen_secrets.py`), +поднимает ровно орк+watchdog и регистрирует ваш проект строго кирпичом `onboard_project.py`. + +```bash +cd <путь-чекаута> # корень репо orchestrator +python3 scripts/setup_lite.py # apply (дефолт): интерактивная установка +python3 scripts/setup_lite.py plan # read-only диагностика (ноль мутаций) +python3 scripts/setup_lite.py verify # read-only пост-проверка контура +``` + +**Контракт:** дефолт-режим `apply` — установка «одной командой»; безопасность дефолта +структурна — фаза 0 любого `apply` ≡ `plan` (read-only скан), каждая мутация хоста — с +**явного согласия** (per-action consent с печатью точной команды), существующий чужой +`.env`/`.env.watchdog` **не перетирается** без `--force` (guard managed-маркера), в +non-TTY без `--yes` — честный выход без зависания. Exit-коды: `0` — все шаги PASS; `2` — +остановка на ручном шаге (повторный запуск продолжит с него — resume); `1` — ошибка. +Секреты вводятся скрыто и **никогда не печатаются**; delete-операций скрипт не выполняет +(лечение — всегда инструкция). Любой ручной шаг ссылается на соответствующий § ниже — +ручной маршрут §2–§13 остаётся полным каноном и fallback'ом для MANUAL-шагов. + +**Проверка:** `python3 scripts/setup_lite.py plan` завершается без блокеров (exit 0) — +PASS; есть блокеры (exit 2) — устраните по выводу и повторите. + --- ## 2. Предусловия хоста @@ -588,9 +619,10 @@ PR-merge API оркестратора, ручной merge не требуетс --- -*Golden source Lite-тиража (ORCH-102, ADR-001). **Норматив сопровождения (NFR-5):** -меняешь шаги тиража (env-ключи, compose-сервисы, маршрут онбординга, smoke) → обнови -этот док В ТОМ ЖЕ PR (правило агентов №2). Полноту и гигиену дока держит структурный +*Golden source Lite-тиража (ORCH-102, ADR-001). **Норматив сопровождения (NFR-5, расширен +ORCH-104):** меняешь шаги тиража (env-ключи, compose-сервисы, маршрут онбординга, smoke) → +обнови этот док **И установочный скрипт `scripts/setup_lite.py`** В ТОМ ЖЕ PR (правило +агентов №2). Полноту и гигиену дока держит структурный анти-дрейф тест `tests/test_lite_setup_doc.py`; кирпичи-каноны: REPLICATION.md (карта env §2, секреты §3, smoke §4), ONBOARDING.md (статусы §1, онбординг), SETUP_WEBHOOKS.md (формат вебхуков), `.env.example` / `.env.watchdog.example` (канон ключей).* diff --git a/tests/test_lite_setup_doc.py b/tests/test_lite_setup_doc.py index b1ad6b3..3b94d50 100644 --- a/tests/test_lite_setup_doc.py +++ b/tests/test_lite_setup_doc.py @@ -426,3 +426,45 @@ def test_replication_boundaries_reference_lite_setup(): def test_changelog_has_orch_102_entry(): assert "ORCH-102" in CHANGELOG.read_text(encoding="utf-8") + + +# --------------------------------------------------------------------------- +# TC-27 (ORCH-104, FR-11 / D12): LITE_SETUP.md вводит установочный скрипт как +# рекомендованный быстрый путь и сохраняет ручной маршрут (пиннинг «13 разделов» +# в порядке держит test_doc_exists_with_all_13_sections_in_order — не трогается). +# --------------------------------------------------------------------------- +def test_doc_introduces_setup_lite_fast_path(): + text = _doc_text() + assert "setup_lite.py" in text, ( + "LITE_SETUP.md не вводит установочный скрипт setup_lite.py (ORCH-104 FR-11)" + ) + # быстрый путь — подраздел §1.1 ВНУТРИ §1 (нумерация ## 1.…## 13. не меняется) + body1 = _section_bodies()["## 1. Рамка Lite"] + assert "1.1" in body1 and "setup_lite.py" in body1, ( + "быстрый путь обязан быть подразделом §1.1 внутри §1 (D12)" + ) + # ручной маршрут сохранён как канон/fallback — упомянут явно + assert "fallback" in text.lower() or "ручной маршрут" in text, ( + "ручной маршрут §2–§13 обязан остаться каноном/fallback (FR-11)" + ) + # норматив сопровождения расширен на скрипт (D12) + assert "scripts/setup_lite.py" in text + + +def test_setup_lite_fast_path_block_is_clean(): + """§1.1 fenced-блок проходит те же сканы, что весь док: без боевых литералов, + без секретоподобных значений, без неизвестных env-токенов.""" + body1 = _section_bodies()["## 1. Рамка Lite"] + blocks = _fenced_blocks(body1) + assert blocks, "§1.1 обязан нести fenced-блок с командой запуска (D12)" + for i, block in enumerate(blocks): + for literal in FORBIDDEN: + assert literal not in block, f"§1.1 блок #{i}: боевой литерал {literal!r}" + for rx in (_SECRET_HEX_RE, _SECRET_ALNUM_RE): + assert rx.search(block) is None, f"§1.1 блок #{i}: секретоподобное значение" + # упомянутые в §1.1 env-токены (если есть) — только из канона .env.example + canon = _env_keys(ENV_EXAMPLE) + mentioned = set(_ENV_TOKEN_RE.findall(body1)) + assert not (mentioned - canon), ( + f"§1.1 упоминает env-токены вне .env.example: {sorted(mentioned - canon)}" + )