Files
orchestrator/docs/overview/tech-pipeline.md
claude-bot 58e5dfe55d
All checks were successful
CI / test (push) Successful in 1m15s
CI / test (pull_request) Successful in 1m12s
docs(serial-gate): sync system showcase + clean stray tags (ORCH-124)
Addresses reviewer REQUEST_CHANGES (run 768) on ORCH-124 — docs-only,
no src/tests touched, fix scope unchanged.

P1: update docs/overview/ showcase for the new serial-gate "pause without
blocking" axis (changed task-routing functionality, ORCH-011/ORCH-079):
- tech-pipeline.md: FIFO exception "pause without blocking" next to freeze
- tech-data-model.md: durable signal tasks.paused_at on the Task row
- tech-observability.md: paused/reason in serial_gate GET /queue block +
  operator endpoints POST /serial-gate/pause|resume

P2: strip leaked tool-call trailing tags (</content>/</invoke>) from 4
golden-source docs of this PR (06-adr/ADR-001, adr-0051,
08-data-requirements.md, 10-tech-risks.md).

CHANGELOG "Доки" bullet extended accordingly. Full suite green (2178 passed);
test_system_docs.py green (machine-checked showcase facts intact).

Refs: ORCH-124
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 21:50:45 +03:00

135 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Блок 2. Конвейер: стадии, гейты, маршруты
> Источник истины — карта переходов `STAGE_TRANSITIONS` в `src/stages.py` и реестр гейтов
> `QG_CHECKS` в `src/qg/checks.py`; перечень ниже сверяется с кодом структурным тестом
> (`tests/test_system_docs.py`). Норматив структуры доков конвейера —
> [PIPELINE_DOCS](../_standards/PIPELINE_DOCS.md).
## Схема конвейера
```
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, см. [интеграции](tech-integrations.md)).
## Откаты
`REQUEST_CHANGES` от ревьюера, проваленные тесты или красный под-гейт возвращают задачу на
стадию разработки с дословным перечнем замечаний. Лимит — 3 попытки подряд, дальше задача
останавливается и требует человека (анти-петля).
## Человеческие гейты и их снятие авто-лейблами
В штатном прогоне человек принимает ровно два решения:
- **Одобрение постановки** (на `analysis`): перевод задачи в статус Approved пропускает её
дальше;
- **Подтверждение прод-выкладки** (на `deploy`): отдельный статус **Confirm Deploy** — чтобы
привычный «approve» не выкатывал прод случайным кликом.
Оба решения можно снять декларативно — лейблами **autoApprove** / **autoDeploy** на задаче
(пакетный авто-режим). Снимается только ожидание человеческого сигнала: ни одна техническая
проверка не пропускается, autoDeploy физически не может выкатить непрошедшее под-гейты.
## Багфикс-маршрут
Задача с меткой **Bug** едет коротким путём: облегчённая аналитика (но полный пакет
документов) и пропуск стадии `architecture` — из аналитики сразу в разработку. Срезается
только аналитика/проектирование: **все гейты исполняются без изменений**. Сложный баг
эскалируется обратно в полный цикл.
## Последовательность внутри репозитория (serial gate)
Новая задача репозитория не входит в работу, пока не завершена более ранняя (FIFO): ветка
каждой задачи срезается от свежего `main`, уже содержащего код предшественника. Деградация
прода после выкладки замораживает репозиторий (freeze) до ручного разбора — следующие задачи
ждут.
У FIFO-порядка есть управляемое исключение — **пауза без блокировки**: оператор может явно
поставить более раннюю задачу на паузу (durable-сигнал `tasks.paused_at`), и тогда срочный
успешник её обгоняет, не дожидаясь завершения. Пауза — отдельная ось: она ≠ отмена (задача не
терминальна и возвращается в гейт обратной командой) и **не** обходит ни freeze, ни объявленные
зависимости. Свежесть базы возобновлённой задачи гарантируют те же механизмы (отложенный срез
ветки + ребейз на слиянии), что и для обычного FIFO.
## Отмена: STOP → `cancelled`
Перевод задачи в статус **STOP** останавливает агента, снимает job'ы с очереди, удаляет
рабочую ветку и worktree и переводит задачу в `cancelled`. Если задача в необратимой фазе
(идёт слияние/выкладка) — отмена откладывается и применяется после честного завершения шага.
STOP никогда не трогает `main` и прод-контейнер.
## Статусная модель Plane: индикация ≠ управление
Статусы в Plane — слой **индикации**: они показывают человеку осмысленную картину хода задачи,
но никогда не управляют конвейером (машина стадий — только `STAGE_TRANSITIONS`). Управляющих
статусов ровно три: запуск в работу, Approved/Confirm Deploy (человеческие гейты) и STOP
(отмена). Полная карта статусов — в [инженерном справочнике](../architecture/README.md).
---
*Кто работает на каждой стадии и что сдаёт — [агенты](tech-agents.md); как гейты читают
вердикты — [качество и безопасность](tech-quality-security.md).*