11 KiB
work_item, stage, author_agent, status, created_at, model_used
| work_item | stage | author_agent | status | created_at | model_used |
|---|---|---|---|---|---|
| ORCH-115 | analysis | analyst | ready-for-review | 2026-06-16 | claude-opus-4-8 |
03 — Критерии приёмки (Acceptance Criteria): ORCH-115 — детерминированный staging-раннер
Work Item: ORCH-115 · Repo: orchestrator · Стадия: analysis
Формат: каждый критерий имеет PASS (что должно быть истинно для приёмки) и FAIL (что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам репозитория.
AC-1 — Детерминированный перехват на deploy-staging (нет _spawn/LLM)
Условие: При включённом флаге и in-scope репо джоб deployer на стадии deploy-staging
обрабатывается раннером, а не LLM-агентом.
- PASS:
launch_job(src/agents/launcher.py) перехватывает джоб до_spawn(рядом с D1/D2) приagent=="deployer"+ стадия задачиdeploy-staging+staging_runner.applies(repo);_spawnне вызывается; не создаётся строкаagent_runs; джоб ведётсяmark_job(...)самим раннером. Тест воспроизводит это без живого Claude CLI. - FAIL: На
deploy-stagingдля in-scope репо при включённом флаге всё ещё вызывается_spawn/ создаётсяagent_runs-строка LLM-deployer'а.
AC-2 — Контракт артефакта 15-staging-log.md неизменен
Условие: Раннер пишет тот же артефакт с тем же machine-key, что читает гейт.
- PASS: Создаётся
docs/work-items/<work_item_id>/15-staging-log.mdс frontmatterstaging_status: SUCCESS|FAILED(UPPERCASE) + обязательная 52c-схема (work_item/stage: deploy-staging/author_agent/status/created_at/model_used)._parse_staging_statusчитает его и возвращает корректный вердикт без изменения парсера. - FAIL: Изменено имя/регистр ключа
staging_status:, отсутствует frontmatter, либо вердикт записан только прозой; либо парсер_parse_staging_statusпришлось менять.
AC-3 — Корректный exit-code → verdict маппинг
Условие: Exit-код staging-сюиты детерминированно маппится в вердикт.
- PASS:
0 → SUCCESS; любой ненулевой / None / ошибка запуска →FAILED(fail-closed). Маппинг — pure-функция, переиспользующая контрактself_deploy.map_exit_code_to_status(или эквивалентный единый), покрыта unit-тестом на каждый класс входа. infra-tolerance (ORCH-061) не пересуживается раннером. - FAIL: Ненулевой код даёт
SUCCESS; ошибка/None даётSUCCESS(ложный green); раннер вводит второй несогласованный маппинг.
AC-4 — Эквивалентность маршрутизации (SUCCESS / FAILED)
Условие: После вердикта конвейер ведёт себя ровно как при завершившемся LLM-deployer'е.
- PASS: SUCCESS → раннер инициирует
advance_stage(finished_agent="deployer"), далее отрабатывают под-гейты security→merge→coverage→image-freshness (ORCH-022/043/027/058) и Phase A (ORCH-036) — теми же путями. FAILED → существующий откатdeploy-staging → developmentс инкрементом developer-retry (src/stage_engine.py:932), тот же исход, что у FAILED-вердикта LLM. - FAIL: Задача зависает на
deploy-staging(гейт не инициирован); или FAILED не откатывает / откатывает иначе; или появляется новое ребро/исход.
AC-5 — Инвариант скоупа: гейты/стадии/схема БД не тронуты (анти-дрейф)
Условие: Изменена только сторона продюсера, не контракт конвейера.
- PASS:
git diffне затрагиваетsrc/stages.py::STAGE_TRANSITIONS; имена/семантикуQG_CHECKS/check_*/_parse_*вsrc/qg/checks.py; machine-verdict-ключи (staging_status:/deploy_status:/verdict:/result:/security_status:/coverage_status:); схему БД (нет новых таблиц/колонок/миграций). Анти-дрейф-тест это подтверждает. - FAIL: Любой из перечисленных артефактов изменён по имени/семантике/структуре.
AC-6 — Kill-switch и скоуп (обратимость)
Условие: Флаг возвращает прежнее поведение; скоуп ограничивает раннер.
- PASS:
staging_runner_enabled=False→ наdeploy-stagingзапускается прежний LLM-deployer через_spawn(байт-в-байт до ORCH-115). Пустойstaging_runner_repos→ раннер активен только дляorchestrator; не-self репо никогда не перехватываются. Покрыто тестом для обоих значений флага. - FAIL: При выключенном флаге раннер всё равно перехватывает; либо не-self репо перехватывается.
AC-7 — never-raise / fail-safe (инструмент недоступен)
Условие: Любая ошибка раннера приводит к безопасному детерминированному исходу.
- PASS: Недоступность docker/
orchestrator-staging, таймаут, I/O-ошибка → раннер не роняет воркер; исход —FAILED(fail-closed) или штатный requeue/defer, никогда тихий advance/ ложный green. Все публичные функцииstaging_runner.py— never-raise;applies()при ошибке →False. - FAIL: Ошибка раннера роняет воркер/клинит очередь; либо ошибка/таймаут даёт
SUCCESS.
AC-8 — Self-hosting safety
Условие: Раннер на deploy-staging не выполняет опасных для прода действий.
- PASS: Раннер не рестартит контейнер 8500, не выполняет
docker compose up -d orchestrator/--build, не пушит force вmain, не правит.env/.env.staging/docker-compose.yml. Merge лога идёт штатным PR/artifact-merge-путём (какself_deploy.write_deploy_log). Подтверждается ревью кода раннера + (где применимо) тестом, что в командах раннера нет запрещённых литералов. - FAIL: Раннер содержит любой путь, рестартящий 8500 / force-push в
main/ правящий инфру.
AC-9 — Изоляция процесса и таймаут
Условие: docker-subprocess ограничен по времени и не оставляет сирот.
- PASS: Раннер запускает staging-сюиту с ограниченным таймаутом
(
staging_runner_timeout_s, согласован со сквозным бюджетом ORCH-065/109/110, не правяreaper_max_running_s); малформ/непозитив таймаут → дефолт + WARNING; завершение чистое (без осиротевших docker/pytest-процессов, согласовано сproc_group/tree-kill ORCH-110). - FAIL: Нет таймаута / зависший subprocess клинит воркер; остаются сироты процессов.
AC-10 — Наблюдаемость
Условие: Исход раннера виден и различим.
- PASS:
GET /queueсодержит read-only блокstaging_runner(enabled/repos/счётчикиsuccess/failed/tool_error/runs); на каждый прогон — один структурный лог-вердикт (work_item/repo/exit_code/status/duration_s), различающий код-фейл и tool-error. - FAIL: Нет блока в
/queue; исход раннера не логируется/не различим.
AC-11 — Норматив сопровождения LLM-карты/политики/витрины
Условие: Документация обновлена в том же PR (правило агентов №2 + норматив ORCH-118).
- PASS:
docs/architecture/llm-call-sites.md(строка A6) /llm-determinization-roadmap.md/llm-usage-policy.mdотражают реализацию детерминированного deployer-staging; соответствующие анти-дрейф-тесты (tests/test_llm_call_site_inventory.py,tests/test_llm_determinization_docs.py) зелёные;.openclaw/agents/deployer.md,CLAUDE.md,CHANGELOG.md,docs/overview/обновлены. - FAIL: Карта/политика/roadmap/витрина не обновлены; анти-дрейф-тесты красные (reviewer: ≥P1).
AC-12 — Полный регресс зелёный
Условие: Существующий конвейер не сломан.
- PASS:
pytest tests/ -qзелёный; новыйtests/test_orch115_staging_runner.pyзелёный; staging-smoke (scripts/staging_check.py) на 8501 проходит штатно. - FAIL: Любой ранее зелёный тест становится красным; новые тесты падают.
Сводная матрица AC ↔ FR/BR
| AC | Покрывает |
|---|---|
| AC-1 | BR-1 / FR-1 |
| AC-2 | BR-2 / FR-4 |
| AC-3 | BR-4 / FR-2 / FR-3 |
| AC-4 | BR-3 / FR-5 |
| AC-5 | NFR-1 / FR-6 |
| AC-6 | BR-5 / FR-6 |
| AC-7 | NFR-2 / FR-1 |
| AC-8 | BR-7 |
| AC-9 | NFR-3 / NFR-4 / FR-5 |
| AC-10 | BR-6 / FR-7 |
| AC-11 | NFR-6 |
| AC-12 | NFR-5 / NFR-1 |