Files
orchestrator/docs/work-items/ORCH-118/01-brd.md
claude-bot 55c13abb9a
All checks were successful
CI / test (push) Successful in 1m9s
analyst(ET): auto-commit from analyst run_id=725
2026-06-15 23:29:04 +03:00

28 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-118 analysis analyst ready-for-review 2026-06-15 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-ревью. Рецензент подтвердил: follow-up'ы по роли / TBD — ОК, 00-business-request.md=TBD (конвенция репо) — НЕ блокер, скоуп docs+tests — ОК; менять их не нужно. Закрывается один блокер: инвариант «места вызова LLM» смешивал факт «существует процесс Claude CLI / спавнится subprocess» (транспорт/механизм) с фактом «на control-path происходит LLM-консультация — поток управления потребляет суждение LLM» (семантическая единица, ради которой и существует задача «replace avoidable LLM control paths»). R4 разводит эти два понятия во всех артефактах (см. новый блок «Единица анализа» ниже, уточнённые BR-1/BR-3/BR-6, FR-1/FR-3/FR-6, AC-1/AC-3/AC-6, TC-01/TC-02 + новый TC-12). Содержательная классификация ролей и весь R3-материал (анти-фабрикация ID) — без изменений.


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, код прямо помечает «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 матчинг).


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).
  • Все остальные 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 — это рабочий прецедент детерминированной замены агента).
  • Среди 6 LLM-ролей tester и deployer по факту почти полностью исполняют детерминированные команды (pytest, staging_check.py, exit-code → вердикт; прод-деплой на self-hosting уже идёт детерминированным путём Phase A/B/C, ORCH-036), завёрнутые в LLM «для удобства».

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

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

2. Объём (scope)

В объёме

  • BR-1 Полная инвентаризация всех мест вызова LLM и всех ролей-агентов (карта call-site'ов).
  • BR-2 Классификация каждого call-site в один из 4 классов (keep / replace-now / replace-later / hybrid-fallback) с явным обоснованием.
  • 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-тесты, прибивающие инварианты карты к коду (транспорт-агностичный двусторонний инвариант: единственный транспорт LLM-консультации _spawn и отсутствие иного LLM-транспорта; детерминированные модули не консультируют LLM; карта покрывает все промпты; тотальность классификации) — анти-дрейф.
  • BR-7 Явно позиционировать роль deployer и роль tester как кандидаты-follow-up для детерминированной замены — по роли, без привязки к конкретным Plane-ID (см. NFR-6).

Вне объёма

  • Реализация детерминированных раннеров 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-ключ (если есть), оценка токенов/времени, признак capability-vs-consultation (LLM-capable vs фактически консультирует, §0.3). Проверяемо: каждый file:line резолвится в реальный код.
  • BR-2 — Классификация. Каждому call-site присвоить ровно один класс из таксономии: keep-LLM (нужно настоящее суждение), replace-deterministic-now (безопасная замена сейчас), replace-later/risky (замена позже / рискованно), needs-hybrid-fallback (детерминированное ядро + LLM-фолбэк на суждение). Для keep-LLMназвать конкретное суждение, ради которого LLM сохраняется.
  • 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/обратимости. Явно указать рекомендованный первый срез и обоснование выбора. Привязка к follow-up задаче — по роли; конкретный Plane-ID НЕ фиксируется (заводится отдельно, NFR-6).
  • BR-5 — Политика использования LLM. Нормативный durable-документ: «LLM — только там, где требуется настоящее суждение»; критерии решения keep vs replace; требование к новым/изменённым control-path'ам обосновывать любое использование LLM против этой политики.
  • BR-6 — Анти-дрейф структурными тестами. Тесты, привязывающие инварианты карты к коду. Инвариант единственной точки формулируется транспорт-агностично и двусторонне (R4, §0): (i) единственный транспорт LLM-консультации в src/**_spawn; и (ii) отсутствует любой иной LLM-транспорт (импорт anthropic/openai/LLM-SDK, прямой HTTP-эндпоинт Anthropic/Claude, второй model-invoking subprocess-сборщик --system-prompt/--model) — это и закрывает дыру «один _spawn зелёный, а рядом проросла новая консультация другим транспортом». Дискриминатор теста — «консультирует LLM», а не «спавнит subprocess» (прочие subprocess git/pytest/docker/ssh/сканеров явно исключены из матчинга). Плюс: перечисленные детерминированные модули/job-роли не несут LLM-консультации; карта перечисляет ровно те 6 промптов, что лежат в .openclaw/agents/; классификация покрывает все call-site'ы по одному разу. Тесты — offline (без сети/LLM/subprocess-к-модели). Тест на привязку к конкретным follow-up ID не вводится (анти-паттерн: прибивал бы карту к непроверяемым ID, R3).
  • BR-7 — Позиционирование follow-up'ов по роли. Карта/roadmap явно отмечают роль deployer и роль tester как кандидаты-замены, не реализуемые в ORCH-118; их старт гейтится утверждением карты. Привязка — по роли, без конкретных Plane-ID (NFR-6).

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.)

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).

7. Критерии успеха

Карта LLM-консультаций полна и привязана к коду, и разводит транспорт/слот («процесс Claude CLI существует») от факта консультации («поток управления потребляет суждение LLM») (R4, §0); каждый site классифицирован с обоснованием; детерминизм не-агентских путей доказан (отсутствием LLM-консультации, не отсутствием subprocess); есть упорядоченный roadmap с зависимостями/экономией/рисками и рекомендованным первым срезом (кандидаты — по роли); есть нормативная политика; структурные тесты зелёные и осмысленные — инвариант единственной точки транспорт-агностичен и двусторонен (единственный транспорт _spawn и отсутствие иного LLM-транспорта); ни один рантайм-инвариант не тронут; раннеры замен НЕ реализованы; ни один артефакт не фиксирует непроверяемых follow-up ID. Детальные PASS/FAIL — в 03-acceptance-criteria.md.

8. Риски

  • Недо-/пере-классификация (LLM убран там, где нужно суждение, или сохранён там, где не нужен) → митигирует требование «назвать конкретное суждение» для keep-LLM и ревью карты.
  • Дрейф карты относительно кода со временем → митигируют структурные тесты (BR-6).
  • Преждевременная замена в погоне за экономией ценой автономности/гибкости → инвентаризация отделена от реализации; первый срез — самый низкорисковый.
  • Фабрикация ссылок/ID (рецидив дефекта R2) → митигирует NFR-6 (только проверяемые ссылки; follow-up'ы — по роли) и ревью. Детали техн.рисков — 10-tech-risks.md (архитектор).