108 lines
8.2 KiB
Markdown
108 lines
8.2 KiB
Markdown
# 03-Критерии приёмки — ORCH-026
|
||
|
||
**Work Item:** ORCH-026 · **Repo:** orchestrator · **Стадия:** analysis
|
||
|
||
Каждый критерий — проверяемое условие PASS/FAIL. Маппинг на тесты — `04-test-plan.yaml`.
|
||
|
||
---
|
||
|
||
## Уровень A — Сериализация merge/деплоя внутри одного репо
|
||
|
||
### AC-A1 — Сериализация merge внутри репо
|
||
- **PASS:** пока задача A применимого репо удерживает окно merge (merge-lease не освобождён /
|
||
`main` ещё не обновлён), задача B того же репо НЕ доходит до фактического merge — она
|
||
**defer**-ится (повторная постановка через `available_at`), а не мержится от устаревшего `main`.
|
||
- **FAIL:** B мержится/деплоится, пока A не в `main`; или B откатывается на `development` вместо
|
||
defer.
|
||
|
||
### AC-A2 — Proactive pre-merge rebase
|
||
- **PASS:** перед merge ветка задачи **всегда** догоняется на свежий `origin/main` (вызывается
|
||
rebase), даже когда текстового конфликта нет и ветка формально не «behind» по старой проверке;
|
||
после rebase ветка содержит код предшественника (A).
|
||
- **FAIL:** rebase запускается только при конфликте/`branch_is_behind_main`, и B мержится без
|
||
кода A.
|
||
|
||
### AC-A3 — Кросс-репо параллелизм сохранён
|
||
- **PASS:** задача в `orchestrator` и задача в `enduro-trails` доходят до merge/деплоя
|
||
параллельно — сериализация одного репо не блокирует другой (lease/гейт строго per-repo).
|
||
- **FAIL:** задача одного репо ждёт освобождения ресурса, удерживаемого задачей ДРУГОГО репо.
|
||
|
||
### AC-A4 — Restart-safe
|
||
- **PASS:** после рестарта прод-контейнера состояние сериализации восстанавливается корректно;
|
||
мёртвый держатель merge-lease проактивно реклеймится (ORCH-065), конвейер не встаёт навсегда.
|
||
- **FAIL:** рестарт оставляет навсегда захваченный lease → конвейер всех проектов встаёт.
|
||
|
||
### AC-A5 — Self-hosting safety
|
||
- **PASS:** прод-контейнер orchestrator НЕ рестартится/не падает вне штатного `Confirm Deploy`
|
||
(ORCH-059); нет push/force-push в `main`; `STAGE_TRANSITIONS` и реестр `QG_CHECKS` не изменены.
|
||
- **FAIL:** любой незапрошенный рестарт прода, прямой push в `main`, или изменение машины стадий.
|
||
|
||
### AC-A6 — Anti-deadlock / anti-livelock при defer
|
||
- **PASS:** при занятой сериализации B defer-ится с задержкой и bounded бюджетом; исчерпание
|
||
бюджета → эскалация (alert/Blocked), не бесконечный цикл и не откат.
|
||
- **FAIL:** B уходит в вечный defer-цикл, либо немедленно откатывается на `development`.
|
||
|
||
### AC-A7 — Условность (не-self репо без регресса)
|
||
- **PASS:** при выключенном kill-switch и для репо вне scope поведение конвейера 1:1 как до
|
||
ORCH-026 (нулевая регрессия для enduro-trails).
|
||
- **FAIL:** не-self репо меняет поведение merge/деплоя.
|
||
|
||
---
|
||
|
||
## Уровень B — Декларативные зависимости
|
||
|
||
### AC-B1 — Декларация зависимости
|
||
- **PASS:** задача может объявить `blocked-by`/`depends-on` (через выбранный источник —
|
||
Plane relations / БД / гибрid), и связь корректно считывается планировщиком.
|
||
- **FAIL:** связь не считывается / теряется.
|
||
|
||
### AC-B2 — Гейт планировщика (B не стартует до A)
|
||
- **PASS:** задача с незавершённым depends-on **не клеймится** воркером (не запускается агент,
|
||
слот `max_concurrency` не занимается), пока все depends-on не достигли `done`; как только A
|
||
становится `done` — B становится claimable.
|
||
- **FAIL:** B запускается раньше завершения A; или занимает слот, простаивая.
|
||
|
||
### AC-B3 — Детект дедлоков (циклы)
|
||
- **PASS:** циклическая зависимость (A→B→A и длиннее) детектируется детерминированно; задача(и)
|
||
в цикле → `Blocked` + alert (Telegram/Plane) с указанием цикла; поток остальных задач не
|
||
блокируется.
|
||
- **FAIL:** цикл приводит к молчаливому вечному ожиданию или к падению воркера.
|
||
|
||
### AC-B4 — Видимость заблокированной задачи
|
||
- **PASS:** заблокированная задача видна — Plane-статус `Blocked` и/или строка ожидания в
|
||
Telegram-карточке (что/кого ждёт); инвариант «одна карточка на задачу» сохранён.
|
||
- **FAIL:** заблокированная задача невидима наблюдателю.
|
||
|
||
### AC-B5 — Совместимость с reconciler/reaper
|
||
- **PASS:** `reconciler` F-1 НЕ «разблокирует» задачу, заблокированную по зависимости (как уже
|
||
делает для Blocked/Needs-Input, ORCH-060/068); reaper не реапит корректно ожидающую задачу.
|
||
- **FAIL:** reconciler продвигает заблокированную задачу мимо её depends-on.
|
||
|
||
---
|
||
|
||
## Общие (оба уровня)
|
||
|
||
### AC-G1 — never-raise
|
||
- **PASS:** любая ошибка (git/сеть/БД/Plane) в новой логике не пробрасывается в `advance_stage`/
|
||
воркер; деградирует консервативно (defer/skip/fail-closed), конвейер не падает.
|
||
- **FAIL:** необработанное исключение роняет воркер/монитор-поток.
|
||
|
||
### AC-G2 — Kill-switch
|
||
- **PASS:** глобальный kill-switch выключает фичу целиком → поведение 1:1 как до ORCH-026.
|
||
- **FAIL:** при выключенном флаге поведение изменено.
|
||
|
||
### AC-G3 — Документация обновлена (golden source)
|
||
- **PASS:** в ТОМ ЖЕ PR обновлены `docs/architecture/README.md`, `CLAUDE.md` (если изменилось
|
||
поведение очереди), `CHANGELOG.md`, заведён ADR в `06-adr/`. Reviewer проверяет.
|
||
- **FAIL:** код изменён, документация — нет (→ REQUEST_CHANGES).
|
||
|
||
### AC-G4 — Миграция БД безопасна (если применимо)
|
||
- **PASS:** миграция только аддитивная (`CREATE TABLE IF NOT EXISTS`/`_ensure_column`),
|
||
идемпотентна, безопасна на живой общей прод-БД; существующие данные enduro-trails не затронуты.
|
||
- **FAIL:** деструктивная миграция / изменение существующих колонок.
|
||
|
||
### AC-G5 — Тесты зелёные
|
||
- **PASS:** новые unit+integration тесты (`04-test-plan.yaml`) проходят; существующий
|
||
`pytest tests/ -q` остаётся зелёным (нет регресса merge-gate/merge-verify/reconciler/reaper).
|
||
- **FAIL:** красный pytest или регресс существующих тестов.
|