# LLM usage policy (ORCH-118) > **Нормативный durable-документ.** Формулирует принцип использования LLM в оркестраторе, критерии > «keep vs replace» через **control-path-ось**, и нормативное **определение «avoidable LLM control > path»**. Применяется ко **всем** будущим правкам control-path'ов. Сопутствующие артефакты — > карта [`llm-call-sites.md`](llm-call-sites.md) и roadmap [`llm-determinization-roadmap.md`](llm-determinization-roadmap.md). --- ## 1. Принцип **LLM — только там, где нужно настоящее суждение.** Если решение/вердикт control-path'а есть **детерминированная функция tool-сигналов**, которые оркестратор уже вычисляет (exit-code `pytest`, smoke, `staging_check.py`, статус деплоя, наличие файлов, CI-статус), — оно должно приниматься **детерминированно**, а не консультацией LLM. LLM сохраняется там, где требуется суждение, **не сводимое** к tool-сигналу (анализ требований, архитектурное решение, написание кода, приемлемость ревью). Это защищает **автономность** (NFR-2): меньше точек, где недетерминизм/стоимость/латентность LLM встроены в поток управления, и меньше класса инцидентов «LLM-агент принял решение, которое на деле есть исполнение фиксированных команд и маппинг результата» (RCA-трек ORCH-110/111/112/113/114/117). --- ## 2. Три оси решения (ground-truth — код) 1. **consultation ≠ transport/slot.** «LLM консультируется» ⇔ решение/артефакт конвейера **потребляет суждение LLM**. Существование транспорта (`_spawn`) или слота агента (job-роли с перехватом до `_spawn`) — это **capability**, не консультация. 2. **control-path (C) ≠ artifact-producer (P)** — определяется **кодом-потребителем** вывода роли: - **(C)** LLM эмитит machine-verdict, на котором **ветвится `check_*`-гейт** → суждение входит в поток управления. - **(P)** LLM производит артефакт, а продвижение решает **детерминированный гейт** независимо (наличие файлов / CI) → суждение в control flow не входит. 3. **деривируемость вердикта** — вердикт C-консультации либо детерминированная функция tool-сигналов, либо настоящее суждение, не сводимое к exit-коду. --- ## 3. Нормативное определение «avoidable LLM control path» Это **двухбитный проверяемый предикат над `src/qg/checks.py`**, а не «удобство на глаз». Call-site является **avoidable LLM control path** тогда и только тогда, когда выполнены **оба** условия: - **(i)** это **C (control-path)** консультация — её LLM-вердикт потребляется потоком управления (`check_*`-гейт ветвится на нём: PASS → дальше / FAIL → откат); - **(ii)** вердикт **деривируем** (derivable) из tool-сигналов, которые оркестратор уже вычисляет сам — exit-code `pytest` / smoke / `staging_check.py` / статус деплоя. Если оба условия выполнены, суждение LLM не добавляет информации → консультацию можно снять без потери смысла (заменить детерминированным раннером или гибридом с LLM-фолбэком только на не-деривируемую часть). **Поимённый целевой набор** (сверен с кодом, прибит тестами TC-13/TC-14): - **avoidable LLM control paths = `{tester, deployer}`** — C **и** вердикт деривируем (`result:` = exit-code `pytest`+smoke; `staging_status:` = маппинг exit-кода `staging_check.py`). - **`reviewer`** — C, но **keep**: вердикт «приемлемость кода/решения» **НЕ деривируем** из exit-кода (настоящее суждение). Это control-path-но-keep, **не** avoidable. - **`analyst` / `architect` / `developer`** — **не** control path (**P**, artifact-producer): детерминированный гейт судит артефакт независимо. --- ## 4. Критерии решения: keep vs replace | Ситуация (по осям §2) | Решение | Класс | |-----------------------|---------|-------| | **P** — artifact-producer (детерминированный гейт судит артефакт) | **keep** LLM | `keep-LLM` | | **C**, вердикт **НЕ деривируем** (настоящее суждение) | **keep** LLM (назвать суждение) | `keep-LLM` | | **C**, вердикт **деривируем**, замена безопасна сейчас | **replace** | `replace-deterministic-now` | | **C**, вердикт деривируем, но замена позже / с предпосылками | **replace later** | `replace-later/risky` | | **C**, ядро деривируемо, но часть требует суждения | **hybrid** (детерм. ядро + LLM-фолбэк) | `needs-hybrid-fallback` | > **keep-LLM требует обоснования:** любая `keep-LLM`-запись обязана **назвать конкретное суждение**; > для C-keep — явно зафиксировать **не-деривируемость** вердикта (почему не сводится к exit-коду). --- ## 5. Требование к новым/изменённым control-path'ам (норматив) - **Обоснование против политики.** Любой **новый** или изменённый control-path, который консультирует LLM, обязан в своём ADR обосновать это против настоящей политики: показать, что он **P** (artifact judged independently) **или** **C с не-деривируемым** вердиктом. C-консультация с деривируемым вердиктом — это `avoidable`; её ввод без обоснования reviewer ловит как finding ≥P1. - **Reviewer-ось (как ORCH-079) — требование, не реализация гейта.** Политика **рекомендует** reviewer'у проверять соответствие новых control-path'ов настоящей политике; ORCH-118 **не** вводит новый Quality Gate (`QG_CHECKS`/`check_*` не меняются) — это нормативное требование процесса. - **Норматив сопровождения.** Меняешь место вызова LLM или потребителя вердикта в `src/qg/checks.py` → обнови карту [`llm-call-sites.md`](llm-call-sites.md) и эту политику **в том же PR** (анти-дрейф держат TC-13/TC-14). - **Единственный транспорт.** Единственный разрешённый транспорт LLM-консультации в `src/**` — это `launcher._spawn` (S0). Ввод второго транспорта (новый `_spawn`, импорт `anthropic`/`openai`/иного LLM-SDK, прямой HTTP Anthropic/Claude, второй model-invoking subprocess) запрещён без явного ADR; прибито тестами TC-01/TC-12. - **Реализованный срез (ORCH-115).** Снятие C-консультации с деривируемым вердиктом — это разрешённое `replace-deterministic-now`, а не ввод новой LLM-консультации. ORCH-115 снял A6/staging-status: детерминированный `src/staging_runner.py` производит `staging_status:` без `_spawn` (перехват до него, как `D1`/`D2`) — раннер **LLM не зовёт** и **второй транспорт не вводит**, поэтому инвариант «единственный транспорт S0» соблюдён (TC-12 зелёный). Это образец для последующих срезов roadmap'а.