104 lines
8.1 KiB
Markdown
104 lines
8.1 KiB
Markdown
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-088 — Serial gate
|
||
|
||
Work Item: **ORCH-088** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
Формат: каждый критерий — чёткое условие **PASS/FAIL**. Критерий считается выполненным, если
|
||
описанная проверка даёт указанный результат. Нумерация AC-1…AC-6 соответствует BR; AC-7…AC-11 —
|
||
производные/защитные.
|
||
|
||
> Скоп — FR-1…FR-5 (serial e2e). Merge-очередь / pre-merge rebase / фазы A/B/C — вне приёмки.
|
||
|
||
---
|
||
|
||
## AC-1 — Gate закрыт при активной задаче
|
||
**Условие:** в репо `R` есть задача `A` со `stage != 'done'`. В очередь поступает новая задача `B`
|
||
того же репо.
|
||
- **PASS:** analyst-агент задачи `B` НЕ запускается; ветка `B` НЕ создаётся; `B` остаётся в ожидании
|
||
(`jobs.status='queued'` / не стартована). `GET /queue` показывает `B` как ожидающую.
|
||
- **FAIL:** analyst `B` стартовал, или ветка `B` создана, пока `A` не `done`.
|
||
|
||
## AC-2 — Автостарт следующей по достижении `done`
|
||
**Условие:** активная задача `A` репо `R` достигла `stage = 'done'` (после прод-деплоя). В очереди
|
||
ждёт `B`.
|
||
- **PASS:** `B` стартует анализ **автоматически** (без ручного действия) — claim analyst-job `B`
|
||
происходит на ближайшем цикле планировщика; ветка `B` создаётся в этот момент.
|
||
- **FAIL:** `B` не стартует после `A.stage='done'`, либо для старта требуется ручное вмешательство.
|
||
|
||
## AC-3 — Restart-safe (состояние в БД)
|
||
**Условие:** активна `A` (`stage<done`), `B` ждёт; оркестратор перезапускается.
|
||
- **PASS:** после рестарта gate по-прежнему закрыт (`B` не стартовала, `A` определяется из БД);
|
||
после `A.stage='done'` `B` стартует. Freeze (если был выставлен) сохраняется после рестарта.
|
||
- **FAIL:** после рестарта `B` стартовала при `A.stage<done`, или freeze «потерян».
|
||
|
||
## AC-4 — Per-repo параллелизм
|
||
**Условие:** активна задача в `orchestrator` (`stage<done`); в `enduro-trails` поступает новая задача.
|
||
- **PASS:** задача `enduro-trails` стартует анализ независимо (gate orchestrator её не держит) и
|
||
наоборот; gate/freeze одного репо не влияет на другой.
|
||
- **FAIL:** задача другого репо заблокирована состоянием gate/freeze чужого репо.
|
||
|
||
## AC-5 — Rollback-freeze + алерт
|
||
**Условие:** задача `A` репо `R` достигла `done`; во время post-deploy мониторинга вынесен вердикт
|
||
`DEGRADED` (self → `ALERT_ONLY`; non-self+auto_rollback → `ROLLBACK`).
|
||
- **PASS:** для `R` выставлен durable freeze (в БД); отправлен Telegram-алерт о заморозке; следующая
|
||
задача репо НЕ стартует, пока freeze не снят **вручную**; `GET /queue` показывает `frozen: true`.
|
||
После ручного снятия freeze следующая задача стартует.
|
||
- **FAIL:** следующая задача стартовала при активном freeze; либо freeze снялся автоматически; либо
|
||
алерт не отправлен.
|
||
|
||
## AC-6 — Нет stale-base (ветка от свежего `main`)
|
||
**Условие:** задачи `A` затем `B` одного репо проходят serial. `A` влита в `main` к моменту своего
|
||
`done`.
|
||
- **PASS:** ветка `B` срезана от `main`, **содержащего код `A`**: проверка
|
||
`git merge-base --is-ancestor <validated_sha задачи A> <branch B>` (или равноценная: HEAD `A` в
|
||
`main` — предок базы `B`) истинна. Branch `B` не создан раньше `A.stage='done'`.
|
||
- **FAIL:** база `B` не содержит коммитов `A` (ветка срезана до завершения `A`).
|
||
|
||
## AC-7 — Kill-switch / нулевая регрессия
|
||
**Условие:** `serial_gate_enabled = False` (или репо вне `serial_gate_repos`).
|
||
- **PASS:** claim и старт ведут себя строго как до ORCH-088 (gate инертен); тесты прежнего поведения
|
||
зелёные; enduro не затронут.
|
||
- **FAIL:** при выключенном флаге поведение отличается от исходного.
|
||
|
||
## AC-8 — never-raise / fail-open для claim
|
||
**Условие:** при вычислении gate происходит ошибка БД/логики в горячем пути claim.
|
||
- **PASS:** ошибка перехвачена и залогирована; claim НЕ падает; для claim — поведение fail-open
|
||
(очередь всех проектов не заклинивает). Конвейер enduro продолжает работать.
|
||
- **FAIL:** ошибка gate роняет claim/воркер или заклинивает очередь.
|
||
|
||
## AC-9 — fail-closed для freeze
|
||
**Условие:** при определении состояния freeze возникает сомнение/ошибка (например, не удалось
|
||
достоверно прочитать признак).
|
||
- **PASS:** в отношении freeze применяется консервативное (безопасное для прода) поведение — не
|
||
стартовать следующую при невозможности подтвердить отсутствие freeze (зафиксировать в ADR/коде).
|
||
- **FAIL:** при сомнении gate открывается и стартует следующую задачу.
|
||
|
||
## AC-10 — Наблюдаемость `GET /queue`
|
||
**Условие:** запрос `GET /queue` при активной задаче и/или freeze.
|
||
- **PASS:** ответ содержит аддитивный блок `serial_gate` с: `enabled`, областью, per-repo
|
||
`active_task`, списком `waiting`, `frozen`. Существующие ключи `/queue` не изменены.
|
||
- **FAIL:** блок отсутствует/ломает существующий контракт, либо данные не отражают реальное состояние.
|
||
|
||
## AC-11 — Инварианты неизменны
|
||
**Условие:** проверка контрактов после внедрения.
|
||
- **PASS:** `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, `check_*`, exit-коды deploy-хука, merge-gate,
|
||
merge-verify, image-freshness, post-deploy контракт — без изменений; миграции БД аддитивны и
|
||
идемпотентны; прод-контейнер не рестартится механизмом gate.
|
||
- **FAIL:** изменён любой перечисленный контракт, либо миграция не идемпотентна.
|
||
|
||
---
|
||
|
||
## Сводная матрица AC ↔ FR/BR
|
||
| AC | FR | BR | Тип проверки |
|
||
|----|----|----|--------------|
|
||
| AC-1 | FR-1 | BR-1 | unit (claim/gate) + integration |
|
||
| AC-2 | FR-1/2 | BR-2 | integration |
|
||
| AC-3 | FR-4 | BR-5 | integration (restart) |
|
||
| AC-4 | FR-3 | BR-4 | unit + integration |
|
||
| AC-5 | FR-5 | BR-6/7 | integration |
|
||
| AC-6 | FR-1 | BR-3 | integration (git base) |
|
||
| AC-7 | — | BR-8 | unit |
|
||
| AC-8 | — | NFR-1 | unit |
|
||
| AC-9 | FR-5 | NFR-1 | unit |
|
||
| AC-10 | — | BR-9 | unit (snapshot) |
|
||
| AC-11 | — | NFR-5 | unit (контракты) |
|