---
work_item: ORCH-118
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-15
model_used: claude-opus-4-8
---

# 01 — BRD (бизнес-требования): ORCH-118 — replace avoidable LLM control paths with deterministic implementations

Work Item: **ORCH-118** · Repo: **orchestrator** · Стадия: analysis

> ⚠️ **Inventory-first.** Это **зонтичная inventory/architecture-задача**, а НЕ реализация
> детерминированных раннеров. Её результат — **карта** всех мест вызова LLM + классификация +
> упорядоченный roadmap + нормативная политика использования LLM, защищённая структурными тестами.
> Реализация конкретных замен — **последующие задачи**, запускаемые ПОСЛЕ утверждения карты. Их код
> в ORCH-118 **не вносится** (см. §2 «Вне объёма»).

> 📌 **Follow-up'ы именуются по РОЛИ, без выдуманных Plane-ID.** Roadmap рекомендует отдельные
> follow-up задачи по ролям-кандидатам (**deployer-замена**, **tester-гибрид** и т.д.). Конкретные
> Plane-ID этих задач в артефактах ORCH-118 **НЕ фиксируются** — они присваиваются при фактическом
> заведении задач в backlog. Аналитик не имеет доказательного источника на конкретные ID и не должен
> их выдумывать (см. NFR-6).

> 🔁 **Revision R3 (2026-06-15).** Из пакета **удалена** нормативная привязка follow-up'ов к
> конкретным ID `ORCH-115`/`ORCH-116` (этих work item нет ни в репозитории, ни в подтверждённом
> backlog — claim «источник истины: live Plane backlog» был **непроверяемым**). Вместе с ней удалены
> навязывавший её структурный тест (бывш. TC-11) и отдельный критерий приёмки (бывш. AC-9). Follow-up'ы
> теперь описаны **по роли**, ID — TBD. Содержательная классификация ролей не менялась
> (deployer = кандидат на детерминированную замену, tester = кандидат на hybrid-fallback).
> *(R1→R2 ранее «чинил» порядок этих ID; R3 убирает корень проблемы — фиксацию несуществующих ID.)*

> 🔁 **Revision R4 (2026-06-15).** Закрыт блокер R3-ревью: инвариант «места вызова LLM» **смешивал**
> факт *«существует процесс Claude CLI / спавнится subprocess»* (транспорт/механизм) с фактом
> *«потребляется суждение LLM»* (LLM-консультация). R4 развёл **транспорт** (`_spawn`) и **слот/
> capability** (D1/D2) от факта **консультации** во всех артефактах (см. §0). Содержательная
> классификация ролей и весь R3-материал (анти-фабрикация ID) — без изменений.

> 🔁 **Revision R5 (2026-06-15) — единственный оставшийся блокер R4-ревью.** Рецензент подтвердил R4
> (консультация ≠ транспорт/слот; no-alternative-LLM-transport; follow-up'ы по роли/TBD; нет
> runtime-дифа) — **менять их не нужно**. Закрывается **один** блокер: артефакты разводили
> «консультация ≠ транспорт/слот», но **не делали явной третью ось — самую важную для названия
> задачи** *«replace avoidable LLM **control paths**»*: среди фактических консультаций **не
> различались** (i) **control-path-консультации** — где LLM-вердикт **потребляется потоком управления**
> (на нём ветвится `check_*`-гейт), и (ii) **artifact-producer-консультации** — где LLM лишь
> **производит артефакт**, а ветвление делает **детерминированный гейт** (наличие файлов / CI), и
> суждение LLM в control flow **не входит**. И главное — нигде **явно не определена «avoidable LLM
> control path»**. R5 добавляет эту ось и определение во **все** артефакты (новый §0-bis, уточнённые
> BR-1/BR-2 + новые BR-8/BR-9, FR-1/FR-2 + новый FR-8, AC-1/AC-2 + новый AC-10, TC-13/TC-14).
> Содержательная классификация (analyst/architect/developer/reviewer → keep-LLM; deployer →
> replace-deterministic; tester → hybrid) **не меняется** — R5 даёт ей **доказательный control-path
> вывод** из кода (`check_*`/`_parse_*` в `src/qg/checks.py`).

---

