Files
orchestrator/docs/work-items/ORCH-112/01-brd.md

15 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used, escalate
work_item stage author_agent status created_at model_used escalate
ORCH-112 analysis analyst ready-for-review 2026-06-15 claude-opus-4-8 full-cycle

01 — BRD / Bug-report: ORCH-112 — failed/cancelled task artifacts must be cleaned from shared checkout

Work Item: ORCH-112 · Repo: orchestrator · Стадия: analysis · Трек: Bug → эскалация в full-cycle

⚠️ escalate: full-cycle (ADR-001 D5 ORCH-019). Баг помечен Bug, но по сути это архитектурный + safety-critical (self-hosting) дефект: правка лежит в самом опасном пути прод-деплоя (хост-хук, прямо перед рестартом прод-контейнера) и требует решения о политике жизненного цикла shared checkout (ADR). Поэтому выпускается полный analysis-пакет, а не облегчённый bug-пакет. Оператор снимает багфикс-трек: POST /bug-fast-track/escalate?work_item=ORCH-112 → задача пойдёт через стадию architecture (architect выпустит ADR для политики cleanup/изоляции).


1. Бизнес-контекст и проблема

Симптом (наблюдаемое)

Self-deploy задачи ORCH-111 упал на шаге git pull origin main хост-хука деплоя с ошибкой:

error: Your local changes to the following files would be overwritten by merge:
        src/config.py
Please commit your changes or stash them before you merge.

Деплой прерван, конвейер потребовал ручного вмешательства оператора (на self-hosting это групповой риск — встаёт деплой и всех других проектов).

Причина симптома (установленный факт)

В общем (shared) checkout /home/slin/repos/orchestrator оставались грязные файлы от ранее неуспешной/отменённой/перезапущенной задачи ORCH-104 (тема Lite installer):

  • модифицированный tracked-файл: src/config.py;
  • модифицированный/untracked: docs/deployment/LITE_SETUP.md;
  • untracked: scripts/install_lite.py, tests/test_install_lite.py, docs/deployment/lite-install.example.yaml.

Через несколько дней эти остатки заблокировали git pull другой задачи (ORCH-111).

Локализация (анализ — куда смотреть архитектору/разработчику)

Установленный факт о топологии (CLAUDE.md / docs/architecture/README.md): /home/slin/repos/orchestrator (хост) == /repos/orchestrator (контейнер, bind-mount) == main clone (settings.repos_dir/<repo> = settings.deploy_host_repo_path). Это deploy-база и база управления worktree'ами, а НЕ рабочая копия агента.

  1. Первичный дефект — нерезистентный git pull. scripts/orchestrator-deploy-hook.sh:224-226 делает cd "$REPO" (= deploy-база) и голый git pull origin main без гигиены рабочего дерева. Любая локальная правка tracked-файла блокирует merge → деплой падает. Проверено: во всём src/+scripts/ нет ни одного git reset --hard / git clean / git stash для приведения базы к чистому состоянию. Shared checkout трактуется как «всегда чистый», что не гарантировано.

  2. Невыполненный/неэнфорснутый инвариант + отсутствие «дворника». Нормальный конвейер не пишет в рабочее дерево main clone: агенты работают в изолированных worktree'ах /repos/_wt/<repo>/<branch> (git_worktree.ensure_worktree); docker build использует контекст worktree (image_freshness._host_worktree_path), не main clone; fallback'и гейтов на main clone — только чтение (git show origin/main:..., qg/checks.py:451, coverage_gate.py:297, stage_engine.py:145). Поэтому грязь ORCH-104 почти наверняка — ручной/брошенный WIP в shared checkout во время инцидента ORCH-104 (косвенное подтверждение: файлы install_lite.py/test_install_lite.py/lite-install.example.yaml никогда не существовали в git-истории — закоммиченный артефакт ORCH-104 это scripts/setup_lite.py, commit e2cf883). Вне зависимости от источника: нет механизма, который детектирует/чистит грязную базу и нет задокументированного/энфорснутого инварианта «main checkout — неизменяемая deploy-база, не workspace».

  3. cancel_task чистит worktree + remote-ветку, но НЕ shared checkout. stage_engine.cancel_task (шаг 3d, строки ~2330-2343): remove_worktree(repo, branch) + gitea.delete_remote_branch(repo, branch). Это корректно (конвейер в main clone не пишет), но означает нулевое покрытие случая «грязная deploy-база» в каскадах failed/cancelled.

Вывод: даже если первопричина грязи — ручное действие, устойчивость должна быть на стороне системы: deploy-база обязана самовосстанавливаться в чистый origin/main перед pull, а политика жизненного цикла — гарантировать, что остатки failed/cancelled задач не клинят будущие операции.

2. Объём (scope)

В объёме

  • Сделать self-deploy git pull origin main (shared deploy-база) устойчивым к грязному рабочему дереву — приведение базы к чистому origin/main автономно, без ручного вмешательства.
  • Гарантировать, что после failed / cancelled / брошенной задачи в shared checkout не остаётся рабочих остатков, способных заблокировать будущий деплой/операцию (сходимость базы к чистому origin/main).
  • Задокументировать (и где осуществимо — мягко энфорснуть/гардить) инвариант «shared main checkout — deploy/worktree-management база, НЕ редактируемый workspace».
  • Наблюдаемость: лог + Telegram-алерт, когда deploy-база найдена грязной и автоочищена (или отказ).

