13 Commits

Author SHA1 Message Date
6d798c01ef docs(overview): витрина системы docs/overview/ — бизнес+тех, 3 аудитории, презентация (ORCH-011)
Единая точка входа в документацию платформы (ADR-001 D1–D9):
- docs/overview/ — 10 файлов: индекс (маршруты «Я заказчик / Я менеджер /
  Я разработчик» + норматив «изменил функциональность → обнови витрину в том же
  PR»), business.md (без жаргона, 6 сценариев), 7 тех-блоков (link-first),
  presentation.md (16 слайдов + процедура сборки «команда + Проверка:»).
- scripts/build_presentation.py — генератор .pptx в тёмном дизайне (python-pptx;
  чистый stdlib-парсер parse_slides + ленивый import pptx; бинарь не коммитится,
  build/ в .gitignore; зависимость НЕ в прод-образе — машинный гард TC-09).
- tests/test_system_docs.py — структурный анти-дрейф: derive-сверки стадий/
  гейтов/агентов импортом STAGE_TRANSITIONS/QG_CHECKS/glob промптов/config,
  валидность ссылок, FORBIDDEN-скан + секрет-эвристика, слайды каноническим
  парсером, NFR-2, указатели.
- reviewer.md — ось обзорных доков ORCH-079 расширена на витрину (D7; канон 52d
  байт-в-байт, только текст внутри секций) + анти-регресс ассерт в
  test_agent_prompts_canon.py.
- Указатели: README.md, CLAUDE.md (правила №2/№6, «Структура»),
  PRODUCT_VISION.md (врезка-ссылка), CHANGELOG.md.

Рантайм байт-в-байт: src/**, docker-compose.yml, Dockerfile, requirements* —
ноль изменений (docs+tests+dev-скрипт, паттерн ORCH-102/103). pytest: 1873 passed.

Refs: ORCH-011

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 09:36:40 +03:00
f0cd19d748 feat(replication): ORCH-10b Bundled-тираж — bundle-compose всего стека + bootstrap-скрипт
Закрывает Type B эпика ORCH-10 (по ADR-001 ORCH-103, D1–D11):

- deploy/bundled/docker-compose.yml — самодостаточный compose всего стека
  (орк + watchdog + Gitea 1.22.6 + зеркало upstream Plane CE v0.23.1,
  ~14 контейнеров); project name orchestrator-bundle (узнаваемый префикс),
  container_name не пиннится, staging-контура нет; одна bridge-сеть,
  машинный трафик — сервис-DNS, наружу только человеческие порты;
  GITEA__webhook__ALLOWED_HOST_LIST=orchestrator; все образы пиннованы
  неподвижными тегами. Корневой compose/Dockerfile/src/** — байт-в-байт.
- deploy/bundled/.env.example — конфиг-канон bundle (плейсхолдеры, ни одного
  дефолтного пароля; key-set-sync интерполяций держит тест).
- scripts/bootstrap_bundle.py — python stdlib-only, режимы plan/apply/verify,
  step-движок check→ensure, exit 0/2/1: preflight (fail-fast до мутаций) →
  секреты (gen_secrets.py + stdlib secrets, без перетирания) → up+готовность →
  init Gitea автоматом → init Plane (manual-step с API-верификацией) →
  онбординг строго onboard_project.py apply+verify → token-remote клон →
  сборка .env/.env.watchdog (единственный писатель, права 600) → health.
  Delete-операций нет вообще (D9), секреты не печатаются (NFR-3).
- CHANGELOG.md, CLAUDE.md (абзац Type B), .gitignore (deploy/bundled/repos/).

Док BUNDLED_SETUP.md, REPLICATION §1, arch README, adr-0038 и три структурных
тест-модуля (TC-01…TC-11) — в предыдущих коммитах ветки; полный регресс
1844 passed, ruff по файлам задачи чистый.

Refs: ORCH-103

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 02:16:32 +03:00
f1635ddb39 feat(replication): расхардкод хоста + секреты нового хоста + smoke-runbook
All checks were successful
CI / test (push) Successful in 57s
CI / test (pull_request) Successful in 55s
Фундамент тиража 10-common (эпик ORCH-10): платформа разворачивается на
новой инфре без правки кода — только env/конфиг. Каждый дефолт = боевому
значению (пустой .env => поведение 1:1, kill-switch-природа, NFR-2);
STAGE_TRANSITIONS/QG_CHECKS/check_*/machine-verdict/схема БД не тронуты.

- config: agent_home_dir / agent_git_name / git_email_domain / staging_port
  (ADR-001 D2/D4); код-блокеры A1-A4 закрыты: plane_sync ссылки из
  gitea_public_url+gitea_owner, launcher - единый agent_git_env() (x2 места),
  self_deploy/post_deploy - HOME+домен из Settings (имена системных акторов -
  платформенные литералы)