## 0. Единица анализа: «LLM-консультация» ≠ «процесс Claude CLI» (R4)

Задача — про **LLM control paths**, поэтому единица инвентаря/классификации/инвариантов — это
**LLM-консультация (call-site)**, а НЕ «спавн процесса / существование Claude CLI». Три ортогональных
факта фиксируются **раздельно** (их смешение и было блокером R3-ревью):

1. **LLM-консультация (семантическая единица).** Точка потока управления, где решение/артефакт
   конвейера **потребляет суждение LLM** (инференс модели). Именно её перечисляет и классифицирует
   карта. «Заменить avoidable LLM control path» = убрать *консультацию* там, где суждение не нужно, —
   независимо от того, каким транспортом она реализована.
2. **Транспорт (механизм) ≠ консультация.** Claude CLI-subprocess через `launcher._spawn`
   (`src/agents/launcher.py`, сборка `CLAUDE_BIN --print … --system-prompt "$(cat …)"` + `Popen`) —
   **текущий единственный транспорт**, которым реализуется LLM-консультация. Транспорт — это одна
   *реализация* понятия, а НЕ его *определение*. «Существует процесс Claude CLI» само по себе **не**
   равно «принято решение на основе суждения LLM».
3. **Capability ≠ consultation (способность ≠ факт консультации).** Спавн процесса делает site
   *LLM-capable*; происходит ли консультация фактически — **гейтится потоком управления**:
   - `D1/D2` (`deploy-finalizer`/`post-deploy-monitor`) — job-роли, **занимающие слот агента**, но
     перехватываемые в `launch_job` **до** `_spawn` (`src/agents/launcher.py:389,394`, код прямо
     помечает «Not an LLM spawn») → **консультации LLM нет**, хотя «агент» как job существует;
   - timeout-kill (`exit_code=-9`) / salvage-guard (`if exit_code==0`) → спавненный процесс может **не
     произвести** потреблённого суждения.
   Поэтому «процесс спавнится» **переоценивает** «суждение потреблено».

Следствие для инварианта единственной точки (детализируется в BR-1/BR-6): он должен быть
**транспорт-агностичным и двусторонним** — (i) единственный транспорт LLM-консультации в `src/**` —
`_spawn`, И (ii) **отсутствует любой иной транспорт** (импорт `anthropic`/`openai`/LLM-SDK, прямой
HTTP-эндпоинт Anthropic/Claude, второй model-invoking subprocess-сборщик `--system-prompt`/`--model`).
Дискриминатор — **«консультирует LLM», а не «спавнит subprocess»**: десятки subprocess-вызовов в
`src/**` (`git`/`pytest`/`docker`/`ssh`/сканеры/`staging_check.py`) **не** являются LLM-консультациями
и не должны попадать под инвариант (см. FR-6 матчинг).

---

## 0-bis. Третья ось: control-path-консультация ≠ artifact-producer-консультация; что такое «avoidable» (R5)

§0 (R4) отделил **факт консультации** от **транспорта** и **слота**. Но название задачи —
«replace **avoidable** LLM **control paths**» — требует ещё одного, **решающего** различия **внутри
множества фактических консультаций** (A1…A6). Без него «control path» и «avoidable» остаются
неопределёнными, и карта не отвечает на главный вопрос задачи: *какие именно консультации — это
avoidable LLM control paths*. Это и есть оставшийся блокер R4-ревью.

### Ось 3 — как именно LLM-вывод соотносится с потоком управления

Каждая фактическая консультация (роль-агент) относится **ровно к одному** из двух типов:

- **(C) Control-path-консультация.** LLM эмитит **machine-verdict**, который **потребляется потоком
  управления конвейера**: соответствующий `check_*`-гейт **ветвится на этом вердикте**
  (PASS→дальше / FAIL→откат). Суждение LLM **входит в control flow** — это и есть «**LLM control
  path**» в точном смысле названия задачи.
- **(P) Artifact-producer-консультация.** LLM **производит артефакт** (документы/код/PR), а решение
  о продвижении принимает **детерминированный гейт**, судящий артефакт **независимо** от
  самоотчёта LLM (наличие файлов, статус CI). Суждение LLM **в control flow не входит** → это **не**
  «LLM control path» (хотя консультация реальна и может требовать настоящего суждения).

