---
work_item: ORCH-112
stage: architecture
author_agent: architect
status: proposed
created_at: 2026-06-15
model_used: claude-opus-4-8
---

# adr-0044: Гигиена shared deploy-базы — устойчивый self-deploy `git pull`

Сквозное (cross-cutting) решение. Детальный per-work-item ADR —
`docs/work-items/ORCH-112/06-adr/ADR-001-deploy-base-checkout-hygiene.md`.

## Статус
Proposed (ORCH-112)

## Контекст (сквозной)

Глобальный путь прод-деплоя self-hosting (`deploy`-стадия, ORCH-036) исполняет хост-хук
`scripts/orchestrator-deploy-hook.sh`, чей шаг «2. Pull latest code» — **голый** `git pull origin main`
в shared main clone (`settings.deploy_host_repo_path`). Любая грязь рабочего дерева (модифицированный
tracked-файл и/или untracked-остатки failed/cancelled/брошенной задачи) **блокирует** merge → деплой
встаёт → ручное вмешательство. На self-hosting (один прод-инстанс на все проекты с общей БД/очередью)
это **групповой риск**: залипший self-deploy орка останавливает обслуживание всех проектов
(инцидент ORCH-111, грязь от ORCH-104).

## Решение (сквозное)

Вводится **resilient-pull, встроенный в прод-deploy-хук** (`--deploy`), + новый чистый never-raise
leaf-компонент `src/checkout_hygiene.py`:

- **Хук** перед `git pull origin main` приводит грязную deploy-базу к чистому актуальному `origin/main`
  (`git fetch` + `git reset --hard origin/main` + **скоупленный** `git clean -fd`), **строго сохраняя**
  rollback/лог-артефакты. Гейт — env `CHECKOUT_HYGIENE`, инжектится `self_deploy.build_deploy_command`.
- **Leaf** `checkout_hygiene` решает условность (`applies(repo)`: kill-switch `checkout_hygiene_enabled`
  + скоуп `checkout_hygiene_repos`, пусто → self-hosting only), строит env-префикс, читает sentinel
  отчёта, шлёт Telegram-алерт. Образец `serial_gate`/`cancel`/`self_deploy`.
- **Сходимость** базы после failed/cancelled (FR-2) — этим же deploy-time self-heal; `cancel_task`
  (ORCH-090) **не расширяется**, фоновый janitor **не вводится**.
- **Наблюдаемость** — хук пишет sentinel `hygiene`, Phase-C finalizer читает и шлёт Telegram-алерт
  (best-effort, never-raise).
- **Инвариант** «main checkout — deploy/worktree-management база, НЕ workspace» документируется
  (INFRA.md + architecture/README.md); de-facto энфорс — сам resilient-pull.

## Кросс-каттинг-инварианты (обязательны к соблюдению будущими задачами)

- **INV-HYGIENE-1 (никогда `-x`):** hygiene-`git clean` — только `git clean -fd`. `-x` удалил бы
  gitignored `.env` (прод-секреты) / `data/*.db` (БД прода) / `build/`. Анти-регресс — статический тест.
- **INV-HYGIENE-2 (явные excludes):** `.deploy-prev-image-*` (rollback, `deploy_prod_prev_image_file`)
  и `deploy-hook.log` — untracked-но-НЕ-ignored → обязательны `-e`-исключения; их удаление сломало бы
  rollback.
- **INV-HYGIENE-3 (скоуп = `$REPO`):** гигиена оперирует только рабочим деревом deploy-базы;
  sibling `<repos_dir>/.deploy-state-*` / `.merge-lease-*.json` и `.git/worktrees/*` — вне области.
- **Self-hosting safety (NFR-1):** никогда не трогать `main` на remote, не force-push, не рестартить
  прод вне штатного гейта, не сносить worktree/ветки других активных задач.
- **Нулевая регрессия (NFR-5):** `STAGE_TRANSITIONS` / реестр `QG_CHECKS` / семантика и имена `check_*` /
  machine-verdict ключи / схема БД / exit-code-контракт хука (0/1/2, ORCH-036) — байт-в-байт. Это
  устойчивость deploy-пути, **не** Quality Gate и **не** стадия.

## Связи
- Дополняет: adr-0007 (executable self-deploy, ORCH-036), adr-0008 (image-freshness, ORCH-058).
- Не нарушает: adr-0026 (STOP/cancel, ORCH-090) — каскад cancel не трогается.

## Откат
`ORCH_CHECKOUT_HYGIENE_ENABLED=false` → прод-деплой байт-в-байт до ORCH-112 (голый `git pull origin main`).
