architect(ET): auto-commit from architect run_id=436
All checks were successful
CI / test (push) Successful in 27s
All checks were successful
CI / test (push) Successful in 27s
This commit is contained in:
@@ -22,11 +22,12 @@ Per-work-item решения живут в `docs/work-items/<id>/06-adr/ADR-NNN-
|
||||
| adr-0014 | SHA-в-main — единственный критерий merge-verify + регресс-гард | accepted | 2026-06-08 | ORCH-073 |
|
||||
| adr-0015 | Зависимости задач (B ждёт A) + сериализация merge внутри репо | accepted | 2026-06-08 | ORCH-026 |
|
||||
| adr-0016 | ensure_open_pr — гарантированный код-PR перед merge-verify | accepted | 2026-06-09 | ORCH-082 |
|
||||
| adr-0017 | Per-repo serial gate (пакетный автономный режим, serial e2e) | proposed | 2026-06-09 | ORCH-088 |
|
||||
|
||||
> ⚠️ Историческая коллизия: номер `0007` занят двумя файлами —
|
||||
> `adr-0007-reconciler.md` (ORCH-053) и `adr-0007-executable-self-deploy.md`
|
||||
> (ORCH-036). Оба accepted; для новых сквозных ADR использовать следующий
|
||||
> свободный номер (текущий максимум — `0016`).
|
||||
> свободный номер (текущий максимум — `0017`).
|
||||
> adr-0014 **amends** adr-0013 (меняет критерий merge-verify на «SHA-в-main»).
|
||||
> adr-0016 **amends** adr-0013/0014 (гарантирует открытый код-PR перед merge_pr, ORCH-082).
|
||||
|
||||
|
||||
59
docs/architecture/adr/adr-0017-serial-gate.md
Normal file
59
docs/architecture/adr/adr-0017-serial-gate.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# adr-0017: Per-repo serial gate (пакетный автономный режим, serial e2e)
|
||||
|
||||
Статус: **proposed** · Дата: 2026-06-09 · Источник: **ORCH-088** (Этап 1)
|
||||
Детально: `docs/work-items/ORCH-088/06-adr/ADR-001-serial-gate.md`.
|
||||
|
||||
## Контекст
|
||||
Цель эпика ORCH-088 — масштаб автономности: накидать вечером 10–20 задач и получить к утру пакет,
|
||||
последовательно проведённый через весь конвейер (analysis → … → deploy → done). Корневая проблема —
|
||||
**stale-анализ**: ветка задачи N+1 срезается на входе в анализ (`start_pipeline._create_gitea_branch`)
|
||||
от `main`, ещё не содержащего код предшественника N. Физическое код-затирание уже закрыто (ORCH-026
|
||||
auto_rebase + merge-lease); остаётся **логический** разрыв. Plane API v1 не имеет bulk/relations ⇒
|
||||
очередь/зависимости хранятся у оркестратора (gate по локальной БД).
|
||||
|
||||
## Решение
|
||||
**Per-repo serial gate** — новая задача репо не входит в `analysis` (не режет ветку, не запускает
|
||||
analyst), пока в том же репо есть незавершённая задача (`stage != 'done'`) или репо заморожен.
|
||||
Три механизма, аддитивно, под kill-switch, с областью репо, never-raise, restart-safe:
|
||||
|
||||
1. **Gate-в-claim** (`db.claim_next_job`) — analyst-job (`jobs.agent='analyst'`) применимого репо не
|
||||
выбирается, если `EXISTS` другая незавершённая задача репо ИЛИ активна строка `repo_freeze`. По
|
||||
образцу `task_deps` `NOT EXISTS` (ORCH-026); только локальная БД (offline hot-path). Job'ы уже
|
||||
активной задачи проходят свободно; rework-analyst не блокирует себя (`t2.id != jobs.task_id`).
|
||||
2. **Отложенный срез ветки** — для применимого репо `start_pipeline` создаёт task-row + enqueue
|
||||
analyst, но **не** создаёт Gitea-ветку/docs; срез релоцируется на момент claim analyst-job
|
||||
(launcher), когда `origin/main` уже содержит предшественника (`done` ⇔ SHA-в-main, ORCH-071/073).
|
||||
`ensure_worktree` режет от свежего `origin/main` ⇒ AC-6 структурно. Идемпотентно (409 = no-op).
|
||||
3. **Durable per-repo freeze** (`repo_freeze`) — post-deploy `DEGRADED`/rollback (ORCH-021) →
|
||||
`set_repo_freeze` + Telegram-алерт; gate закрыт безусловно до **ручного** снятия
|
||||
(`POST /serial-gate/unfreeze`). Деградировавшая задача уже `done` (BR-7) ⇒ нужен отдельный сигнал.
|
||||
|
||||
Чистая логика — leaf `src/serial_gate.py` (never-raise). Флаги `serial_gate_enabled` (kill-switch),
|
||||
`serial_gate_repos` (CSV; **пусто ⇒ все репо**, в отличие от self-hosting-only ORCH-35/43/58),
|
||||
`serial_gate_freeze_enabled`. Наблюдаемость — блок `serial_gate` в `GET /queue`.
|
||||
|
||||
## Альтернативы
|
||||
- **Гейт в `start_pipeline` + re-trigger при `done`** — больше состояния/путей, риск зависших задач;
|
||||
relocation на claim переиспользует restart-safe `jobs`-очередь.
|
||||
- **Freeze как колонка `tasks`** — неверная семантика (freeze per-repo, задача уже `done`).
|
||||
- **Self-hosting-only область** — лишает enduro анти-stale-base (FR-3).
|
||||
- **Отдельная таблица очереди ожидания** — избыточно; `jobs(queued)`+gate достаточно.
|
||||
- **Снятие freeze Plane-жестом** — перегрузка статусов (анти-паттерн ORCH-059).
|
||||
|
||||
## Последствия
|
||||
- **+** AC-6 закрыт структурно; AC-2/AC-3 «бесплатны» (ожидание = `queued` job без ветки);
|
||||
переиспользование проверенных паттернов; cross-repo параллелизм сохранён; `STAGE_TRANSITIONS` /
|
||||
`QG_CHECKS` / `check_*` / merge-gate / merge-verify / image-freshness / post-deploy / deploy-хук /
|
||||
`max_concurrency` — **без изменений**.
|
||||
- **NFR-1:** hot-claim тотальный сбой → **fail-open** (не заклинить очередь всех проектов); freeze в
|
||||
Python-слое → **fail-closed** (безопасность прода).
|
||||
- **−** Срез ветки/docs мигрируют из async в sync-путь launcher (обёртка); Blocked-задача держит пакет
|
||||
(Этап 1, осознанно); freeze снимается только вручную.
|
||||
- Откат: `serial_gate_enabled=False` ⇒ claim/старт 1:1 как до ORCH-088; таблица `repo_freeze` инертна.
|
||||
- **Вне скопа** (Этап 1): merge-очередь FIFO, pre-merge rebase как отдельная фича, фазы A/B/C,
|
||||
любой параллелизм задач внутри одного репо, зависимость от ORCH-83.
|
||||
|
||||
## Связи
|
||||
- Переиспользует: adr-0002 (очередь ORCH-1), adr-0015 (claim-gate/auto_rebase/merge-lease ORCH-026),
|
||||
adr-0010 (post-deploy monitor — источник DEGRADED), adr-0013/0014 (merge-verify ⇒ `done`⇔SHA-в-main).
|
||||
- Новая аддитивная таблица `repo_freeze` (`docs/work-items/ORCH-088/08-data-requirements.md`).
|
||||
Reference in New Issue
Block a user