Различие доказывается кодом — **кто потребляет вывод роли** (`src/qg/checks.py`, ground-truth на
момент задачи):

| Роль | Потребитель вывода (control-flow consumer) | Тип (C/P) | Control path? |
|------|--------------------------------------------|-----------|---------------|
| analyst | `check_analysis_complete` (checks.py:33) — **наличие файлов** 01–04 | **P** | нет |
| architect | `check_architecture_done` (checks.py:62) — **наличие** 06-adr/07 | **P** | нет |
| developer | `check_ci_green` (checks.py:82) + `check_branch_mergeable` (657) — **CI/merge** | **P** | нет |
| reviewer | `check_reviewer_verdict` (checks.py:336) читает **`verdict:`** → REQUEST_CHANGES-откат | **C** | **да** |
| tester | `check_tests_passed` (checks.py:182) → `_parse_tests_verdict` (226) читает **`result:`** | **C** | **да** |
| deployer | `check_staging_status` (599)→`_parse_staging_status` (538) **`staging_status:`**; `check_deploy_status` (473)→`_parse_deploy_status` (413) **`deploy_status:`** | **C** | **да** |

> Для **P**-ролей гейт читает **не самоотчёт LLM**, а независимый детерминированный сигнал
> (файлы/CI) — поэтому подделать ветвление «самооценкой» нельзя; это структурно НЕ control path.
> Для **C**-ролей гейт читает **именно machine-verdict, который написал LLM** — суждение LLM и есть
> точка ветвления.

### Определение «avoidable LLM control path» (нормативное, R5)

Call-site — **avoidable LLM control path** ⟺ выполнены **оба** условия:

1. **(control path)** это **C**-консультация — её LLM-вердикт потребляется потоком управления
   (`check_*` ветвится на нём); **и**
2. **(deterministically derivable)** этот вердикт по сути есть **детерминированная функция от
   tool-сигналов** (exit-code `pytest`/smoke, `staging_check.py`, exit-code деплоя), которые
   оркестратор **уже вычисляет сам** → суждение LLM **не добавляет информации** → консультацию можно
   снять без потери смысла.

Отсюда — **точный целевой набор задачи** (доказательно, не «на глаз»):

- **avoidable LLM control paths = {tester, deployer}** — C **и** вердикт деривируем из exit-кодов
  (`_parse_tests_verdict` судит то, что есть исход `pytest`; `_parse_staging_status`/
  `_parse_deploy_status` судят то, что есть исход `staging_check.py`/деплоя; прод-деплой
  self-hosting **уже** идёт детерминированным путём Phase A/B/C, ORCH-036).
- **control path, но НЕ avoidable = {reviewer}** — C, но вердикт **не** деривируем: «приемлем ли
  код?» — настоящее суждение (keep-LLM). Это показывает, что «control path» **сам по себе** не равен
  «avoidable» — отсекает условие 2.
- **НЕ control path (avoidable-вопрос неприменим) = {analyst, architect, developer}** — P:
  детерминированный гейт судит артефакт, суждение LLM в control flow не входит; авторская работа
  требует настоящего суждения (keep-LLM). Это отсекает условие 1.
- **уже детерминированы (вне консультаций) = {deploy-finalizer, post-deploy-monitor}** — §0.3.

Эта ось **выводит** R3/R4-классификацию из кода, а не постулирует её: класс call-site'а есть
**функция** его (C/P)-типа и деривируемости вердикта (см. BR-2). «Avoidable» больше не «удобство на
глаз», а проверяемый двухбитный предикат над `src/qg/checks.py`.

---

## 1. Бизнес-контекст и проблема

Зонтичный follow-up по итогам RCA-цепочки **ORCH-114/117** (и предшествующих ORCH-110/111/112/113):
корневым классом инцидентов было то, что **side-effectful и решающие control-path'ы не имели единого
детерминированного владения** — где-то решение принималось «потому что так удобно» через LLM-агента,
хотя по сути это исполнение фиксированных команд и маппинг результата.

Установленный факт по текущему коду (инвентаризация — §1 TRZ, артефакт-карта):

