Files
orchestrator/docs/work-items/ORCH-118/02-trz.md
claude-bot bc5d550965
All checks were successful
CI / test (push) Successful in 1m8s
analyst(ET): auto-commit from analyst run_id=724
2026-06-15 23:17:18 +03:00

169 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
work_item: ORCH-118
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-15
model_used: claude-opus-4-8
---
# 02 — ТЗ (TRZ): ORCH-118 — replace avoidable LLM control paths with deterministic implementations
Work Item: **ORCH-118** · Repo: **orchestrator** · Стадия: analysis
> ТЗ описывает **что** должно измениться и **где** (артефакты/контракты/тесты), выведено из BRD и
> фактического кода. **Как** (точная структура/размещение документов карты, формат классификации,
> схема структурных тестов) — решает архитектор в `06-adr/`. ТЗ фиксирует требования и границы.
>
> ⚠️ **Скоуп — inventory + классификация + roadmap + политика + структурные тесты.** Реализация
> детерминированных раннеров — **вне скоупа** (FR-7). Это **docs + tests only**: `src/**`-рантайм не
> меняется.
>
> 📌 **Follow-up'ы — по роли, без выдуманных Plane-ID** (R3, NFR-6). Конкретные ID (напр.
> `ORCH-115`/`ORCH-116`) в артефактах **не фиксируются** — этих work item нет в репо/подтверждённом
> backlog; ID присваивается при заведении задачи.
---
## 1. Сводка изменения
Выпустить **доказательную карту** всех мест вызова LLM в оркестраторе с классификацией и
упорядоченным roadmap'ом детерминированных замен, а также нормативную **политику использования LLM**;
прибить инварианты карты к коду набором **структурных тестов**. Реализация замен не входит. Все
рантайм-контракты (`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключи / схема БД) —
**не меняются**.
Опорный факт инвентаризации (ground-truth кода на момент задачи; line-привязки уточняет карта):
| # | Call-site (LLM-capable) | Где | Что делает |
|---|--------------------------|-----|------------|
| S0 | **Единственная точка запуска** | `src/agents/launcher.py::_spawn` (сборка `CLAUDE_BIN --print … --system-prompt "$(cat …)"` + `subprocess.Popen`) | запускает любую из 6 ролей |
| A1 | analyst | промпт `.openclaw/agents/analyst.md`, стадия `analysis` | анализ бизнес-запроса → 0104 |
| A2 | architect | `.openclaw/agents/architect.md`, стадия `architecture` | архитектурные решения → 06-adr |
| A3 | developer | `.openclaw/agents/developer.md`, стадия `development` | реализация + PR |
| A4 | reviewer | `.openclaw/agents/reviewer.md`, стадия `review` | ревью → `12-review.md` (`verdict:`) |
| A5 | tester | `.openclaw/agents/tester.md`, стадия `testing` | `pytest`+smoke → `13-test-report.md` (`result:`) |
| A6 | deployer | `.openclaw/agents/deployer.md`, стадии `deploy-staging`/`deploy` | `staging_check.py`/exit-code → `15`/`14` логи |
| D1 | deploy-finalizer | `launch_job` перехват **до** `_spawn` (`launcher.launch_job`) | детерминированный (LLM не запускается) |
| D2 | post-deploy-monitor | `launch_job` перехват **до** `_spawn` (`launcher.launch_job`) | детерминированный (LLM не запускается) |
> Не-агентские control-path'ы (маршрутизация `advance_stage`, `QG_CHECKS`/`check_*`/`_parse_*`,
> `error_classifier`, `serial_gate`/`merge_gate`/`coverage_gate`/`security_gate`/`staging_verdict`/
> `review_parse`/`frontmatter`, `self_deploy` Phase A/B/C) — **уже детерминированы** (FR-3).
## 2. Задействованные модули / пути
| Путь | Действие |
|------|----------|
| `src/agents/launcher.py` | **читать** (инвентарь S0/D1/D2; `_spawn`, `launch_job`, `AGENT_CONFIGS`, `resolve_agent_model/effort`) — **не менять** |
| `.openclaw/agents/{analyst,architect,developer,reviewer,tester,deployer}.md` | **читать** (инвентарь 6 ролей) — **не менять** |
| `src/stages.py`, `src/stage_engine.py` | **читать** (доказать детерминизм маршрутизации) — **не менять** |
| `src/qg/checks.py` | **читать** (`QG_CHECKS`/`check_*`/`_parse_*` — детерминизм) — **не менять** |
| `src/{serial_gate,merge_gate,coverage_gate,security_gate,staging_verdict,review_parse,error_classifier,frontmatter,self_deploy,post_deploy,transition_lease,reconciler,job_reaper}.py` | **читать** (детерминированные leaf'ы — доказательная база) — **не менять** |
| `src/usage.py`, `src/db.py` (`agent_runs`) | **читать** (источник оценок экономии токенов/времени) — **не менять** |
| `docs/architecture/llm-call-sites.md` *(имя — пример; финально решает архитектор)* | **создать**: карта call-site'ов + классификация (FR-1/FR-2/FR-3) |
| `docs/architecture/llm-determinization-roadmap.md` *(имя — пример)* | **создать**: упорядоченный roadmap (FR-4) |
| `docs/architecture/llm-usage-policy.md` *(имя — пример)* | **создать**: нормативная политика (FR-5) |
| `docs/work-items/ORCH-118/06-adr/ADR-001-*.md` | **создать** (архитектор): фиксация карты/таксономии/первого среза как ADR |
| `tests/test_llm_call_site_inventory.py` *(имя — пример)* | **создать**: структурные анти-дрейф тесты (FR-6) |
| `docs/architecture/README.md`, `docs/overview/*`, `CHANGELOG.md` | **обновить** (ссылка на карту/политику; норматив golden-source) |
> Документы карты/политики целесообразно разместить в `docs/architecture/` (durable, сквозное), а не
> только в `docs/work-items/ORCH-118/` — окончательное размещение/формат решает архитектор.
## 3. Функциональные требования
### FR-1 — Полнота и привязка инвентаря (BR-1)
Карта перечисляет **каждый** LLM-capable call-site: `S0` (единственный `_spawn`), `A1…A6` (6 ролей),
`D1/D2` (детерминированные job-роли — как доказательство паттерна). Поля записи: `id`, `location`
(`file:line`), `trigger`, `stage/owner`, `output artifact`, `machine-verdict key` (если есть),
`est. tokens/runtime`, `classification`, `rationale`, `dependency`, `risk`. Каждый `file:line`
обязан резолвиться в реальный код. Инвариант: иных мест запуска LLM в `src/**`, кроме `S0`, нет — и
это подтверждается тестом FR-6(a).
### FR-2 — Таксономия классификации (BR-2)
Ровно 4 взаимоисключающих класса с определениями:
- `keep-LLM` — нужно настоящее суждение; **обязательно назвать** конкретное суждение.
- `replace-deterministic-now` — безопасная детерминированная замена сейчас.
- `replace-later/risky` — замена возможна, но позже / с риском (нужны предпосылки).
- `needs-hybrid-fallback` — детерминированное ядро + LLM-фолбэк только на суждение.
Каждому call-site присвоен **ровно один** класс. Ожидаемое (из инвентаризации; финальное решение
фиксирует архитектор в ADR): `analyst/architect/developer/reviewer → keep-LLM`;
`deployer → replace-deterministic-now` или `replace-later/risky` (staging = exit-code-маппинг; прод
self-hosting уже детерминирован Phase A/B/C) — **кандидат-замена по роли deployer**;
`tester → needs-hybrid-fallback` (детерминированный прогон `pytest`+smoke, LLM-суждение только на
маппинг TC↔критерии / триаж падений) — **кандидат-замена по роли tester**;
`deploy-finalizer/post-deploy-monitor → already-deterministic` (вне таксономии замен, как эталон).
> 📌 **Follow-up'ы — по роли, без Plane-ID (R3, NFR-6).** Кандидаты обозначаются ролью
> (deployer-замена, tester-гибрid), а не конкретными ID. Привязка к будущему work item делается при
> заведении задачи; ORCH-118 ID не выдумывает.
### FR-3 — Подтверждение детерминизма не-агентских путей (BR-3)
Карта отдельным разделом фиксирует, с `file:line`-доказательством, что НЕ вызывают LLM:
маршрутизация (`advance_stage`/`STAGE_TRANSITIONS`), все `QG_CHECKS`/`check_*`, парсеры вердиктов
(`_parse_*` через `frontmatter.parse_frontmatter`), `error_classifier` (regex), под-гейты
(security/merge/coverage/image-freshness), `self_deploy` Phase A/B/C, reconciler/reaper/serial-gate/
transition-lease. Любой найденный неожиданный LLM-путь добавляется в инвентарь (FR-1) и
классифицируется (FR-2).
### FR-4 — Упорядоченный roadmap замен (BR-4)
Ранжированный список кандидатов (названных **по роли**); для каждого: зависимости (предпосылки/блокеры),
**оценка** экономии токенов/времени (из `agent_runs`), риск безопасности, нужен ли hybrid-fallback,
ожидание kill-switch/обратимости, и **тип будущей follow-up задачи по роли** (без конкретного
Plane-ID — заводится отдельно, NFR-6). Явно: **рекомендованный первый срез** + обоснование (самый
низкорисковый, опирающийся на существующий прецедент D1/D2).
### FR-5 — Политика использования LLM (BR-5)
Нормативный durable-документ: принцип «LLM — только где нужно настоящее суждение»; критерии решения
keep vs replace (детерминируемость выхода, наличие machine-verdict, обратимость, влияние на
автономность); требование к новым/изменённым control-path'ам обосновывать любое использование LLM
против политики. Может включать рекомендацию reviewer-оси (как ORCH-079) — **как требование, не как
реализацию гейта** (новый QG не вводится, FR-6 §QG).
### FR-6 — Структурные анти-дрейф тесты (BR-6)
Новый offline-тест-файл (без сети/LLM/subprocess-к-модели), проверяющий инварианты карты:
- **(a)** В `src/**` ровно **одна** точка сборки/запуска Claude CLI (поиск по `CLAUDE_BIN` +
`--system-prompt` + `Popen`/`bash -c`), и это `launcher._spawn`.
- **(b)** Перечисленные детерминированные модули и обработчики `D1/D2` **не** содержат запуска LLM.
- **(c)** Карта перечисляет ровно те промпт-файлы, что физически лежат в `.openclaw/agents/`
(двусторонняя сверка — нет дрейфа).
- **(d)** Классификация покрывает каждый перечисленный call-site **ровно один раз** (тотальность,
без дублей/пропусков).
- **(e)** `D1/D2` действительно перехватываются в `launch_job` **до** `_spawn` (детерминированы).
> ❌ **Не вводить** тест, прибивающий карту к конкретным follow-up Plane-ID → ✅ тесты проверяют
> только инварианты, резолвящиеся в код/файлы репозитория (R3, NFR-6). Привязка к несуществующим ID
> была корнем отклонённой R2.
### FR-7 — Скоуп-гард (BR-7)
Раннеры замен **не реализуются** в ORCH-118. Карта/roadmap явно помечают кандидатов **по роли**
(deployer-замена, tester-гибрid) как follow-up, старт которых гейтится утверждением карты. Тест/диф не
должны содержать новых детерминированных раннеров tester/deployer. **Конкретные follow-up Plane-ID не
фиксируются** ни в одном артефакте (NFR-6).
## 4. Изменения API
Нет. (Опциональная read-only наблюдаемость в `GET /queue`/`GET /metrics`**вне скоупа** ORCH-118;
если архитектор сочтёт полезным — отдельная аддитивная врезка, но не требуется этой задачей.)
## 5. Изменения схемы БД
Нет. (Источник оценок экономии — существующие колонки `agent_runs`: `model`/`effort`/токены/стоимость/
время; только чтение.)
## 6. Требования к новым/изменённым QG checks
Нет. `QG_CHECKS` / `check_*` / `_parse_*` / machine-verdict-ключи — **байт-в-байт**. Структурные тесты
FR-6 — обычные `pytest`-тесты, **не** Quality Gate и **не** стадия. Политика LLM (FR-5) — нормативный
документ, а не машинный гейт.
## 7. Совместимость / регресс
- **Docs + tests only:** рантайм `src/**` не меняется → нулевая регрессия; enduro-trails не затронут;
kill-switch не нужен (нет рантайм-поведения), как в ORCH-077/079/101/102/103/011.
- **Обратимость:** артефакты — документы и тесты; откат = удаление/правка docs (рантайм-риска нет).
- **Анти-дрейф:** структурные тесты держат карту синхронной с кодом; норматив сопровождения — «менял
места вызова LLM → обнови карту и политику в том же PR» (фиксируется в политике и golden-source
docs).
- **Анти-фабрикация (R3):** артефакты фиксируют только проверяемые ссылки; follow-up'ы — по роли,
без выдуманных Plane-ID (NFR-6).
- **Self-hosting:** не деплоит/не рестартит прод/не трогает `main` — безопасно для общего инстанса.