106 lines
8.1 KiB
Markdown
106 lines
8.1 KiB
Markdown
# 03 — Критерии приёмки (Acceptance Criteria)
|
||
|
||
**Work Item:** ORCH-043 — merge-gate + auto-rebase + re-test
|
||
**Автор:** Analyst
|
||
|
||
Каждый критерий имеет однозначное условие PASS/FAIL. Все критерии должны быть PASS.
|
||
|
||
---
|
||
|
||
## AC-1 — Ветка актуальна: гейт пропускает без догона
|
||
- **Дано:** ветка содержит последний `origin/main` (не отстаёт).
|
||
- **Когда:** выполняется `check_branch_mergeable(repo, work_item_id, branch)`.
|
||
- **PASS:** возвращает `(True, ...)` с причиной «up-to-date», auto-rebase НЕ запускается,
|
||
ветка не пушится повторно.
|
||
- **FAIL:** возвращает `False`, либо выполняет ненужный rebase/push.
|
||
|
||
## AC-2 — Ветка отстаёт + чистый догон + зелёный re-test → проход
|
||
- **Дано:** ветка отстаёт от `origin/main`; rebase проходит без текстового конфликта;
|
||
тест-набор на догнанной ветке зелёный.
|
||
- **Когда:** выполняется merge-gate.
|
||
- **PASS:** ветка догнана до `origin/main`, запушена `--force-with-lease`, re-test зелёный,
|
||
гейт возвращает `(True, ...)`.
|
||
- **FAIL:** гейт возвращает `False` при чистом догоне и зелёном re-test, либо `main` тронут,
|
||
либо push выполнен НЕ через `--force-with-lease`.
|
||
|
||
## AC-3 — Текстовый конфликт rebase → откат на development, без слияния
|
||
- **Дано:** auto-rebase упирается в текстовый конфликт.
|
||
- **Когда:** выполняется merge-gate.
|
||
- **PASS:** rebase отменён (worktree чист), гейт возвращает `(False, "rebase conflict...")`,
|
||
задача переведена на `development`, в Plane — комментарий с причиной, слияния в `main` нет.
|
||
- **FAIL:** ветка осталась в конфликтном состоянии, или задача продвинулась к слиянию,
|
||
или `main` изменён.
|
||
|
||
## AC-4 — Красный re-test после догона → откат на development, без слияния
|
||
- **Дано:** rebase чистый, но тесты на догнанной ветке падают.
|
||
- **Когда:** выполняется merge-gate.
|
||
- **PASS:** гейт возвращает `(False, "re-test failed after rebase...")`, задача на
|
||
`development`, комментарий в Plane, слияния нет.
|
||
- **FAIL:** гейт вернул `True`, либо слияние произошло при красном re-test.
|
||
|
||
## AC-5 — Сериализация слияний (merge-lock)
|
||
- **Дано:** две задачи одного `repo` одновременно подходят к merge-gate.
|
||
- **Когда:** обе пытаются пройти гейт.
|
||
- **PASS:** «догон+re-test+слияние» выполняет одновременно только одна задача; вторая
|
||
ждёт освобождения lock (в пределах `merge_lock_timeout_s`), после чего повторно
|
||
сверяет «не отстаёт» и при необходимости догоняется. Воспроизводимый сценарий
|
||
«две зелёные ветки ломают main» НЕ приводит к красному `main`.
|
||
- **FAIL:** обе задачи параллельно проходят гейт и вливаются, воспроизводя гонку.
|
||
|
||
## AC-6 — Re-test тайм-аут управляем
|
||
- **Дано:** re-test превышает `settings.merge_retest_timeout_s`.
|
||
- **PASS:** прогон прерывается, гейт возвращает `(False, "re-test timeout...")`, задача
|
||
не виснет, идёт штатный откат.
|
||
- **FAIL:** задача висит дольше тайм-аута или падает с необработанным исключением.
|
||
|
||
## AC-7 — Никогда не push/merge в main напрямую из гейта
|
||
- **PASS:** код merge-gate не выполняет `git push ... main` и не форс-пушит `main`;
|
||
force-операции — только `--force-with-lease` по ветке задачи.
|
||
- **FAIL:** найден любой push/force-push в `main` из логики гейта.
|
||
|
||
## AC-8 — Изоляция в worktree
|
||
- **PASS:** все git-операции гейта идут в worktree ветки (`get_worktree_path` /
|
||
`ensure_worktree`), а не в общем `/repos/<repo>` clone.
|
||
- **FAIL:** rebase/тесты выполняются в общем clone, создавая S-4-гонку.
|
||
|
||
## AC-9 — Контракт never-raise
|
||
- **Дано:** недоступен git/сеть, бит worktree, отсутствует ветка и т.п.
|
||
- **PASS:** `check_branch_mergeable` и функции `merge_gate.py` возвращают `(False, "<reason>")`
|
||
(или безопасный фоллбэк), НИКОГДА не пробрасывают исключение в `advance_stage`.
|
||
- **FAIL:** любое необработанное исключение всплывает из гейта.
|
||
|
||
## AC-10 — Реестр QG и снапшоты консистентны
|
||
- **PASS:** `"check_branch_mergeable"` зарегистрирован в `QG_CHECKS` и callable;
|
||
`tests/test_qg_registry_snapshot.py` (`_EXPECTED_QGS`, при изменении стадий —
|
||
`_EXPECTED_TRANSITIONS`) обновлены и зелёные; порядок ключей `STAGE_TRANSITIONS`
|
||
сохранён (не сломан `get_previous_stage`).
|
||
- **FAIL:** дрейф реестра/стадий без обновления снапшотов; красные snapshot-тесты.
|
||
|
||
## AC-11 — Интеграция отката в stage_engine
|
||
- **PASS:** в `_handle_qg_failure_rollbacks` есть ветка merge-gate FAIL → `development`
|
||
с уведомлениями (Plane + Telegram) и учётом `MAX_DEVELOPER_RETRIES`; `_run_qg`
|
||
корректно диспетчеризует новый чек.
|
||
- **FAIL:** FAIL гейта не приводит к откату, или нет уведомления, или зацикливание заворотов.
|
||
|
||
## AC-12 — Условный no-op / выключение (если реализовано)
|
||
- **Дано:** `settings.merge_gate_enabled = False` (или репо вне `merge_gate_repos`).
|
||
- **PASS:** гейт возвращает `(True, "merge-gate disabled")`, конвейер работает как прежде.
|
||
- **FAIL:** гейт блокирует/ломает конвейер при выключенном флаге.
|
||
|
||
## AC-13 — Документация обновлена (golden source)
|
||
- **PASS:** обновлены `docs/architecture/README.md` (merge-gate/auto-rebase/re-test,
|
||
при изменении — таблицы стадий/реестра), `CHANGELOG.md`, `.env.example` (новые
|
||
`ORCH_*` настройки); создан ADR `06-adr/ADR-001-merge-gate.md`.
|
||
- **FAIL:** функционал изменён, документация/ADR/CHANGELOG не обновлены (Reviewer →
|
||
REQUEST_CHANGES).
|
||
|
||
## AC-14 — Безопасность self-hosting
|
||
- **PASS:** в рамках задачи прод-контейнер `orchestrator` (8500) не рестартился и не падал;
|
||
изменения не трогают `.env*`, `docker-compose.yml`, прод-инфраструктуру; страховка
|
||
стадией `deploy-staging` сохранена.
|
||
- **FAIL:** любой рестарт/падение прод-оркестратора или правка прод-инфры в рамках задачи.
|
||
|
||
## AC-15 — Зелёный регресс
|
||
- **PASS:** `pytest tests/ -q` зелёный целиком (новые тесты ORCH-043 + существующий набор).
|
||
- **FAIL:** любой упавший/сломанный существующий тест.
|