- В оркестраторе **единственный транспорт LLM-консультации** — `src/agents/launcher.py::_spawn` (одна
  `subprocess.Popen` сборка Claude CLI: `CLAUDE_BIN --print … --system-prompt "$(cat …)"`), которым
  пользуются **6 ролей-агентов** (analyst, architect, developer, reviewer, tester, deployer).
  Прямых вызовов Anthropic API / LLM-SDK / иных model-invoking транспортов в `src/**` **нет**
  (подтверждено инвентаризацией; впредь — держится тестом FR-6). ⚠️ Это утверждение про **транспорт**,
  а не про «единственный subprocess»: в `src/**` десятки прочих `subprocess`-вызовов (`git`/`pytest`/
  `docker`/`ssh`/сканеры) — они **не** консультируют LLM (см. §0).
- **Из 6 консультаций только 3 — это LLM control paths** (вердикт потребляется потоком управления,
  §0-bis): **reviewer / tester / deployer**. Остальные 3 (**analyst / architect / developer**) —
  artifact-producer'ы: их выход судит **детерминированный** гейт (наличие файлов / CI), суждение LLM
  в control flow не входит. Среди 3 control path'ов **avoidable** — те, чей вердикт деривируем из
  exit-кодов: **tester** и **deployer**; **reviewer** — control path с **настоящим** суждением
  (keep).
- **Все остальные control-path'ы уже детерминированы (без LLM):** маршрутизация стадий
  (`STAGE_TRANSITIONS`/`advance_stage`), все Quality Gate'ы и под-гейты (`check_*`, security/merge/
  coverage/image-freshness), парсеры вердиктов (`_parse_*` через `frontmatter.py`), классификатор
  ретраев (`error_classifier.py`), serial-gate/transition-lease/reconciler/reaper, а также **две
  зарезервированные job-роли** `deploy-finalizer` и `post-deploy-monitor` (перехватываются в
  `launch_job` **до** `_spawn` — это рабочий прецедент детерминированной замены агента).

Боль/риск, который закрывает задача: LLM на **механических control path'ах** — это (а) лишний
источник недетерминизма и инцидентов (ложный вердикт/действие в точке ветвления), (б) задержка
(запуск opus-агента вместо прямого вызова), (в) расход токенов/денег. При этом «вслепую» убирать LLM
нельзя — часть путей несёт **настоящее суждение** (анализ, архитектура, написание кода, **ревью**), и
автономность/гибкость должны сохраниться. Точный дискриминатор «убирать/оставить» — определение
«avoidable LLM control path» (§0-bis).

ORCH-118 даёт **доказательную карту** «где LLM действительно нужен, а где это avoidable control path»
и **упорядоченный план** безопасных замен — фундамент, на котором последующие срезы (по
ролям-кандидатам) выполняются предсказуемо и без регресса.

## 2. Объём (scope)

