ORCH-118 (inventory-first, docs+tests only): publish an evidence-based map of
every place the orchestrator's control flow consumes (or can consume) an LLM
judgment, mark the control-path axis (C control-path vs P artifact-producer),
define "avoidable LLM control path" as a checkable two-bit predicate, classify
each call-site, and order the deterministic-replacement roadmap. Pin the map to
code with offline structural anti-drift tests.
- docs/architecture/llm-call-sites.md — map + machine-readable inventory block
+ control-path axis + classification + keep-LLM justifications + deterministic
non-agent paths (FR-1/FR-2/FR-3/FR-8).
- docs/architecture/llm-determinization-roadmap.md — ordered candidates BY ROLE,
savings sourced from agent_runs, recommended first slice = deployer staging
(FR-4). No fabricated follow-up Plane-IDs (R3/NFR-6).
- docs/architecture/llm-usage-policy.md — normative principle, keep/replace
criteria via the axis, definition of "avoidable LLM control path" (FR-5/FR-8).
- tests/test_llm_call_site_inventory.py — TC-01/02/03/04/05/06/09/12/13/14.
- tests/test_llm_determinization_docs.py — TC-07/08/11.
- CHANGELOG.md + docs/overview/tech-quality-security.md — golden-source sync (AC-8).
Avoidable LLM control paths = {tester, deployer}; control-path-keep = {reviewer};
not-control-path (P) = {analyst, architect, developer}. Single LLM transport =
launcher._spawn (S0); no alternative transport (TC-12). Runtime untouched:
STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict keys / DB schema are
byte-for-byte; no replacement runners implemented (FR-7). Full suite: 2081 passed.
Refs: ORCH-118
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
17 KiB
LLM call-site map — inventory, control-path axis & classification (ORCH-118)
Что это. Доказательная карта каждого места, где control-path оркестратора потребляет (или способен потребить) суждение LLM. Единица инвентаря — LLM-консультация (control-path потребляет суждение LLM), не «спавн процесса / существование Claude CLI» (capability ≠ consultation, BRD §0 / R4).
Снимок, прибитый к коду. Карта — снимок; её инварианты держат структурные тесты
tests/test_llm_call_site_inventory.py(анти-дрейф). Меняешь место вызова LLM или потребителя вердикта вsrc/qg/checks.py→ обнови эту карту и политику в том же PR (норматив сопровождения).Источник истины содержательной классификации — ADR
docs/work-items/ORCH-118/06-adr/ADR-001-llm-call-site-map-and-determinization-roadmap.md(D2/D3/D4) и сквознойdocs/architecture/adr/adr-0047-llm-usage-policy-and-call-site-map.md. Нормативное определение «avoidable LLM control path» и критерии keep/replace — вllm-usage-policy.md; порядок замен — вllm-determinization-roadmap.md.
0. Три ортогональных факта (как читать карту)
Карта явно разводит три раздельных факта — их смешение было корнем блокеров R3→R5:
- Ось 1 — consultation ≠ transport/slot. «LLM-консультация» = точка, где решение/артефакт
конвейера потребляет суждение LLM. Транспорт (
_spawn) — реализация, не определение. Слот агента (job-ролиD1/D2) делает site LLM-capable, но консультация гейтится потоком управления (перехват до_spawn) → capability ≠ consultation. - Ось 2 — control-path (C) ≠ artifact-producer (P). Определяется кодом-потребителем вывода
роли в
src/qg/checks.py:- (C) control-path — LLM эмитит machine-verdict, на котором ветвится
check_*-гейт (PASS → дальше / FAIL → откат). Суждение LLM входит в поток управления. - (P) artifact-producer — LLM производит артефакт, а продвижение решает детерминированный гейт, судящий артефакт независимо (наличие файлов / CI-статус). Суждение LLM в control flow не входит.
- (C) control-path — LLM эмитит machine-verdict, на котором ветвится
- Ось 3 — деривируемость вердикта. Вердикт C-консультации либо есть детерминированная функция
tool-сигналов (exit-code
pytest/smoke/staging_check.py/деплоя), которые оркестратор уже вычисляет сам, либо требует настоящего суждения, не сводимого к exit-коду.
Avoidable LLM control path (нормативное определение —
llm-usage-policy.md): call-site, для которого выполнены оба условия — (i) это C-консультация (её LLM-вердикт потребляется потоком управления) и (ii) вердикт деривируем из tool-сигналов. Тогда суждение LLM не добавляет информации → консультацию можно снять без потери смысла.
1. Инвентарь LLM-консультаций (полный, привязан к коду)
Каждая запись несёт: id · location (file:line) · trigger · stage/owner · output artifact ·
machine-verdict key · output consumer (кто потребляет вывод роли) · est. tokens/runtime
(оценка из agent_runs) · consults-LLM · axis (C/P) · classification · rationale.
| id | location (file:line) | trigger | stage / owner | output artifact | machine-verdict key | output consumer (src/qg/checks.py) |
est. tokens/runtime (оценка) | consults-LLM | axis | classification | rationale |
|---|---|---|---|---|---|---|---|---|---|---|---|
| S0 | src/agents/launcher.py:472 (_spawn; CLI-сборка 610-614; парс токенов _monitor_agent:838) |
launch_job → _spawn для любой из 6 ролей |
— (транспорт) | — | — | — | — | транспорт (capability) | — | — | Единственный транспорт LLM-консультации в src/**; не call-site решения |
| A1 | .openclaw/agents/analyst.md |
стадия analysis |
analyst | 01-brd … 04-test-plan |
— | check_analysis_complete:33 (наличие файлов) |
~80–200k / 5–20 мин | да (через S0) | P | keep-LLM |
анализ требований / BRD/ТЗ — настоящее суждение; гейт судит лишь наличие артефактов |
| A2 | .openclaw/agents/architect.md |
стадия architecture |
architect | 06-adr/, 07 |
— | check_architecture_done:62 (наличие 06-adr/07) |
~80–200k / 5–20 мин | да (через S0) | P | keep-LLM |
архитектурное решение / ADR — настоящее суждение |
| A3 | .openclaw/agents/developer.md |
стадия development |
developer | код + PR | — | check_ci_green:82 (+ check_branch_mergeable:657) — CI/merge |
~150–400k / 10–40 мин | да (через S0) | P | keep-LLM |
написание кода — настоящее суждение; гейт судит CI/merge, не самоотчёт |
| A4 | .openclaw/agents/reviewer.md |
стадия review |
reviewer | 12-review.md |
verdict: |
check_reviewer_verdict:336 (verdict:) |
~100–300k / 5–25 мин | да (через S0) | C | keep-LLM |
control path, но вердикт «приемлемость кода/решения» НЕ деривируем из exit-кода — настоящее суждение |
| A5 | .openclaw/agents/tester.md |
стадия testing |
tester | 13-test-report.md |
result: |
check_tests_passed:182 → _parse_tests_verdict:226 (result:) |
~60–150k / 5–20 мин | да (через S0) | C | needs-hybrid-fallback |
avoidable: PASS/FAIL = exit-code pytest+smoke (деривируем); LLM нужен лишь на триаж падений / маппинг TC↔критерии |
| A6 | .openclaw/agents/deployer.md |
стадии deploy-staging / deploy |
deployer | 15-staging-log.md / 14-deploy-log.md |
staging_status: / deploy_status: |
check_staging_status:599 → _parse_staging_status:538 (staging_status:); check_deploy_status:473 → _parse_deploy_status:413 (deploy_status:) |
~40–120k / 3–15 мин | да (через S0) | C | replace-deterministic-now |
avoidable: staging-вердикт = маппинг exit-кода staging_check.py; прод уже детерминирован Phase A/B/C (ORCH-036) |
| D1 | src/agents/launcher.py:389 (перехват в launch_job до _spawn; «Not an LLM spawn» 407) |
post-deploy edge | deploy-finalizer | jobs-row | — | — | — (детерминированный) | нет (слот, перехват до _spawn) |
— | already-deterministic (эталон) |
Занимает слот агента, но LLM не консультируется — рабочий прецедент замены |
| D2 | src/agents/launcher.py:394 (перехват в launch_job до _spawn; «Not an LLM spawn» 428) |
post-deploy observation | post-deploy-monitor | jobs-row | — | — | — (детерминированный) | нет (слот, перехват до _spawn) |
— | already-deterministic (эталон) |
Тик наблюдения; LLM не консультируется |
Итог (поимённо).
avoidable LLM control paths = {tester, deployer}; control-path-но-keep ={reviewer}; не-control-path (P) ={analyst, architect, developer}; already-deterministic-эталон ={deploy-finalizer, post-deploy-monitor}.
1.1 Машинно-читаемый блок инвентаря
Стабильный заголовок таблицы (
id | role | location | output_consumer | consults_llm | axis | avoidable | classification) парситсяtests/test_llm_call_site_inventory.py(split по|, без новых зависимостей) и сверяется с кодом (TC-03/04/05/13/14). Не менять заголовок и значения без синхронной правки кода/тестов.
| id | role | location | output_consumer | consults_llm | axis | avoidable | classification |
|---|---|---|---|---|---|---|---|
| S0 | _spawn | src/agents/launcher.py:472 | - | transport | - | - | - |
| A1 | analyst | .openclaw/agents/analyst.md | check_analysis_complete | yes | P | no | keep-LLM |
| A2 | architect | .openclaw/agents/architect.md | check_architecture_done | yes | P | no | keep-LLM |
| A3 | developer | .openclaw/agents/developer.md | check_ci_green | yes | P | no | keep-LLM |
| A4 | reviewer | .openclaw/agents/reviewer.md | check_reviewer_verdict | yes | C | no | keep-LLM |
| A5 | tester | .openclaw/agents/tester.md | _parse_tests_verdict | yes | C | yes | needs-hybrid-fallback |
| A6 | deployer | .openclaw/agents/deployer.md | _parse_staging_status | yes | C | yes | replace-deterministic-now |
| D1 | deploy-finalizer | src/agents/launcher.py:389 | - | no | - | - | already-deterministic |
| D2 | post-deploy-monitor | src/agents/launcher.py:394 | - | no | - | - | already-deterministic |
1.2 keep-LLM — названное суждение (обоснование)
Для каждой
keep-LLM-записи назван конкретный вид суждения, ради которого LLM сохраняется. Для C-keep (reviewer) обоснование явно фиксирует НЕ-деривируемость вердикта (почему не сводится к exit-коду). Парсится TC-05 (- role: текст).
- analyst: анализ требований и написание BRD/ТЗ — настоящее суждение; детерминированный гейт
check_analysis_completeсудит лишь наличие файлов, не их содержательное качество. - architect: архитектурное решение и ADR — настоящее суждение о компромиссах/инвариантах;
check_architecture_doneсудит лишь наличие 06-adr/07. - developer: написание кода — настоящее суждение; гейт
check_ci_greenсудит CI/merge, а не самоотчёт агента. - reviewer: «приемлемость кода/решения» — настоящее суждение, которое НЕ деривируемо (not derivable) из exit-кода
pytest/smoke/деплоя; в отличие от tester/deployer вердикт reviewer'а не сводится к tool-сигналу, поэтому это control-path-но-keep, а не avoidable.
2. Таксономия классификации (4 класса, выведена из осей)
Четыре взаимоисключающих класса; класс выводится из осей §0 (а не постулируется):
keep-LLM— нужно настоящее суждение (обязательно назвать конкретное суждение, §1.2).replace-deterministic-now— безопасная детерминированная замена сейчас.replace-later/risky— замена возможна позже / с предпосылками.needs-hybrid-fallback— детерминированное ядро + LLM-фолбэк только на суждение.
Правило вывода:
P → keep-LLM; C + не-деривируемый вердикт → keep-LLM;
C + деривируемый вердикт → replace-* / needs-hybrid-fallback (= avoidable).
deploy-finalizer/post-deploy-monitor помечены already-deterministic — вне таксономии замен
(эталон: LLM не консультируется, перехват до _spawn).
3. Детерминизм не-агентских control-path'ов (доказательство, FR-3 / AC-3)
Эти пути не консультируют LLM (ни через _spawn-транспорт, ни альтернативным транспортом). ⚠️ Они
спавнят subprocess'ы (git/pytest/docker/ssh/сканеры/staging_check.py) — это
детерминированные инструменты, не LLM: доказательство детерминизма — отсутствие LLM-транспорта,
а не отсутствие subprocess (дискриминатор §0). Проверяется TC-02.
| Путь / модуль | file:line (якорь) |
Природа |
|---|---|---|
| Маршрутизация стадий | src/stages.py::STAGE_TRANSITIONS:12, advance_stage в src/stage_engine.py |
статический словарь + детерминированная функция |
| Реестр Quality Gate | src/qg/checks.py::QG_CHECKS:812 (14 имён) |
словарь имя→функция |
Все check_* |
src/qg/checks.py (33/62/82/182/336/473/599/657, …) |
файловые/HTTP/exit-code проверки |
Парсеры вердиктов _parse_* |
src/qg/checks.py:226/413/538 через src/frontmatter.py::parse_frontmatter |
YAML-frontmatter парс (читают, не производят вердикт) |
| Классификатор ошибок | src/error_classifier.py |
regex по строкам |
| Под-гейты | src/{security_gate,merge_gate,coverage_gate,staging_verdict}.py |
сканеры/pytest --cov/git/маппинг exit-кодов |
| Self-deploy Phase A/B/C | src/self_deploy.py |
детерминированный detached-деплой (ORCH-036) |
| Сериализация / владение | src/{serial_gate,transition_lease,reconciler,job_reaper}.py |
FIFO-гейт / durable-lease / CAS / reaper |
Любая найденная неожиданная LLM-консультация в этих путях добавляется в инвентарь §1 и классифицируется §2 (тогда TC-02 станет красным — точка дрейфа).
4. Скоуп и анти-дрейф
- Docs + tests only (ORCH-118).
STAGE_TRANSITIONS/ реестр и именаQG_CHECKS/check_*/ machine-verdict-ключи (verdict:/result:/staging_status:/deploy_status:/security_status:/coverage_status:) / схема БД — байт-в-байт не тронуты. Раннеры замен не реализованы (см. roadmap — follow-up'ы по роли, без Plane-ID). - Анти-дрейф тесты:
tests/test_llm_call_site_inventory.py(TC-01…TC-06, TC-09, TC-12, TC-13, TC-14) иtests/test_llm_determinization_docs.py(TC-07/08/11). Дискриминатор всех проверок — «консультирует LLM», а не «спавнит subprocess». - Связанные документы:
llm-usage-policy.md,llm-determinization-roadmap.md.