- image_freshness: staging_port из конфига + fail-closed guard
  staging_port == прод-порт -> отказ ДО ssh/build (инвариант ORCH-058 AC-9
  стал исполняемым); REPO= передаётся хуку явно обоими инвокерами (D7)
- SELF_HOSTING_REPO - нормативная платформенная константа (D3, пин-тест)
- compose: полная ${VAR:-default}-интерполяция (реестр B, карта D6); группа
  ORCH-040 uid/gid/HOME/маунты двигается согласованно (build.args APP_*);
  group_add "МИНА 1" сохранён x3; оба app-сервиса с явным command:
- Dockerfile: ARG APP_UID/APP_GID/APP_USER/APP_HOME (CMD exec-form 8500
  сознательно не тронут - D5); deploy-hook: REPO="${REPO:-...}" (D1 реестра)
- секреты: stdlib scripts/gen_secrets.py (token_hex(32); печать по умолчанию;
  --write никогда не перезаписывает существующий .env молча, exit=2;
  перезапись только --force); .env.example дополнен до полноты ключей старта
- доки: новый docs/operations/REPLICATION.md (карта env, чек-лист секретов,
  smoke-процедура с PASS/FAIL, границы 10-common/Lite/Bundled), INFRA.md,
  README, CLAUDE.md, CHANGELOG
- анти-регресс: tests/test_no_host_hardcodes.py (tokenize-сканер запрещённых
  литералов, config-модули - структурное исключение, allowlist пуст,
  негативная самопроверка) + test_host_config_keys / test_infra_parametrization
  / test_secrets_gen / test_replication_smoke; согласованные структурные
  правки test_orch040_compose (судит резолв дефолтов) и
  test_deploy_hook_rollback_sim (REPO через env-override = контракт D7)

Полный регресс: 1764 passed.