### В объёме
- **BR-1** Полная инвентаризация всех мест вызова LLM и всех ролей-агентов (карта call-site'ов).
- **BR-2** Классификация каждого call-site в один из 4 классов (keep / replace-now / replace-later /
  hybrid-fallback) с явным обоснованием, **выведенным** из control-path-оси (§0-bis): класс есть
  функция (C/P)-типа и деривируемости вердикта.
- **BR-3** Доказательное подтверждение (с привязкой `file:line`), что не-агентские control-path'ы
  (маршрутизация / ретраи / QG / парсеры / finalizer'ы) уже детерминированы.
- **BR-4** Упорядоченный roadmap замен: зависимости, оценка экономии токенов/времени, риски
  безопасности, потребность в hybrid-fallback, рекомендованный **первый срез** — кандидаты названы
  **по роли** (follow-up ID — TBD).
- **BR-5** Нормативная **политика использования LLM** («LLM — только там, где нужно настоящее
  суждение») как durable-документ.
- **BR-6** Структурные regression-тесты, **прибивающие инварианты карты к коду** (транспорт-агностичный
  двусторонний инвариант + control-path-ось) — анти-дрейф.
- **BR-7** Явно позиционировать **роль deployer** и **роль tester** как **кандидаты-follow-up** для
  детерминированной замены — **по роли, без привязки к конкретным Plane-ID** (см. NFR-6).
- **BR-8 (R5)** Карта **явно** размечает каждую консультацию по оси (C) control-path /
  (P) artifact-producer с доказательством — **кто потребляет вывод роли** (`check_*`/`_parse_*` с
  `file:line`).
- **BR-9 (R5)** Карта/политика **явно** определяют термин **«avoidable LLM control path»** (двухбитный
  предикат §0-bis) и **поимённо** называют целевой набор `{tester, deployer}`, явно отделяя его от
  control-path-но-keep (`reviewer`) и от не-control-path (`analyst`/`architect`/`developer`).

### Вне объёма
- ❌ **Реализация** детерминированных раннеров deployer / tester и любых других замен — это отдельные
  follow-up задачи ПОСЛЕ утверждения карты (явное требование заказчика в business request).
- ❌ **Выдумывание/фиксация конкретных follow-up Plane-ID** (напр. `ORCH-115`/`ORCH-116`) в любых
  артефактах ORCH-118 — ID присваиваются при заведении задач (NFR-6).
- ❌ Изменение `STAGE_TRANSITIONS` / реестра `QG_CHECKS` / семантики и имён `check_*` /
  machine-verdict-ключей (`verdict:`/`result:`/`staging_status:`/`deploy_status:`/`security_status:`/
  `coverage_status:`) / схемы БД.
- ❌ Включение model-routing (G3 ORCH-41) или смена модели/эффорта ролей.
- ❌ Любая правка поведения `src/**` в рантайме (ORCH-118 — **docs + tests only**, по образцу
  ORCH-077/079/101/102/103/011).
- ❌ Снижение автономности или гибкости конвейера.

## 3. Заинтересованные стороны
- **Заказчик / Owner** — инициатор RCA-трека ORCH-114/117; принимает карту и roadmap (gate утверждения).
- **Сопровождающие платформы (self-hosting)** — выигрывают в стабильности, скорости, экономии токенов.
- **Downstream-проекты (enduro-trails)** — делят общий прод/очередь; для них требуется **нулевая
  регрессия** (NFR-1).
- **Будущие исполнители follow-up'ов** — потребители карты, roadmap и политики.

## 4. Бизнес-требования (BR)

- **BR-1 — Инвентарь LLM-консультаций (call-site'ов).** Выпустить durable-документ, перечисляющий
  **каждое** место, где control-path **потребляет суждение LLM** или может его потребить (единица —
  *LLM-консультация*, §0, а не «спавн процесса»): единственный транспорт `_spawn`, все 6 ролей-агентов
  и обе зарезервированные job-роли `D1/D2` (включаются как доказательство «слот агента есть, но
  консультации LLM нет» — перехват до `_spawn`). Для каждого — `file:line`, триггер, стадия/владелец,
  выходной артефакт, machine-verdict-ключ (если есть), **потребитель вывода (`check_*`/`_parse_*` с
  `file:line`)**, оценка токенов/времени, **признак capability-vs-consultation** (§0.3) и **признак
  оси (C) control-path / (P) artifact-producer** (§0-bis, BR-8). Проверяемо: каждый `file:line`
  резолвится в реальный код.
- **BR-2 — Классификация.** Каждому call-site присвоить **ровно один** класс из таксономии:
  `keep-LLM` (нужно настоящее суждение), `replace-deterministic-now` (безопасная замена сейчас),
  `replace-later/risky` (замена позже / рискованно), `needs-hybrid-fallback` (детерминированное ядро +
  LLM-фолбэк на суждение). Класс **выводится** из control-path-оси (§0-bis): **P** → `keep-LLM`
  (артефактная авторская работа); **C + не-деривируемый вердикт** → `keep-LLM` (reviewer); **C +
  деривируемый вердикт** → `replace-*` / `needs-hybrid-fallback` (tester/deployer = avoidable). Для
  `keep-LLM` — **назвать конкретное суждение**, ради которого LLM сохраняется (для **C**-keep —
  почему вердикт **не** деривируем).
- **BR-3 — Подтверждение детерминизма не-агентских путей.** Документально, с `file:line`-доказательством,
  зафиксировать, что маршрутизация стадий, ретраи, QG-проверки, парсеры вердиктов и finalizer'ы **не
  консультируют LLM** (не зависят от суждения LLM — ни через `_spawn`, ни через иной транспорт; их
  subprocess-вызовы git/pytest/docker/ssh/сканеров — детерминированные инструменты, не LLM, §0). Если
  инвентаризация найдёт неожиданную LLM-консультацию — она попадает в карту (BR-1) и классификацию
  (BR-2).
- **BR-4 — Упорядоченный roadmap.** Ранжированный план замен: для каждого кандидата (названного **по
  роли**) — зависимости, **оценка** экономии токенов/времени (из телеметрии `agent_runs`), риск
  безопасности, нужен ли hybrid-fallback, ожидание kill-switch/обратимости. Явно указать
  **рекомендованный первый срез** и обоснование выбора (опора на control-path-вывод: первым берётся
  самый «чисто деривируемый» control path). Привязка к follow-up задаче — **по роли**; конкретный
  Plane-ID НЕ фиксируется (заводится отдельно, NFR-6).
- **BR-5 — Политика использования LLM.** Нормативный durable-документ: «LLM — только там, где требуется
  настоящее суждение»; критерии решения keep vs replace, **сформулированные через ось §0-bis**
  (является ли путь control path; деривируем ли вердикт); требование к новым/изменённым control-path'ам
  обосновывать любое использование LLM против этой политики.
- **BR-6 — Анти-дрейф структурными тестами.** Тесты, привязывающие инварианты карты к коду:
  транспорт-агностичный двусторонний инвариант единственной точки (§0); перечисленные
  детерминированные модули/job-роли не несут LLM-консультации; карта перечисляет ровно те 6 промптов,
  что лежат в `.openclaw/agents/`; тотальность классификации; **плюс control-path-ось (R5):** карта
  размечает каждую роль (C/P) согласованно с фактическим потребителем в `src/qg/checks.py`, а
  avoidable-набор = `{tester, deployer}`. Тесты — offline. **Тест на привязку к конкретным follow-up
  ID не вводится** (анти-паттерн R3).
- **BR-7 — Позиционирование follow-up'ов по роли.** Карта/roadmap явно отмечают **роль deployer** и
  **роль tester** как кандидаты-замены, **не** реализуемые в ORCH-118; их старт гейтится утверждением
  карты. Привязка — **по роли**, без конкретных Plane-ID (NFR-6).
- **BR-8 (R5) — Явная control-path-разметка.** Карта несёт для каждой консультации поле оси
  **(C) control-path / (P) artifact-producer** + доказательство (потребитель вывода с `file:line`).
  Разметка **проверяема** структурным тестом против `src/qg/checks.py` (BR-6, TC-13).
- **BR-9 (R5) — Явное определение «avoidable LLM control path» и поимённый целевой набор.** Карта/
  политика дают нормативное определение термина (двухбитный предикат §0-bis) и **поимённо** называют
  `{tester, deployer}` как avoidable, явно отделяя их от `reviewer` (control path, keep) и от
  `analyst/architect/developer` (не control path). Набор **проверяем** тестом (BR-6, TC-14).

## 5. Нефункциональные требования (NFR)

- **NFR-1 — Сохранение поведения (нулевая регрессия).** ORCH-118 — docs+tests only:
  `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict-ключи/схема БД — **байт-в-байт**; поведение
  конвейера 1:1; enduro-trails не затронут.
- **NFR-2 — Сохранение автономности и гибкости.** Ни инвентаризация, ни политика не должны
  предлагать решений, снижающих автономный/пакетный режим (ORCH-088/089) или гибкость; политика
  **защищает** автономность как инвариант любой будущей замены.
- **NFR-3 — Self-hosting безопасность.** Задача только **читает** код и пишет docs+tests — не
  деплоит, не рестартит прод-контейнер, не трогает `main`/force-push, не запускает процессов/сети.
- **NFR-4 — Трассируемость и сопровождаемость.** Карта привязана к коду маркерами/тестом и остаётся
  честной при эволюции кода; формат — по `docs/_standards/PIPELINE_DOCS.md` и `TRACEABILITY.md`.
- **NFR-5 — Доказательность экономии.** Цифры экономии берутся из реальной телеметрии `agent_runs`
  (модель/эффорт/токены/стоимость/время по ролям) и помечаются как **оценки** до фактического замера
  после реализации.
- **NFR-6 — Только проверяемые ссылки (анти-фабрикация, R3).** В артефактах фиксируются только
  ссылки, резолвящиеся в код/документы репозитория. Конкретные **follow-up Plane-ID не выдумываются**:
  кандидаты-замены именуются по роли; ID присваивается при заведении задачи. (Это закрывает корень
  отклонённой ревизии R2.)
- **NFR-7 (R5) — Контроль-ориентированность определений.** «LLM control path» и «avoidable»
  определяются **через потребление вывода потоком управления** (кто из `check_*` ветвится на выводе),
  а не через «есть ли вообще LLM-вызов на стадии». Любое утверждение «это avoidable LLM control path»
  обязано резолвиться в конкретный `check_*`/`_parse_*` + tool-сигнал, из которого вердикт деривируем.

## 6. Допущения и ограничения
- Единственный транспорт LLM сейчас — Claude CLI через `launcher._spawn`; прямых вызовов Anthropic API
  в `src/**` нет (подтверждается инвентаризацией).
- Model-routing не включён — все 6 ролей на `claude-opus-4-8` (ORCH-41), что упрощает оценку экономии.
- Карта — **снимок на момент задачи**, защищённый структурными тестами от тихого расхождения с кодом.
- Прецедент детерминированной замены агента уже существует и работает (`deploy-finalizer`/
  `post-deploy-monitor` в `launch_job` до `_spawn`) — это снижает архитектурный риск follow-up'ов.
- На момент анализа конкретные follow-up work item для замены ролей в backlog **не подтверждены** —
  поэтому ID не фиксируются (NFR-6).
- **(R5)** Control-path-разметка опирается на ground-truth `src/qg/checks.py` на момент задачи; при
  эволюции кода её честность держит структурный тест (TC-13/TC-14).

## 7. Критерии успеха
Карта LLM-консультаций полна и привязана к коду, и **разводит три ортогональных факта**: транспорт/слот
(«процесс Claude CLI существует», R4 §0), факт консультации, **и — control-path-ось (R5 §0-bis):
потребляется ли LLM-вывод потоком управления (`check_*` ветвится на нём) или его независимо судит
детерминированный гейт**. Термин **«avoidable LLM control path» явно определён** (двухбитный предикат)
и целевой набор **поимённо** назван `{tester, deployer}` с доказательным отделением от `reviewer`
(control path, keep) и от `analyst/architect/developer` (не control path). Каждый site классифицирован
с обоснованием, **выведенным** из этой оси; детерминизм не-агентских путей доказан (отсутствием
LLM-консультации, не отсутствием subprocess); есть упорядоченный roadmap с зависимостями/экономией/
рисками и рекомендованным первым срезом (кандидаты — по роли); есть нормативная политика; структурные
тесты зелёные и осмысленные (инвариант единственной точки транспорт-агностичен и двусторонен; control-path
-разметка сверена с `src/qg/checks.py`; avoidable-набор зафиксирован); ни один рантайм-инвариант не
тронут; раннеры замен НЕ реализованы; ни один артефакт не фиксирует непроверяемых follow-up ID.
Детальные PASS/FAIL — в `03-acceptance-criteria.md`.

## 8. Риски
- **Недо-/пере-классификация** (LLM убран там, где нужно суждение, или сохранён там, где не нужен) →
  митигирует **control-path-вывод** (§0-bis: класс выводится из (C/P)-типа и деривируемости вердикта,
  а не «на глаз») + требование «назвать конкретное суждение» для `keep-LLM` + ревью карты.
- **Конфляция «есть LLM на стадии» с «это control path»** (рецидив корня R4-блокера) → митигирует
  явная разметка оси и тест TC-13 (сверка с фактическим потребителем `check_*`).
- **Дрейф карты** относительно кода со временем → митигируют структурные тесты (BR-6), включая
  control-path-инварианты (TC-13/TC-14).
- **Преждевременная замена** в погоне за экономией ценой автономности/гибкости → инвентаризация
  отделена от реализации; первый срез — самый низкорисковый «чисто деривируемый» control path.
- **Фабрикация ссылок/ID** (рецидив дефекта R2) → митигирует NFR-6 (только проверяемые ссылки;
  follow-up'ы — по роли) и ревью. Детали техн.рисков — `10-tech-risks.md` (архитектор).