Вне объёма

  • Запрет/контроль ручных операций оператора в shared checkout (вне технической власти системы; закрываем устойчивостью, а не запретом).
  • Изменение модели worktree per-task (git_worktree, ORCH-2) — она корректна и не трогается.
  • Любое изменение STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict ключей / схемы БД.
  • Изменение поведения деплоя на чистой базе (happy-path должен остаться байт-в-байт).
  • Выбор конкретного механизма (reset --hard vs janitor vs guard) — это зона архитектора (ADR).

3. Заинтересованные стороны

  • Заказчик/оператор (Слава) — страдает от ручного разруливания залипших деплоев; принимает результат.
  • Self-hosting конвейер orchestrator — прямой потребитель (надёжность прод-деплоя).
  • Все проекты на общем инстансе (enduro-trails) — косвенно: залипший self-deploy орка останавливает обслуживание их задач.

4. Бизнес-требования (BR)

  • BR-1 — Грязное рабочее дерево shared deploy-базы (модифицированные tracked-файлы и/или untracked-файлы) НЕ должно блокировать self-deploy git pull origin main: деплой обязан привести базу к чистому, актуальному origin/main без ручного вмешательства.
  • BR-2 — После failed / cancelled / брошенной задачи в shared checkout не должно оставаться рабочих остатков этой задачи, способных заблокировать будущий деплой/git-операцию; база сходится к чистому origin/main.
  • BR-3 — Инвариант «shared main checkout (<host_repos_dir>/<repo>) — deploy/worktree-management база, НЕ workspace» должен быть задокументирован (docs/operations/INFRA.md + docs/architecture/README.md) и, где осуществимо, энфорснут/гардирован; конвейер/агенты никогда не пишут рабочие изменения в main clone (верифицировать, что это так).
  • BR-4Наблюдаемость: обнаружение грязной базы и факт автоочистки (или отказ) должны логироваться и алертиться (Telegram, кликабельный номер) — оператор видит, что гигиена сработала.
  • BR-5На чистой базе поведение деплоя — байт-в-байт прежнее (обычный fast-forward git pull); никакого регресса happy-path.

5. Нефункциональные требования (NFR)

  • NFR-1 (self-hosting safety) — гигиена никогда не трогает ветку main на remote, не делает force-push, не рестартит прод-контейнер вне штатного гейта, не удаляет worktree/ветки других активных задач. Оперирует только настроенным путём deploy-базы.
  • NFR-2 (сохранность deploy-состояния) — автоочистка не должна удалять артефакты, легитимно живущие под $REPO/рядом: rollback-снимки $REPO/.deploy-prev-image-* (deploy_prod_prev_image_file), deploy-hook.log, sibling-состояния <repos_dir>/.deploy-state-* / .merge-lease-*.json, и админ-записи worktree в .git/worktrees. (Наивный git clean -xfd в $REPO уничтожил бы .deploy-prev-image-* и сломал rollback — это жёсткое ограничение для архитектора/разработчика.)
  • NFR-3 (обратимость / kill-switch) — новое поведение под флагом; выключенный флаг → деплой байт-в-байт как до ORCH-112 (голый git pull origin main).
  • NFR-4 (надёжность) — never-raise / fail-safe (по образцу leaf'ов serial_gate/cancel); идемпотентность; restart-safe; сбой гигиены не должен маскировать или ухудшать исход деплоя сверх текущего.
  • NFR-5 (нулевая регрессия конвейера)STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict ключи / схема БД / exit-code-контракт хука (0/1/2, ORCH-036) — байт-в-байт.
  • NFR-6 (область) — изменение скоупится на self-hosting (orchestrator); поведение для прочих репо/синхронного деплоя агентом — не ухудшается.

6. Допущения и ограничения

  • Shared checkout и хост-хук физически разделяют один путь с контейнером через bind-mount (repos_dirhost_repos_dir); хук исполняется на хосте по ssh (ORCH-036, detached).
  • Build-once путь (SOURCE_IMAGE retag) не зависит от содержимого рабочего дерева main clone — прод получает ровно staging-валидированный образ; значит дискард рабочего дерева base перед pull безопасен для деплоимого артефакта. (--build-staging собирается из worktree, не из main — отдельный контур.)
  • Источник истины кода — origin/main; локальные правки в deploy-базе по определению не должны существовать (это deploy-база, а не место работы).
  • Конкретный механизм (resilient pull через reset+clean со скоуп-исключениями / активный janitor / guard инварианта / комбинация) — открытый вопрос для архитектуры, решается в 06-adr/.

7. Критерии успеха

Self-deploy успешно выполняет git pull на ранее грязной shared-базе без ручного вмешательства; deploy-база сходится к чистому origin/main; rollback-состояние и sibling-артефакты сохранены; happy-path и весь конвейер — без регресса; обязательный регресс-тест красный до фикса, зелёный после. Детальные PASS/FAIL — 03-acceptance-criteria.md.

8. Риски

  • Деструктивная гигиена (reset --hard/clean) в прод-deploy-базе рядом с рестартом прода — ошибка скоупа может удалить rollback-state/логи (см. NFR-2) → ADR обязателен.
  • Маскировка реальной первопричины: если в будущем какой-то код начнёт писать в main clone, «тихая автоочистка» это скроет → нужна наблюдаемость (BR-4).
  • Кросс-каттинг с ORCH-036 (self-deploy), ORCH-058 (image-freshness/provenance), ORCH-090 (cancel), ORCH-2 (worktree-модель). Детали/митигации — 10-tech-risks.md (заполняет архитектор).