Refs: ORCH-101

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 20:50:43 +03:00
dc1cb87818 feat(onboarding): turnkey project onboarding — kit + CLI + runbook (ORCH-009)
Operator capability to bring a NEW project online in one pass, fully
outside the runtime and the pipeline (src/** byte-exact, no kill-switch
needed — activation is an explicit human CLI run). Reference = the
orchestrator repo itself (ORCH-52b/c/d/e canons).

* onboarding/repo-skeleton/ — parametrized kit of a new repo: 6 agent
  prompt templates per canon 52d/92 (5 ru + deployer en with the
  shared-host guardrail frame), reviewer doc-gate (REQUEST_CHANGES),
  CLAUDE.md passport, AGENTS.md, CONTRIBUTING.md, docs/ skeleton with
  mandatory operations/INFRA.md, .env.example; {{NAME}} placeholders +
  stdlib render, dictionary onboarding/placeholders.json (bijection
  held by tests). Canon is NOT forked: docs/_templates + docs/_standards
  are live-copied from the checkout at materialization time (BR-2/D3).
* scripts/onboard_project.py — plan (default, GET-only, zero mutations)
  / apply (idempotent ensure, no delete ops at all) / verify (registry
  round-trip via the actual projects._parse_projects_json, all 22 state
  names incl. fail-closed Confirm Deploy/STOP, labels, webhook, kit
  completeness, unresolved-placeholder scan). Closed read-only src
  import list (ADR D4); state groups fixed per ADR D5 (STOP→cancelled,
  terminal groups only Done/Cancelled/STOP); Gitea webhook reuses the
  single global ORCH_GITEA_WEBHOOK_SECRET (TR-6); initial push ONLY
  into a freshly created empty repo (INV-4 untouched); never restarts
  prod / never edits .env / deletes nothing (NFR-2); secrets masked
  (NFR-3); Plane CE API gaps degrade to manual-step (fail-safe).
* docs/operations/ONBOARDING.md runbook + SETUP_WEBHOOKS.md generalized
  per-repo; CLAUDE.md / docs/architecture/README.md / CHANGELOG.md
  updated in the same PR (golden source).
* Anti-drift tests: test_onboarding_kit.py / test_onboarding_script.py
  (mocked, no network) / test_onboarding_invariants.py (snapshots of
  STAGE_TRANSITIONS/QG_CHECKS, closed CLI import list, reference
  .openclaw/agents/ prompts untouched). Full regression: 1713 passed.

Refs: ORCH-009

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 16:08:43 +03:00
9070489968 fix(staging): tolerate sandbox-infra-only FAILs (C9a/C9b) in deploy-staging verdict
Some checks failed
CI / test (push) Failing after 39s
CI / test (pull_request) Failing after 35s
The self-hosting orchestrator looped on deploy-staging -> development because
scripts/staging_check.py exited 1 on ANY failed check, so two infra-only checks
(C9a sandbox branch / C9b analyst-job — caused by SANDBOX bot accounts not being
members of the sandbox Plane project, NOT a pipeline regress) forced
staging_status: FAILED -> rollback -> loop, burning developer retries and tokens.

Direction (б) per ADR-001: classify staging checks as REAL (all pipeline checks,
fail-closed) vs SANDBOX_INFRA (narrow allowlist {C9a, C9b}, waivable). New leaf
module src/staging_verdict.py (stdlib-only, never-raise): classify_check +
compute_staging_verdict fold per-check results into a tolerant-but-fail-closed
verdict — any REAL failure -> FAILED/exit1 (safety net holds under any flag);
only C9a/C9b failed & tolerant -> SUCCESS/exit0 with waived list; only infra &
strict -> FAILED/exit1; any internal error -> FAILED/exit1 (never a false green).

staging_check.py now auto-classifies each check (public 3-tuple _items shape kept
as an ORCH-048 b6 regression guard), exposes categorized_items(), prints
INFRA-WAIVED/VERDICT lines, and exits via the verdict; new --strict flag forces
legacy strictness per-run. Kill-switch ORCH_STAGING_INFRA_TOLERANCE_ENABLED
(default true) restores legacy strict mode globally. launcher gains
action_stage_no_changes_note so "no changes to commit" on action stages is logged
as expected, not treated as under-delivery.

Contracts unchanged: STAGE_TRANSITIONS, QG_CHECKS registry, staging_status:/
deploy_status: frontmatter, hook exit-code (0/1/2), check_staging_status; no DB
migration. Docs: README, STAGING_CHECK.md, deployer.md, .env.example, CHANGELOG.

Refs: ORCH-061

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 12:39:00 +00:00
6ddff5583d fix(ORCH-058): parametrize staging_check in --build-staging + explicit staging target
All checks were successful
CI / test (push) Successful in 19s
CI / test (pull_request) Successful in 18s
Round-3 review follow-up on c53d625 (P1/P2):

- P1: --build-staging now runs staging_check via parametrized
  STAGING_CONTAINER / STAGING_CHECK_PATH / STAGING_CHECK_MODE (default
  orchestrator-staging / bind-mount path / stub) instead of hardcoding
  $TARGET_SERVICE + the script path. docker exec runs INSIDE the staging
  container (ORCH-048 canonical: B6 registry isolation), after health,
  before exit 0. Fail-closed: any non-zero -> exit 1. STAGING only (8501).
- P2a: rebuild_staging_image now passes the STAGING target EXPLICITLY
  (TARGET_SERVICE/TARGET_PORT/COMPOSE_PROFILE/STAGING_CONTAINER) so the
  self-rebuild can never drift onto prod 8500 if hook defaults change (AC-9).
- P2b: TC-09 caller<->hook contract tests assert the ssh command carries
  GIT_SHA + BUILD_CONTEXT + the staging target and never the prod 8500 one;
  no-ssh-host fails closed.
- P3: consolidated the three duplicate README footers into one.
- Docs (golden source): DEPLOY_HOOK.md step 4 + env rows, README footer,
  CHANGELOG, Dockerfile ARG GIT_SHA="" comment, .env.example freshness block.

Validates exactly the artefact later BUILD-ONCE retagged to prod (AC-4,
ADR-001 step 3). 632 tests pass, ruff clean, bash -n OK.

Refs: ORCH-058

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 09:24:38 +00:00
Dev Agent
c53d625744 ORCH-058: --build-staging runs staging_check.py --mode stub vs fresh 8501 (AC-4)
All checks were successful
CI / test (push) Successful in 16s
Per ADR-001 step 3 / AC-4: after the freshly rebuilt staging container is
healthy, run staging_check.py --mode stub against the fresh 8501 stand BEFORE
reporting success, so the EXACT artefact BUILD-ONCE retagged to prod is the one
validated on staging. Fail-closed: staging_check rc!=0 -> exit 1 (not promoted).

- Invoked inside the container (docker exec $TARGET_SERVICE) per the canonical
  signature in scripts/staging_check.py header, --base-url http://localhost:$TARGET_PORT.
- Targets ONLY 8501 (staging), never 8500 (prod) - AC-9.
- --mode stub: fast, deterministic, no LLM spend (ADR).
- Static regression test test_tc07_build_staging_runs_staging_check_stub_after_health:
  asserts staging_check.py + --mode stub present, runs after health, before exit 0,
  fail-closed, and never hard-codes prod 8500.
2026-06-07 12:11:07 +03:00
2ee06ae676 fix(deploy-hook): --build-staging must build from validated worktree, recreate+health 8501
All checks were successful
CI / test (push) Successful in 17s
Closes reviewer P0/P1 (ORCH-058 attempt 3): the committed --build-staging hook
recomputed GIT_SHA=$(git rev-parse HEAD) in $REPO (prod clone on `main`) and built
`docker build ... "$REPO"`, ignoring the caller-supplied BUILD_CONTEXT/GIT_SHA. On
the deploy-staging -> deploy edge the PR is not yet merged, so `main` HEAD != the
validated SHA -> the staging image got the wrong revision label and Strategy-B's
guard fail-closed on EVERY valid self-deploy (AC-6 deadlock). It also only did
`docker build` + exit 0 — never recreating 8501 nor health-checking — so
rebuild_staging_image's rc=0 ("rebuilt and healthy") was a lie (AC-4 unmet).

- Hook --build-staging now honours caller BUILD_CONTEXT (validated worktree) and
  GIT_SHA, recreates orchestrator-staging on the fresh image and runs the 10x6s
  health-check; build/health failure -> exit 1 (FAILED contract preserved).
- image_freshness.rebuild_staging_image: document why COMPOSE_PROFILE/TARGET_SERVICE/
  TARGET_PORT are intentionally omitted (hook STAGING defaults -> 8501 only, P2).
- tests: assert the caller<->hook contract (builds from $BUILD_CONTEXT, no
  `git rev-parse HEAD` recompute, recreates + health-checks 8501) so the P0
  regression can't pass green again (P1).

Refs: ORCH-058

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 08:37:51 +00:00
Dev Agent
f0c2986477 ORCH-058: implement fail-closed provenance guard in deploy-hook + GIT_SHA OCI label in Dockerfile
All checks were successful
CI / test (push) Successful in 16s
- deploy-hook: REVISION_LABEL/EXPECTED_REVISION (default unset -> backward-compat)
- deploy-hook: fail-closed guard inspects SOURCE_IMAGE revision label before docker tag, normalises <no value>, exit 1 on empty/mismatch
- deploy-hook: new --build-staging mode rebuilds staging image stamping GIT_SHA
- Dockerfile: ARG GIT_SHA + LABEL org.opencontainers.image.revision=$GIT_SHA

Closes TC07/TC08 (tests/test_deploy_hook_provenance.py).
2026-06-07 11:20:38 +03:00
10f2a39a58 feat(deploy): build-once SOURCE_IMAGE retag in hook + deploy-stage docs
Add the optional, backward-compatible SOURCE_IMAGE branch to
orchestrator-deploy-hook.sh: when set, retag the staging-validated image
onto TARGET_IMAGE (docker tag) before `up -d --no-build` instead of
rebuilding — guarantees prod runs the exact artefact that passed staging
(AC-7 / TC-14). Unset -> prior behaviour; exit-code contract (0/1/2) and
health-loop untouched.

Update golden-source docs (AC-13): rewrite deployer.md `deploy` stage from
"paper SUCCESS" to the executable self-deploy (Phase A/B/C, no self-restart
from inside the container) and add the ORCH-036 CHANGELOG entry.

Refs: ORCH-036

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 21:07:35 +00:00
28d019a1e2 fix(staging_check): B6 reads registry from running staging instance env
All checks were successful
CI / test (push) Successful in 12s
CI / test (pull_request) Successful in 16s
B6 false-FAILed because it built the project registry from the
launcher process-env via a host-path hack (sys.path.insert +
importlib.reload), not from the running staging instance. Run from the
host, ORCH_PROJECTS_JSON is unset -> default ET+ORCH registry -> false
FAIL -> spurious deploy-staging -> development rollback.

Variant (v) per ADR-001: remove the host-path hack; canonically run the
suite INSIDE orchestrator-staging via docker exec so src.projects
resolves from /app (PYTHONPATH) with .env.staging. Verdict logic
extracted into pure _evaluate_b6(known) -> (passed, detail) +
_known_project_ids_from_registry() / _run_b6() with deterministic FAIL on
source unavailability. deployer.md and STAGING_CHECK.md updated to the
docker exec command. src/projects.py, .env* and checks A/B4/B5/C
untouched.

Refs: ORCH-048

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-06 07:03:31 +00:00
Dev Agent
a6cbacb62c feat(staging): add orchestrator deploy hook with health-check and auto-rollback (ORCH-34)
All checks were successful
CI / test (push) Successful in 13s
CI / test (pull_request) Successful in 9s
2026-06-05 09:26:12 +03:00
Dev Agent
94334bdd42 feat(staging): add live staging check suite (smoke + access + e2e)
All checks were successful
CI / test (push) Successful in 10s
CI / test (pull_request) Successful in 10s
2026-06-05 08:54:56 +03:00