architect(ET): auto-commit from architect run_id=727
All checks were successful
CI / test (push) Successful in 1m7s
All checks were successful
CI / test (push) Successful in 1m7s
This commit is contained in:
@@ -416,6 +416,34 @@ ORCH-079 синхронизирует витрину с кодом и закры
|
||||
- ADR: [adr-0023](adr/adr-0023-overview-docs-reviewer-axis-and-epic52-close.md); детально —
|
||||
`docs/work-items/ORCH-079/06-adr/ADR-001-readme-sync-and-reviewer-overview-docs-axis.md`.
|
||||
|
||||
#### Карта LLM-консультаций + политика использования LLM (ORCH-118 — design)
|
||||
Зонтичный follow-up RCA-трека ORCH-114/117: оркестратор не имел нормативного критерия «где LLM нужен,
|
||||
а где это avoidable control path» и карты мест вызова LLM, прибитой к коду. ORCH-118 — **inventory +
|
||||
карта + roadmap + политика + структурные тесты** (реализация детерминированных раннеров — follow-up'ы
|
||||
**по роли**, без выдуманных Plane-ID). Это **docs + tests only**: `STAGE_TRANSITIONS` / реестр и имена
|
||||
`QG_CHECKS`/`check_*` / machine-verdict-ключи / схема БД — **байт-в-байт не тронуты**; kill-switch не
|
||||
нужен (нет рантайм-поведения), как ORCH-077/079/101/102/103/011.
|
||||
- **Три ортогональных оси (ground-truth — код):** (1) consultation ≠ transport/slot (единственный
|
||||
транспорт LLM-консультации в `src/**` — `launcher._spawn`, `launcher.py:472/610-614`; иного нет;
|
||||
D1/D2 `deploy-finalizer`/`post-deploy-monitor` занимают слот, но перехватываются в `launch_job` до
|
||||
`_spawn`, `launcher.py:389/394` — консультации нет); (2) **control-path (C) ≠ artifact-producer (P)**
|
||||
по коду-потребителю в `src/qg/checks.py` (C: `check_*` ветвится на LLM-вердикте; P: детерминированный
|
||||
гейт судит артефакт независимо — файлы/CI); (3) деривируемость вердикта из tool-сигналов.
|
||||
- **Нормативное определение** «avoidable LLM control path» = двухбитный предикат: C-консультация **И**
|
||||
вердикт деривируем из tool-сигналов. Целевой набор (поимённо, доказательно): **avoidable =
|
||||
{tester, deployer}**; control-path-но-keep = `{reviewer}`; не-control-path (P, keep) =
|
||||
`{analyst, architect, developer}`; уже детерминированы = `{deploy-finalizer, post-deploy-monitor}`.
|
||||
- **Документы (durable, `docs/architecture/`):** `llm-call-sites.md` (карта + control-path-разметка +
|
||||
классификация, снимок, прибитый тестами), `llm-determinization-roadmap.md` (порядок замен; первый
|
||||
срез — **deployer staging-status**, чистый маппинг exit-кода `staging_check.py`; прод уже
|
||||
детерминирован Phase A/B/C ORCH-036), `llm-usage-policy.md` (нормативный принцип «LLM — только где
|
||||
нужно настоящее суждение»). Анти-дрейф — `tests/test_llm_call_site_inventory.py` (offline; включая
|
||||
control-path-инвариант сверки с `src/qg/checks.py` и фиксацию avoidable-набора).
|
||||
- **Норматив сопровождения:** менял места вызова LLM **или** потребителя вердикта в `src/qg/checks.py`
|
||||
→ обнови карту/разметку и политику в том же PR.
|
||||
- ADR: [adr-0047](adr/adr-0047-llm-usage-policy-and-call-site-map.md); детально —
|
||||
`docs/work-items/ORCH-118/06-adr/ADR-001-llm-call-site-map-and-determinization-roadmap.md`.
|
||||
|
||||
### Модель и эффорт по ролям (ORCH-41, валидация ORCH-74)
|
||||
Модель и `--effort` каждого агента берутся из config (`src/config.py`), резолвятся `launcher.resolve_agent_model` / `resolve_agent_effort` по приоритету **project-override (`projects_json` `agent_models`/`agent_efforts`) > `ORCH_AGENT_MODEL_<AGENT>`/`ORCH_AGENT_EFFORT_<AGENT>` > `*_default` > CLI-дефолт (без флага)**. **Эффорт (ORCH-081):** ниже `*_default` добавлен непустой **per-role floor** — class-default поля `agent_effort_<role>` из `config.py` (его пустой env перебить не может). Floor — строго последний уровень (ниже default) и срабатывает ТОЛЬКО когда все уровни пусты, поэтому пустые прод-`ORCH_AGENT_EFFORT_*=` (которые pydantic трактует как явное `''` и обнуляют дефолт) больше не приводят к запуску без `--effort`: каждая роль получает свой канонический пол (developer=`xhigh`, tester/deployer=`medium`, прочие=`high`). Непустой явный конфиг по-прежнему побеждает floor; опечатка вне `VALID_EFFORTS` дропается валидацией ДО floor (never-break, не маскируется). См. `docs/work-items/ORCH-081/06-adr/ADR-001-effort-resolution-floor.md`. frontmatter `model:` в `.openclaw/agents/*.md` **удалён** (ORCH-74 G1) — он был мёртвой/лживой декларацией (launcher его не читает); config — единственный источник правды о модели. Model-routing (G3) НЕ включён — все 6 агентов на `claude-opus-4-8`.
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
---
|
||||
work_item: ORCH-118
|
||||
stage: architecture
|
||||
author_agent: architect
|
||||
status: accepted
|
||||
created_at: 2026-06-15
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# adr-0047: Нормативная политика использования LLM + карта call-site'ов (control-path-ось «avoidable»)
|
||||
|
||||
> **Сквозной (cross-cutting) ADR.** Агрегирует решение ORCH-118, влияющее на **весь** оркестратор:
|
||||
> нормативная политика использования LLM, три ортогональных оси, определение «avoidable LLM control
|
||||
> path» и снимок-карта LLM-консультаций, прибитая к коду структурными тестами. Локальная детализация —
|
||||
> `docs/work-items/ORCH-118/06-adr/ADR-001-llm-call-site-map-and-determinization-roadmap.md`.
|
||||
|
||||
## Статус
|
||||
Accepted
|
||||
|
||||
## Контекст
|
||||
|
||||
RCA-цепочка ORCH-114/117 (и 110/111/112/113) показала корневой класс: у side-effectful и решающих
|
||||
control-path'ов не было единого детерминированного владения; местами решение брал LLM-агент «потому
|
||||
что удобно», хотя по сути это исполнение фиксированных команд + маппинг результата — лишний
|
||||
недетерминизм, задержка и расход токенов в точке ветвления.
|
||||
|
||||
Оркестратор не имел **нормативного критерия** «где LLM нужен, а где это avoidable control path» и
|
||||
**карты** мест вызова LLM, прибитой к коду. Без них любая будущая правка control-path'а могла снова
|
||||
ввести LLM «на удобстве», а «вслепую» убирать LLM нельзя — часть путей несёт настоящее суждение
|
||||
(анализ, архитектура, написание кода, ревью).
|
||||
|
||||
**Ground-truth кода (ORCH-118, сверено):** единственный транспорт LLM-консультации в `src/**` —
|
||||
`launcher._spawn` (`launcher.py:472`, CLI `610-614`); иного LLM-транспорта нет (нет SDK-импортов /
|
||||
прямого HTTP Anthropic / второго сборщика). 6 ролей-агентов консультируют через него; D1/D2
|
||||
(`deploy-finalizer`/`post-deploy-monitor`) перехватываются в `launch_job` **до** `_spawn`
|
||||
(`launcher.py:389/394`) — слот есть, консультации нет. Потребитель вывода каждой роли — конкретный
|
||||
`check_*`/`_parse_*` в `src/qg/checks.py`.
|
||||
|
||||
## Решение
|
||||
|
||||
### D1 — Три ортогональных оси (нормативно для всего оркестратора)
|
||||
|
||||
1. **consultation ≠ transport/slot** — «потребляет суждение LLM» ≠ «спавнит процесс / занимает слот
|
||||
агента» (capability ≠ consultation).
|
||||
2. **control-path (C) ≠ artifact-producer (P)** — определяется кодом-потребителем: C — `check_*`
|
||||
ветвится на machine-verdict, написанном LLM; P — детерминированный гейт судит артефакт независимо
|
||||
(файлы/CI).
|
||||
3. **деривируемость вердикта** — вердикт C-консультации либо детерминированная функция tool-сигналов
|
||||
(exit-code `pytest`/smoke/`staging_check.py`/деплоя), либо настоящее суждение.
|
||||
|
||||
### D2 — Нормативное определение «avoidable LLM control path»
|
||||
|
||||
> Call-site — **avoidable LLM control path** ⟺ **(i)** C-консультация (LLM-вердикт потребляется
|
||||
> потоком управления) **И (ii)** вердикт деривируем из tool-сигналов, которые оркестратор уже
|
||||
> вычисляет → LLM не добавляет информации.
|
||||
|
||||
Целевой набор (доказательно из `src/qg/checks.py`): **avoidable = {tester, deployer}**;
|
||||
control-path-но-keep = `{reviewer}`; не-control-path (P, keep) = `{analyst, architect, developer}`;
|
||||
уже детерминированы (вне консультаций) = `{deploy-finalizer, post-deploy-monitor}`.
|
||||
|
||||
### D3 — Нормативная политика использования LLM (`docs/architecture/llm-usage-policy.md`)
|
||||
|
||||
Принцип: **«LLM — только там, где требуется настоящее суждение».** Критерий keep vs replace —
|
||||
через оси D1 (является ли путь control path; деривируем ли вердикт; обратимость; влияние на
|
||||
автономность NFR-2). **Требование:** любая новая/изменённая control-path-консультация обязана
|
||||
обосновать использование LLM против этой политики; reviewer контролирует это как обзорную ось
|
||||
(в духе ORCH-079) — **как требование, не как новый машинный гейт**.
|
||||
|
||||
### D4 — Карта как снимок, прибитый к коду
|
||||
|
||||
`docs/architecture/llm-call-sites.md` — инвентарь + control-path-разметка + классификация со
|
||||
схемой полей и машинным блоком (детали — work-item ADR-001 D2/D4). Структурные тесты
|
||||
`tests/test_llm_call_site_inventory.py` (offline) держат инварианты: транспорт-агностичный
|
||||
двусторонний инвариант единственной точки, отсутствие консультации в детерминированных путях,
|
||||
control-path-разметка сверена с `src/qg/checks.py`, avoidable-набор = `{tester, deployer}`.
|
||||
|
||||
### D5 — Roadmap детерминизации (`docs/architecture/llm-determinization-roadmap.md`)
|
||||
|
||||
Рекомендованный первый срез — **deployer (staging-status)** (`replace-deterministic-now`: чистый
|
||||
маппинг exit-кода `staging_check.py`; прод уже детерминирован Phase A/B/C ORCH-036; опора на
|
||||
прецедент D1/D2). Затем — **tester-гибрид** (`needs-hybrid-fallback`). Кандидаты — **по роли**,
|
||||
без конкретных Plane-ID (NFR-6).
|
||||
|
||||
### D6 — Скоуп и инварианты (нормативно)
|
||||
|
||||
ORCH-118 — **docs + tests only**: `STAGE_TRANSITIONS` / реестр и имена `QG_CHECKS`/`check_*` /
|
||||
machine-verdict-ключи / схема БД — **байт-в-байт не тронуты**; раннеры замен не реализуются;
|
||||
follow-up Plane-ID не фиксируются. Self-hosting-безопасно (только чтение кода + запись docs/tests).
|
||||
|
||||
**Норматив сопровождения (durable):** менял места вызова LLM **или** потребителя вердикта в
|
||||
`src/qg/checks.py` → обнови карту/разметку и политику в **том же PR** (иначе тесты D4 красные).
|
||||
|
||||
## Альтернативы
|
||||
- **Машинный гейт-enforcement политики (новый QG)** — отвергнуто: политика нормативно-описательная,
|
||||
как ось трассировки ORCH-078; новый QG увеличил бы поверхность риска без необходимости (FR-6 §QG).
|
||||
- **Реализация раннеров в этой же задаче** — отвергнуто: inventory-first по требованию заказчика;
|
||||
«вслепую» убирать LLM рискованно без утверждённой карты.
|
||||
- **Привязка к конкретным follow-up ID** — отвергнуто (NFR-6, корень отклонённой R2).
|
||||
|
||||
## Последствия
|
||||
- **+** Единый нормативный критерий и код-привязанная карта закрывают класс «LLM на удобстве» и
|
||||
делают замены предсказуемыми; автономность защищена политикой.
|
||||
- **−** Карта — снимок: эволюция `src/qg/checks.py` требует со-обновления карты (держится тестами).
|
||||
*Митигейшн:* запланированный норматив сопровождения, тест указывает точку дрейфа.
|
||||
- **Откат:** удаление/правка `docs/architecture/llm-*.md` + тест-файла + секции README; рантайм не
|
||||
затронут.
|
||||
|
||||
## Ссылки
|
||||
- Work-item ADR: `docs/work-items/ORCH-118/06-adr/ADR-001-llm-call-site-map-and-determinization-roadmap.md`
|
||||
- BRD/TRZ/AC: `docs/work-items/ORCH-118/{01-brd,02-trz,03-acceptance-criteria}.md`
|
||||
- Сверено по коду: `src/agents/launcher.py`, `src/qg/checks.py`, `.openclaw/agents/*.md`
|
||||
- Связанные: ORCH-036 (детерминированный self-deploy), ORCH-061 (`staging_verdict`),
|
||||
ORCH-077/079 (docs/prompts-only прецедент + reviewer-ось обзорных доков), ORCH-114/117 (RCA-трек)
|
||||
</content>
|
||||
Reference in New Issue
Block a user