Files
orchestrator/docs/overview/tech-pipeline.md
claude-bot dbd8df6eb2
All checks were successful
CI / test (push) Successful in 1m15s
CI / test (pull_request) Successful in 1m16s
docs(operations): add user FAQ for STOP cancellation status (ORCH-108)
Create docs/operations/FAQ_STOP.md — a user-facing "вопрос → ответ" FAQ for
Plane board users explaining the STOP status: what it does, how to cancel a
task, step-by-step consequences (agent stops → jobs cancelled → working branch
and worktree removed → task → cancelled → Telegram+Plane; docs artifacts
preserved, main/prod untouched), deferred cancellation in the critical
merge/deploy window, explicit "STOP does NOT revert merged/deployed code"
(revert is a separate task), restart only via "To Analyse" from scratch, no-op
causes, where to observe the result, and STOP/Approved/Confirm Deploy disambig.

docs-only: src/**, STAGE_TRANSITIONS, QG_CHECKS, check_*, machine-verdict keys
and the DB schema are byte-for-byte untouched. STOP behaviour source of truth
remains ORCH-090 (adr-0026); the FAQ documents and links to it (link-first:
machine details markers/lease/tombstone given by reference, not duplicated).

Add two-way cross-links: docs/overview/business.md (Сценарий 6) and
docs/overview/tech-pipeline.md (Отмена: STOP → cancelled) → FAQ; FAQ → overview
+ ADR ORCH-090. Structure guarded by deterministic anti-drift test
tests/test_faq_stop_doc.py (offline, no network/LLM/subprocess; mirrors
tests/test_lite_setup_doc.py): existence + 8 section anchors + fact bricks +
cross-links + claim-level negative scan (sentence-level, not bare substrings,
so it never false-fails on correctly negating phrases — TR-3, with a
non-evergreen self-check). Full pytest tests/ green (2227 passed).

Refs: ORCH-108

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 17:50:58 +03:00

13 KiB
Raw Blame History

Блок 2. Конвейер: стадии, гейты, маршруты

Источник истины — карта переходов STAGE_TRANSITIONS в src/stages.py и реестр гейтов QG_CHECKS в src/qg/checks.py; перечень ниже сверяется с кодом структурным тестом (tests/test_system_docs.py). Норматив структуры доков конвейера — PIPELINE_DOCS.

Схема конвейера

created → analysis → architecture → development → review → testing → deploy-staging → deploy → done
                          ↑                          │
                          └──── REQUEST_CHANGES ─────┘   (откат на доработку, max 3)

Плюс системный сток cancelled — терминальное состояние отменённой задачи (кнопка STOP, см. ниже). Это не ребро конвейера, а равноправный done сток: попасть в него можно с любой стадии, выйти — нельзя.

Стадии и гейты выхода

Гейт выхода (exit-гейт) — машинная проверка, без которой задача не покидает стадию:

Стадия Кто работает Гейт выхода (имя в реестре) Что проверяет
created вход конвейера (вебхук Plane)
analysis analyst check_analysis_approved пакет аналитики полон И постановка одобрена человеком
architecture architect check_architecture_done ADR / инфра-требования зафиксированы
development developer check_ci_green CI на ветке задачи зелёный
review reviewer check_reviewer_verdict машинный вердикт ревью: APPROVED
testing tester check_tests_passed машинный вердикт тестера: PASS
deploy-staging deployer check_staging_status репетиция выкладки на песочнице успешна
deploy deployer / finalizer check_deploy_status прод-выкладка реально успешна
done терминал
cancelled терминал (сток отмены)

Детерминированный staging-раннер (ORCH-115). На стадии deploy-staging для self-hosting orchestrator работу ведёт детерминированный код (src/staging_runner.py), а не LLM-агент deployer: он перехватывается в launch_job до запуска агента (как Phase A/B/C прод-деплоя), исполняет ту же staging-сюиту, маппит exit-код в staging_status: и инициирует тот же гейт check_staging_status. Это замена продюсера артефакта, а не гейта: контракт 15-staging-log.md, имя/семантика check_staging_status, STAGE_TRANSITIONS — не изменились. Под kill-switch staging_runner_enabled (скоуп staging_runner_repos, пусто → self-hosting only); при выключении на стадии снова работает LLM-deployer байт-в-байт. Это первый реализованный срез determinization-roadmap (см. docs/architecture/llm-determinization-roadmap.md).

Детерминированный test-раннер (ORCH-116). На стадии testing для self-hosting orchestrator работу ведёт детерминированный код (src/test_runner.py), а не LLM-агент tester: он перехватывается в launch_job до запуска агента (тем же паттерном, что staging-раннер), исполняет регресс pytest в worktree ветки + read-only smoke, маппит exit-код в result: и инициирует тот же гейт check_tests_passed. Это замена продюсера артефакта, а не гейта: контракт 13-test-report.md, имя/семантика check_tests_passed/_parse_tests_verdict, STAGE_TRANSITIONS — не изменились. Под kill-switch test_runner_enabled (скоуп test_runner_repos, пусто → self-hosting only; репо без тест-контракта → LLM-tester); при выключении снова работает LLM-tester байт-в-байт. Это второй реализованный срез determinization-roadmap (гибрид: LLM-фолбэк остаётся на off-control-path триаж, не на вынесение result:).

Под-гейты деплойного ребра — врезки, не стадии

На переходе deploy-staging → deploy исполняются четыре под-гейта в нормативном порядке (security → merge → coverage → image-freshness):

  1. check_security_gate — секреты/зависимости, вердикт из security-отчёта;
  2. check_branch_mergeable — merge-gate: ветка догнана до свежего main (под merge-lease) и мержабельна;
  3. check_coverage_gate — покрытие тестами не ниже базовой линии/порога (baseline-ratchet);
  4. check_staging_image_fresh — staging-образ собран из актуального кода.

Это врезки в переход, а не стадии: они не появляются в карте STAGE_TRANSITIONS, а исполняются stage engine'ом внутри ребра. Провал любого из них — откат на доработку. Исключение (ORCH-110): инфра-таймаут локального re-test merge-gate (а не детерминированный красный тест) — это транзиент, а не дефект кода → ограниченный повтор + отдельный инфра-alert, без отката на доработку и без расхода developer-retry (красный re-test/конфликт по-прежнему откатывают). На ребре deploy → done аналогичная врезка merge-verify подтверждает, что код задачи реально слит в main (слияние — только через PR-API Gitea, см. интеграции).

Откаты

REQUEST_CHANGES от ревьюера, проваленные тесты или красный под-гейт возвращают задачу на стадию разработки с дословным перечнем замечаний. Лимит — 3 попытки подряд, дальше задача останавливается и требует человека (анти-петля).

Человеческие гейты и их снятие авто-лейблами

В штатном прогоне человек принимает ровно два решения:

  • Одобрение постановки (на analysis): перевод задачи в статус Approved пропускает её дальше;
  • Подтверждение прод-выкладки (на deploy): отдельный статус Confirm Deploy — чтобы привычный «approve» не выкатывал прод случайным кликом.

Оба решения можно снять декларативно — лейблами autoApprove / autoDeploy на задаче (пакетный авто-режим). Снимается только ожидание человеческого сигнала: ни одна техническая проверка не пропускается, autoDeploy физически не может выкатить непрошедшее под-гейты.

Багфикс-маршрут

Задача с меткой Bug едет коротким путём: облегчённая аналитика (но полный пакет документов) и пропуск стадии architecture — из аналитики сразу в разработку. Срезается только аналитика/проектирование: все гейты исполняются без изменений. Сложный баг эскалируется обратно в полный цикл.

Последовательность внутри репозитория (serial gate)

Новая задача репозитория не входит в работу, пока не завершена более ранняя (FIFO): ветка каждой задачи срезается от свежего main, уже содержащего код предшественника. Деградация прода после выкладки замораживает репозиторий (freeze) до ручного разбора — следующие задачи ждут.

У FIFO-порядка есть управляемое исключение — пауза без блокировки: более раннюю задачу можно снять с активной очереди репозитория, не дожидаясь её завершения, и тогда срочный успешник её обгоняет. Паузу (durable-сигнал tasks.paused_at) ставят два источника. Оператор — явно (POST /serial-gate/pause, снять — /resume). Движок — автоматически, когда аналитик упирается в блокирующие открытые вопросы и задача уходит в Needs Input (узкий триггер под флагом analyst_needs_input_autopause_enabled, скоуп self-hosting); на возобновлении (ответ человека) движок снимает паузу симметрично. Авто-park нужен, чтобы задача, ждущая человека часы или дни, не клинила FIFO-очередь репозитория в автономном пакетном прогоне. Пауза — отдельная ось: она ≠ отмена (задача не терминальна и возвращается в гейт обратной командой) и не обходит ни freeze, ни объявленные зависимости. Свежесть базы возобновлённой задачи гарантируют те же механизмы (отложенный срез ветки + ребейз на слиянии), что и для обычного FIFO.

Отмена: STOP → cancelled

Перевод задачи в статус STOP останавливает агента, снимает job'ы с очереди, удаляет рабочую ветку и worktree и переводит задачу в cancelled. Если задача в необратимой фазе (идёт слияние/выкладка) — отмена откладывается и применяется после честного завершения шага. STOP никогда не трогает main и прод-контейнер.

Пользовательская инструкция «как этим пользоваться» — FAQ по статусу STOP.

Статусная модель Plane: индикация ≠ управление

Статусы в Plane — слой индикации: они показывают человеку осмысленную картину хода задачи, но никогда не управляют конвейером (машина стадий — только STAGE_TRANSITIONS). Управляющих статусов ровно три: запуск в работу, Approved/Confirm Deploy (человеческие гейты) и STOP (отмена). Полная карта статусов — в инженерном справочнике.


Кто работает на каждой стадии и что сдаёт — агенты; как гейты читают вердикты — качество и безопасность.