# ТЗ — ORCH-074: убрать мёртвый frontmatter `model:` + валидация имени модели

Work Item ID: ORCH-074
Базируется на: BRD `01-brd.md`. Скоп фиксирован решением Славы (08.06):
**G1 + G2 + опц. G4. G3 (routing) НЕ включаем. Эффорт НЕ трогать.**

## 1. Задействованные модули `src/` и файлы

| Файл | Изменение |
|------|-----------|
| `.openclaw/agents/analyst.md` | **G1:** удалить строку `model: claude-sonnet-4-6` из frontmatter |
| `.openclaw/agents/architect.md` | **G1:** удалить строку `model: claude-opus-4-7` |
| `.openclaw/agents/developer.md` | **G1:** удалить строку `model: claude-sonnet-4-6` |
| `.openclaw/agents/reviewer.md` | **G1:** удалить строку `model: claude-opus-4-7` |
| `.openclaw/agents/tester.md` | **G1:** удалить строку `model: claude-sonnet-4-6` |
| `.openclaw/agents/deployer.md` | **G1:** удалить строку `model: claude-sonnet-4-6` |
| `src/agents/launcher.py` | **G2:** добавить валидацию имени модели в `resolve_agent_model` (или helper), по образцу `VALID_EFFORTS`-гарда в `resolve_agent_effort` |
| `src/config.py` | **G4 (опц.):** задать `agent_fallback_model` (если архитектор решит). При G2 — возможно добавить константу/настройку валидного формата модели |
| `docs/architecture/README.md` | **AC-6:** таблица «модель/эффорт по ролям» актуализирована; нет упоминаний sonnet/opus-4-7 как «модели агента» |
| `.env.example` | **AC-3/AC-6:** добавить блок `ORCH_AGENT_MODEL_*` / `ORCH_AGENT_EFFORT_*` / `ORCH_AGENT_FALLBACK_MODEL` (сейчас в `.env.example` их НЕТ) |
| `CLAUDE.md` | **AC-6:** при необходимости — отметить, что модель агента берётся ТОЛЬКО из config (frontmatter описательный) |
| `CHANGELOG.md` | запись о доработке |
| `tests/test_resolve_agent_model.py` | **AC-2:** добавить кейсы валидации мусорного имени |

## 2. G1 — убрать мёртвый frontmatter `model:`

Удалить **только** строку `model: …` из YAML-frontmatter каждого из 6 файлов
`.openclaw/agents/*.md`. Остальные ключи (`name`, `description`, `tools`/`model`-comment)
не трогать. frontmatter остаётся валидным YAML и описательным.

Проверка (AC-1):
```
grep -L "^model:" .openclaw/agents/*.md   # должны вернуться ВСЕ 6 файлов
```
(`grep -L` печатает файлы БЕЗ совпадения — все 6 не должны содержать `^model:`.)

## 3. G2 — валидация имени модели (never-break)

Требование (НЕ предписывает архитектуру — выбор предиката за архитектором):

- Резолвенное имя модели валидируется ПЕРЕД возвратом из `resolve_agent_model`
  (либо в общем helper). Невалидное имя → `logger.warning(...)` + откат на
  следующий валидный уровень (в пределе — `agent_model_default`, а если и он
  невалиден → `""`, т.е. без флага `--model`, CLI-дефолт). **Никогда** не вернуть
  мусор, который попадёт в `--model`.
- Поведение — точная аналогия `resolve_agent_effort` (`VALID_EFFORTS`): валидный →
  как есть; невалидный → лог + дроп.
- Предикат валидности (на усмотрение архитектора, рекомендация аналитика):
  формат-чек `claude-*` (forward-compatible — новые версии моделей не требуют
  правки allowlist) ЛИБО явный `VALID_MODELS` allowlist (строже, но требует
  поддержки при выходе новых моделей). **Выбор и обоснование — в ADR.**
- **Рекомендация аналитика (форма):** оформить предикат как отдельный
  чистый helper (напр. `is_valid_model(name) -> bool` рядом с `VALID_EFFORTS`),
  а не инлайнить в `resolve_agent_model` — тогда ОДИН валидатор переиспользуется
  и резолвом модели, и чтением fallback (G4, см. §4). Финальная форма — за
  архитектором.
- Инвариант обратной совместимости: ВСЕ ныне используемые валидные имена
  (`claude-opus-4-8`, а также enduro per-project override) проходят валидацию
  без изменения поведения. Невалидным считается только мусор (опечатка,
  `gpt-4`, пустая строка после strip и т.п.).
- Контракт уровней резолва ORCH-041 сохраняется: валидация добавляется поверх,
  механизм приоритетов не меняется.

## 4. G4 — fallback_model (опционально, решает архитектор)

- `src/config.py::agent_fallback_model` сейчас `""` (флаг не прокидывается).
- Если архитектор решит включить — задать каноничное имя модели; launcher уже
  прокидывает его в `--fallback-model` (`launcher.py:374-375`, попадает в cmd
  на строке 388).
- **⚠️ Код-факт (проверено 08.06):** fallback читается НАПРЯМУЮ —
  `fb = settings.agent_fallback_model` (`launcher.py:374`) — и **НЕ проходит**
  через `resolve_agent_model`, значит валидация G2, добавленная внутри
  `resolve_agent_model`, его НЕ покроет. Следствие для архитектора: если G4
  включается, валидацию имени модели (G2) надо применить ТАКЖЕ к fallback на
  его месте чтения (или вынести валидатор в отдельный helper, который вызывают
  ОБА: и резолв модели, и чтение fallback). Иначе опечатка в `agent_fallback_model`
  обходит G2 и уезжает в `--fallback-model` — нарушение never-break.
- Если архитектор решит НЕ включать — оставить `""`, AC-5 помечается N/A в ADR.

## 5. Изменения API / схемы БД

- **API (HTTP):** нет.
- **Схема БД:** нет миграций.
- **CLI-команда агента:** формируется в `launcher._spawn` (строки 384-392).
  Меняется только КАЧЕСТВО значения `--model` (валидное/дроп), сама структура
  команды не меняется.

## 6. Требования к QG checks

- Новых QG-чеков НЕ требуется. Валидация — это runtime-гард в launcher, не
  отдельный quality-gate.

## 7. Артефакты pipeline

Должны быть созданы/обновлены в ЭТОМ PR (golden source = код + доки):
- `docs/architecture/README.md` — таблица «модель/эффорт по ролям».
- `.env.example` — блок переменных моделей/эффорта/fallback.
- `CHANGELOG.md` — запись.
- `06-adr/ADR-NNN-*.md` — решение по предикату валидации (G2) и по G4 (fallback вкл/выкл).
- ADR архитектора фиксирует: выбран вариант G1 «убрать» (не «читать frontmatter»).

## 8. Эффорт — НЕ ТРОГАТЬ

`agent_effort_*` корректны (`thinking → high`, `tester/deployer → medium`).
Менять только при явном отдельном обосновании (вне скоупа этой задачи).

## 9. Грабли

- Имена моделей — каноничные строки Claude CLI; сверить с тем, что реально
  принимает CLI на проде (`ORCH_CLAUDE_BIN`). НЕ хардкодить версию вне `config.py`.
- Если frontmatter автогенерится инструментом — убедиться, что `model:` не вернётся.
- Self-hosting: НЕ ронять прод-контейнер; деплой через «Confirm Deploy».
