analyst(ET): auto-commit from analyst run_id=701
This commit is contained in:
169
docs/work-items/ORCH-112/01-brd.md
Normal file
169
docs/work-items/ORCH-112/01-brd.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
work_item: ORCH-112
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-15
|
||||
model_used: claude-opus-4-8
|
||||
escalate: 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_dir`↔`host_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` (заполняет архитектор).
|
||||
110
docs/work-items/ORCH-112/02-trz.md
Normal file
110
docs/work-items/ORCH-112/02-trz.md
Normal file
@@ -0,0 +1,110 @@
|
||||
---
|
||||
work_item: ORCH-112
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-15
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 02 — ТЗ (TRZ): ORCH-112 — failed/cancelled task artifacts must be cleaned from shared checkout
|
||||
|
||||
Work Item: **ORCH-112** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
> ТЗ описывает **требования и ограничения к реализации**, выведенные из BRD и фактического кода.
|
||||
> Архитектурное **решение** (какой механизм гигиены/изоляции выбрать) — задача архитектора (`06-adr/`),
|
||||
> т.к. задача эскалирована в full-cycle (`01-brd.md` → `escalate: full-cycle`).
|
||||
|
||||
## 1. Сводка изменения
|
||||
Сделать self-deploy устойчивым к **грязной shared deploy-базе** и гарантировать сходимость базы к
|
||||
чистому `origin/main` после failed/cancelled/брошенных задач. Корень симптома — голый
|
||||
`git pull origin main` в `scripts/orchestrator-deploy-hook.sh` (строка 226), исполняемый в
|
||||
`$REPO` (= `settings.deploy_host_repo_path` = main clone), который падает при любой локальной правке
|
||||
tracked-файла. Требуется: (а) приведение deploy-базы к чистому `origin/main` перед/в момент pull
|
||||
**без ручного вмешательства**, со строгим сохранением deploy-rollback-состояния; (б) документирование
|
||||
+ (по возможности) энфорс инварианта «main checkout — deploy-база, не workspace»; (в) наблюдаемость.
|
||||
|
||||
## 2. Задействованные модули / пути
|
||||
| Путь | Действие | Примечание |
|
||||
|------|----------|-----------|
|
||||
| `scripts/orchestrator-deploy-hook.sh` | изменить | строки 224-226: голый `git pull origin main` в `$REPO` — точка отказа (FR-1) |
|
||||
| `src/self_deploy.py` | возможно изменить | `build_deploy_command` / `initiate_deploy` / `rebuild_staging_image` строят инвокацию хука — возможная точка передачи гигиены/флага (решает архитектор) |
|
||||
| `src/stage_engine.py` | возможно изменить | `cancel_task` (шаг 3d, ~2330-2343) — каскад cancel; расширение гигиены на shared-базу (FR-2, если выбран этот путь) |
|
||||
| `src/git_worktree.py` | возможно изменить | модель main clone ↔ worktree; возможный helper приведения базы к чистоте / верификация инварианта (BR-3) |
|
||||
| `src/config.py` | изменить | новый kill-switch + флаги области (FR-5) |
|
||||
| `src/<new_leaf>.py` (напр. `checkout_hygiene.py`) | возможно создать | чистый never-raise leaf политики гигиены (по образцу `serial_gate`/`cancel`) — **создавать ли** решает архитектор |
|
||||
| `docs/operations/INFRA.md` | изменить | инвариант «shared checkout — deploy-база, не workspace» (BR-3) |
|
||||
| `docs/architecture/README.md` | изменить | описать политику гигиены/жизненного цикла deploy-базы |
|
||||
| `CHANGELOG.md`, `CLAUDE.md` | изменить | правило «docs = golden source» (CLAUDE.md §2) |
|
||||
| `tests/test_<...>.py` | создать | регресс + покрытие (см. `04-test-plan.yaml`) |
|
||||
|
||||
## 3. Функциональные требования
|
||||
|
||||
### FR-1 — Устойчивый self-deploy `git pull` (BR-1, BR-5)
|
||||
- На пути self-deploy (`scripts/orchestrator-deploy-hook.sh`, шаг «2. Pull latest code»)
|
||||
`git pull origin main` **не должен падать** из-за грязного рабочего дерева `$REPO`.
|
||||
- Перед обновлением база приводится к чистому, актуальному `origin/main` (приведение tracked- и
|
||||
untracked-изменений к состоянию `origin/main`), **с сохранением** артефактов из NFR-2.
|
||||
- На **уже чистой** базе результат — обычный fast-forward; наблюдаемое поведение и exit-коды
|
||||
(0/1/2, ORCH-036) — **байт-в-байт прежние** (BR-5).
|
||||
- Контракт: never-break — сбой шага гигиены не должен ухудшать исход относительно текущего голого
|
||||
pull (fail-safe).
|
||||
|
||||
### FR-2 — Сходимость shared-базы после failed/cancelled/брошенной задачи (BR-2)
|
||||
- После терминации задачи (`failed` job-исход / `cancelled` через STOP / брошенный WIP) в shared
|
||||
checkout **не остаётся** рабочих остатков, способных заблокировать будущий деплой/git-операцию.
|
||||
- Допустимая трактовка «сходимости» (на выбор архитектора, **не** прескриптивно здесь): автоочистка
|
||||
непосредственно в self-deploy перед pull (FR-1) **и/или** активный «дворник», приводящий
|
||||
`<host_repos_dir>/<repo>` к чистому `origin/main`.
|
||||
- Каскад `cancel_task` (ORCH-090) уже чистит **worktree + remote-ветку**; расширение на shared-базу
|
||||
(если выбрано) делается тем же never-raise best-effort способом.
|
||||
|
||||
### FR-3 — Инвариант deploy-базы (BR-3)
|
||||
- Задокументировать: `<host_repos_dir>/<repo>` — deploy/worktree-management база; рабочие изменения
|
||||
туда **не пишутся** конвейером/агентами (агенты — worktree `git_worktree`; build — worktree-контекст;
|
||||
fallback'и гейтов — read-only `git show origin/main`).
|
||||
- Верифицировать, что текущий код этот инвариант соблюдает (анализ ORCH-112: соблюдает; единственные
|
||||
обращения к main clone — read-only/fetch/worktree-управление). Где осуществимо — добавить
|
||||
лёгкий guard/проверку (решает архитектор), **без** изменения горячих путей.
|
||||
|
||||
### FR-4 — Наблюдаемость (BR-4)
|
||||
- Обнаружение грязной deploy-базы и факт автоочистки (число/имена сброшенных путей) или **отказ**
|
||||
гигиены — лог (структурная запись) + Telegram-алерт (`send_telegram`, кликабельный номер задачи,
|
||||
best-effort, never-raise). Опционально — read-only снапшот в `GET /queue` (решает архитектор).
|
||||
|
||||
### FR-5 — Условность / kill-switch (BR-5, NFR-3, NFR-6)
|
||||
- Новое поведение под **kill-switch** (env `ORCH_*`, по образцу `serial_gate_enabled`/`stop_status_enabled`);
|
||||
выключенный флаг → деплой байт-в-байт прежний (голый `git pull origin main`).
|
||||
- Область — self-hosting (`orchestrator`); прочие репо/синхронный деплой агентом — не ухудшаются.
|
||||
- `applies(repo)` (локальный, без сети) проверяется первым.
|
||||
|
||||
## 4. Изменения API
|
||||
**Нет** обязательных. Опционально (на усмотрение архитектора) — read-only блок (напр. `checkout_hygiene`)
|
||||
в существующем `GET /queue` для наблюдаемости. Новых управляющих эндпоинтов не требуется.
|
||||
|
||||
## 5. Изменения схемы БД
|
||||
**Нет.** Состояние гигиены, если нужно, — in-memory / sentinel-файлы (паттерн `self_deploy`/`merge_gate`),
|
||||
без миграции БД. Аддитивная таблица не требуется.
|
||||
|
||||
## 6. Требования к новым/изменённым QG checks
|
||||
**Нет.** Это **не** Quality Gate и не стадия — это устойчивость deploy-пути и политика гигиены.
|
||||
`STAGE_TRANSITIONS` / реестр `QG_CHECKS` / семантика и имена `check_*` / machine-verdict ключи
|
||||
(`deploy_status:`/`staging_status:`/…) — **байт-в-байт не тронуты** (NFR-5).
|
||||
|
||||
## 7. Совместимость / регресс
|
||||
- **Обратная совместимость:** kill-switch off → голый `git pull origin main` (1:1 до ORCH-112);
|
||||
чистая база → fast-forward без изменений (BR-5).
|
||||
- **Область раската:** self-hosting `orchestrator`; enduro/прочие — нулевая регрессия.
|
||||
- **Обратимость:** выключение флага мгновенно возвращает прежнее поведение.
|
||||
- **Сохранность (жёсткое ограничение, NFR-2):** гигиена **не удаляет** `$REPO/.deploy-prev-image-*`
|
||||
(rollback), `deploy-hook.log`, sibling `<repos_dir>/.deploy-state-*` / `.merge-lease-*.json`,
|
||||
админ-записи `.git/worktrees`. Любой `clean`-скоуп обязан их исключать.
|
||||
- **Self-hosting инварианты (NFR-1):** никогда не трогать `main` на remote, не force-push, не
|
||||
рестартить прод вне гейта, не сносить worktree/ветки других активных задач, оперировать только
|
||||
настроенным путём deploy-базы. Exit-code-контракт хука (0/1/2) сохранён.
|
||||
- **Артефакты pipeline:** создаются/обновляются обычные docs work item (`01..04` этой задачи,
|
||||
`06-adr/` на стадии architecture после эскалации, `14-deploy-log.md` при деплое). Новых
|
||||
pipeline-артефактов задача не вводит.
|
||||
- **Трассировка (CLAUDE.md §9 / ORCH-078):** правки маркированных блоков (ORCH-036 self-deploy,
|
||||
ORCH-058 image-freshness, ORCH-090 cancel) — сверять с их `06-adr/` перед изменением, инварианты
|
||||
не ломать.
|
||||
128
docs/work-items/ORCH-112/03-acceptance-criteria.md
Normal file
128
docs/work-items/ORCH-112/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,128 @@
|
||||
---
|
||||
work_item: ORCH-112
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-15
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-112 — failed/cancelled task artifacts must be cleaned from shared checkout
|
||||
|
||||
Work Item: **ORCH-112** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
|
||||
(что считается провалом). Reviewer/CI проверяют их буквально по файлам репозитория и тестам.
|
||||
|
||||
---
|
||||
|
||||
## AC-1 — Грязная tracked-правка не блокирует self-deploy pull (регресс ORCH-104/ORCH-111)
|
||||
|
||||
**Условие:** shared deploy-база имеет локальную модификацию tracked-файла (напр. `src/config.py`),
|
||||
self-deploy выполняет шаг pull.
|
||||
- **PASS:** база приводится к чистому актуальному `origin/main` без ручного вмешательства; шаг pull
|
||||
не возвращает «local changes would be overwritten by merge»; деплой продолжается; есть тест,
|
||||
воспроизводящий точный сценарий ORCH-111 (**красный до фикса, зелёный после**).
|
||||
- **FAIL:** pull/деплой падает на грязной tracked-правке; или сценарий не покрыт тестом.
|
||||
|
||||
---
|
||||
|
||||
## AC-2 — Untracked WIP-файлы не блокируют и не «протекают» в деплой
|
||||
|
||||
**Условие:** в shared-базе лежат untracked-файлы failed/брошенной задачи (напр.
|
||||
`scripts/install_lite.py`, `tests/test_install_lite.py`, `docs/deployment/lite-install.example.yaml`).
|
||||
- **PASS:** база сходится к чистому `origin/main`; untracked-остатки не блокируют операцию и не
|
||||
попадают в деплоимый/собираемый артефакт.
|
||||
- **FAIL:** untracked-остатки блокируют операцию либо остаются и клинят будущий деплой.
|
||||
|
||||
---
|
||||
|
||||
## AC-3 — Сохранность deploy-rollback-состояния и sibling-артефактов (жёсткое ограничение)
|
||||
|
||||
**Условие:** в `$REPO`/рядом присутствуют `.deploy-prev-image-*` (rollback), `deploy-hook.log`,
|
||||
`<repos_dir>/.deploy-state-*`, `.merge-lease-*.json`, `.git/worktrees/*`.
|
||||
- **PASS:** после гигиены **все** перечисленные артефакты на месте; rollback по
|
||||
`.deploy-prev-image-*` остаётся работоспособным; есть тест, доказывающий их неудаление.
|
||||
- **FAIL:** гигиена удаляет хотя бы один из этих артефактов (особенно `.deploy-prev-image-*`).
|
||||
|
||||
---
|
||||
|
||||
## AC-4 — Happy-path без регресса (чистая база)
|
||||
|
||||
**Условие:** shared-база чистая, self-deploy выполняет pull.
|
||||
- **PASS:** поведение и exit-коды (0/1/2, ORCH-036) — байт-в-байт прежние (обычный fast-forward);
|
||||
полный `pytest tests/ -q` зелёный.
|
||||
- **FAIL:** изменилось наблюдаемое поведение/exit-код на чистой базе, либо красный регресс.
|
||||
|
||||
---
|
||||
|
||||
## AC-5 — Self-hosting safety
|
||||
|
||||
**Условие:** исполнение пути гигиены/деплоя.
|
||||
- **PASS:** нет операций над веткой `main` на remote, нет force-push, нет рестарта прод-контейнера
|
||||
вне штатного гейта, нет удаления worktree/веток других активных задач; операции строго в пределах
|
||||
настроенного пути deploy-базы; тест/анализ это подтверждает.
|
||||
- **FAIL:** любое из перечисленных нарушений присутствует или возможно.
|
||||
|
||||
---
|
||||
|
||||
## AC-6 — Kill-switch и обратимость
|
||||
|
||||
**Условие:** новый флаг выключен.
|
||||
- **PASS:** деплой ведёт себя байт-в-байт как до ORCH-112 (голый `git pull origin main`); включение
|
||||
флага активирует устойчивое поведение; область скоупится на self-hosting (прочие репо не затронуты).
|
||||
- **FAIL:** выключенный флаг меняет поведение, либо нет kill-switch, либо затронуты прочие репо.
|
||||
|
||||
---
|
||||
|
||||
## AC-7 — Сходимость после cancel/failed
|
||||
|
||||
**Условие:** задача отменена (STOP/ORCH-090) или job завершился `failed`, оставив остатки в
|
||||
рабочем дереве deploy-базы.
|
||||
- **PASS:** shared-база сходится к чистому `origin/main` (через автоочистку в деплое и/или дворник),
|
||||
и последующий self-deploy проходит без ручного вмешательства; покрыто интеграционным тестом.
|
||||
- **FAIL:** остатки сохраняются и блокируют последующий деплой/git-операцию.
|
||||
|
||||
---
|
||||
|
||||
## AC-8 — Наблюдаемость
|
||||
|
||||
**Условие:** обнаружена грязная deploy-база.
|
||||
- **PASS:** факт обнаружения и автоочистки (или отказ) — в логах (структурно) и в Telegram-алерте
|
||||
(кликабельный номер); алерт best-effort, never-raise (его сбой не валит деплой).
|
||||
- **FAIL:** тихая очистка без следа в логах/уведомлениях, либо сбой алерта роняет деплой.
|
||||
|
||||
---
|
||||
|
||||
## AC-9 — Инвариант конвейера и БД не тронуты
|
||||
|
||||
**Условие:** диф задачи.
|
||||
- **PASS:** `STAGE_TRANSITIONS` / реестр `QG_CHECKS` / семантика и имена `check_*` / machine-verdict
|
||||
ключи / схема БД / exit-code-контракт хука — байт-в-байт; структурные тесты конвейера зелёные.
|
||||
- **FAIL:** любой из перечисленных контрактов изменён.
|
||||
|
||||
---
|
||||
|
||||
## AC-10 — Документация (golden source)
|
||||
|
||||
**Условие:** изменён функционал deploy-базы/гигиены.
|
||||
- **PASS:** обновлены `docs/operations/INFRA.md` (инвариант deploy-база ≠ workspace) и
|
||||
`docs/architecture/README.md`; `CHANGELOG.md`/`CLAUDE.md` отражают изменение; ADR заведён на
|
||||
стадии `architecture` (после эскалации `escalate: full-cycle`).
|
||||
- **FAIL:** функционал изменён, доки/ADR не обновлены (reviewer → finding ≥P1, CLAUDE.md §6).
|
||||
|
||||
---
|
||||
|
||||
## Сводная матрица AC ↔ FR/BR
|
||||
| AC | Покрывает |
|
||||
|----|-----------|
|
||||
| AC-1 | BR-1 / FR-1 |
|
||||
| AC-2 | BR-1, BR-2 / FR-1, FR-2 |
|
||||
| AC-3 | NFR-2 / FR-1 (ограничение) |
|
||||
| AC-4 | BR-5 / FR-1 |
|
||||
| AC-5 | NFR-1 / FR-1, FR-2 |
|
||||
| AC-6 | NFR-3, NFR-6 / FR-5 |
|
||||
| AC-7 | BR-2 / FR-2 |
|
||||
| AC-8 | BR-4 / FR-4 |
|
||||
| AC-9 | NFR-5 / FR-1…FR-5 |
|
||||
| AC-10 | BR-3 / FR-3 |
|
||||
83
docs/work-items/ORCH-112/04-test-plan.yaml
Normal file
83
docs/work-items/ORCH-112/04-test-plan.yaml
Normal file
@@ -0,0 +1,83 @@
|
||||
work_item: ORCH-112
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-15
|
||||
model_used: claude-opus-4-8
|
||||
title: "Гигиена shared deploy-базы: устойчивость self-deploy git pull к грязному дереву"
|
||||
framework: pytest
|
||||
scope: >
|
||||
Покрывается: устойчивость self-deploy `git pull origin main` к грязной shared deploy-базе
|
||||
(модифицированные tracked + untracked файлы), сходимость базы к чистому origin/main после
|
||||
failed/cancelled задач, сохранность deploy-rollback-состояния, kill-switch/область, наблюдаемость,
|
||||
self-hosting safety. Вне покрытия: модель worktree per-task (ORCH-2, не трогается), запрет ручных
|
||||
операций оператора, изменения STAGE_TRANSITIONS/QG_CHECKS/схемы БД (их нет).
|
||||
notes: >
|
||||
TC-01 — ОБЯЗАТЕЛЬНЫЙ регресс-тест воспроизведения инцидента ORCH-111: КРАСНЫЙ до фикса, ЗЕЛЁНЫЙ
|
||||
после. Шелл-симуляции хука моделировать по образцу tests/test_deploy_hook_rollback_sim.py
|
||||
(временный git-репо во временной директории, без сети/прода/ssh). Полный регресс `pytest tests/ -q`
|
||||
обязан оставаться зелёным (NFR-5). Точные имена тест-модулей/функций уточнит разработчик; тип
|
||||
гигиены (resilient-pull / janitor / guard) выберет архитектор — тесты сформулированы так, чтобы
|
||||
проверять ТРЕБУЕМЫЙ ИНВАРИАНТ (база сходится к чистому origin/main, артефакты сохранены), а не
|
||||
конкретный механизм.
|
||||
|
||||
tests:
|
||||
- id: TC-01
|
||||
type: integration
|
||||
description: "РЕГРЕСС (обязательный, red→green): shared deploy-база с локальной модификацией tracked-файла src/config.py + untracked файлами — симуляция шага git pull хука приводит базу к чистому origin/main и НЕ падает с 'local changes would be overwritten by merge' (воспроизводит ORCH-111; красный до фикса)."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: integration
|
||||
description: "Untracked WIP-файлы (install_lite.py / test_install_lite.py / lite-install.example.yaml) в shared-базе не блокируют операцию и база сходится к чистому origin/main."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: integration
|
||||
description: "Сохранность (NFR-2): после гигиены файлы $REPO/.deploy-prev-image-* , deploy-hook.log, sibling .deploy-state-* / .merge-lease-*.json и .git/worktrees/* НЕ удалены; rollback по .deploy-prev-image-* остаётся работоспособным."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: integration
|
||||
description: "Happy-path без регресса: на ЧИСТОЙ shared-базе шаг pull — обычный fast-forward; наблюдаемое поведение и exit-коды (0/1/2, ORCH-036) байт-в-байт прежние."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: "Self-hosting safety: путь гигиены никогда не оперирует веткой main на remote, не делает force-push, не рестартит прод и не сносит worktree/ветки других задач; операции ограничены настроенным путём deploy-базы (статический/поведенческий ассерт)."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: "Kill-switch off → деплой/pull байт-в-байт прежний (голый git pull origin main); on → активна устойчивая гигиена. Область applies(repo): self-hosting orchestrator real, прочие репо — no-op."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-07
|
||||
type: integration
|
||||
description: "Сходимость после cancel/failed: cancel_task (ORCH-090) / failed-исход не оставляет рабочих остатков в shared-базе, блокирующих будущий деплой; последующий self-deploy проходит без ручного вмешательства."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-08
|
||||
type: unit
|
||||
description: "Наблюдаемость: обнаружение грязной базы и факт автоочистки (или отказ) попадают в лог; Telegram-алерт best-effort/never-raise (его сбой не валит деплой), номер задачи кликабельный."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-09
|
||||
type: unit
|
||||
description: "Инвариант конвейера: STAGE_TRANSITIONS / реестр QG_CHECKS / имена и семантика check_* / machine-verdict ключи / exit-code-контракт хука — не изменены (структурный анти-регресс)."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-10
|
||||
type: unit
|
||||
description: "Документация-инвариант: docs/operations/INFRA.md и docs/architecture/README.md содержат правило «shared main checkout — deploy/worktree-management база, не workspace» (структурная сверка)."
|
||||
module: tests/test_deploy_checkout_hygiene.py
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user