Files
orchestrator/docs/architecture/llm-call-sites.md
claude-bot 9710d5f80d
All checks were successful
CI / test (push) Successful in 1m8s
CI / test (pull_request) Successful in 1m10s
docs(llm): LLM call-site map, control-path axis, roadmap & usage policy + anti-drift tests
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>
2026-06-16 00:13:07 +03:00

17 KiB
Raw Blame History

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. Ось 1 — consultation ≠ transport/slot. «LLM-консультация» = точка, где решение/артефакт конвейера потребляет суждение LLM. Транспорт (_spawn) — реализация, не определение. Слот агента (job-роли D1/D2) делает site LLM-capable, но консультация гейтится потоком управления (перехват до _spawn) → capability ≠ consultation.
  2. Ось 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 не входит.
  3. Ось 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-brd04-test-plan check_analysis_complete:33 (наличие файлов) ~80200k / 520 мин да (через S0) P keep-LLM анализ требований / BRD/ТЗ — настоящее суждение; гейт судит лишь наличие артефактов
A2 .openclaw/agents/architect.md стадия architecture architect 06-adr/, 07 check_architecture_done:62 (наличие 06-adr/07) ~80200k / 520 мин да (через S0) P keep-LLM архитектурное решение / ADR — настоящее суждение
A3 .openclaw/agents/developer.md стадия development developer код + PR check_ci_green:82 (+ check_branch_mergeable:657) — CI/merge ~150400k / 1040 мин да (через S0) P keep-LLM написание кода — настоящее суждение; гейт судит CI/merge, не самоотчёт
A4 .openclaw/agents/reviewer.md стадия review reviewer 12-review.md verdict: check_reviewer_verdict:336 (verdict:) ~100300k / 525 мин да (через 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:) ~60150k / 520 мин да (через 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:) ~40120k / 315 мин да (через 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.