From 5f4c8fbec2a40e9e4c7b6cdb115e124bd32b0f64 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Mon, 8 Jun 2026 22:29:25 +0300 Subject: [PATCH] analyst(ET): auto-commit from analyst run_id=399 --- docs/work-items/ORCH-081/01-brd.md | 82 +++++++++++++ docs/work-items/ORCH-081/02-trz.md | 110 ++++++++++++++++++ .../ORCH-081/03-acceptance-criteria.md | 60 ++++++++++ docs/work-items/ORCH-081/04-test-plan.yaml | 86 ++++++++++++++ 4 files changed, 338 insertions(+) create mode 100644 docs/work-items/ORCH-081/01-brd.md create mode 100644 docs/work-items/ORCH-081/02-trz.md create mode 100644 docs/work-items/ORCH-081/03-acceptance-criteria.md create mode 100644 docs/work-items/ORCH-081/04-test-plan.yaml diff --git a/docs/work-items/ORCH-081/01-brd.md b/docs/work-items/ORCH-081/01-brd.md new file mode 100644 index 0000000..29ff204 --- /dev/null +++ b/docs/work-items/ORCH-081/01-brd.md @@ -0,0 +1,82 @@ +# 01 — BRD: ORCH-081 (ORCH-52h) + +**Work Item:** ORCH-081 +**Эпик:** ORCH-052 (продолжение ORCH-52a / ORCH-074) +**Тип:** Багфикс (конфигурация эффорта агентов) +**Приоритет:** HIGH +**Repo:** orchestrator (self-hosting) + +## 1. Контекст и проблема + +При проверке ORCH-074 (08.06) обнаружено: `resolve_agent_effort()` для **всех 6 агентов +в проде** возвращает пустую строку `''`, хотя в `src/config.py` заданы осмысленные +дефолты (`agent_effort_default="high"`, per-agent `high`/`medium`). Итог: флаг +`--effort` **не передаётся** в Claude CLI, и каждый агент бежит на встроенном +CLI-дефолте эффорта, а **не** на заявленном `high`/`medium`. + +### Корень (диагностика) +В проде env-переменные `ORCH_AGENT_EFFORT_DEFAULT` и +`ORCH_AGENT_EFFORT_{ANALYST,ARCHITECT,DEVELOPER,REVIEWER,TESTER,DEPLOYER}` выставлены в +**пустую строку** (`VAR=` без значения). Pydantic Settings трактует присутствующую +env-переменную (даже пустую) как явное значение и **перебивает** дефолт класса: +`agent_effort_* = ''`. В цепочке резолва (`launcher._resolve_agent_attr`): +- per-agent `''` → falsy → пропуск (уровень 2); +- default `''` → falsy → пропуск (уровень 3); +- → возврат `''` (уровень 4, «без флага»). + +Поскольку **и default тоже пуст**, привычный откат «per-agent пуст → взять default» +не спасает: откатываться не на что. Это ключевой нюанс — фикс обязан давать каждой +роли непустой «пол» (floor) даже когда И per-agent, И default env пусты. + +## 2. Бизнес-ценность / зачем важно + +Для Opus 4.8 (канон Anthropic) уровень reasoning-эффорта влияет на качество вывода +**сильнее**, чем у прежних моделей. Coding/agentic роли (особенно `developer`) должны +идти минимум на `high`, а `developer` — кандидат на `xhigh`. Сейчас фактически работает +неконтролируемый CLI-дефолт → прямой удар по стратегии надёжности и предсказуемости +качества всего конвейера (включая enduro-trails из общего инстанса). + +## 3. Решение (бизнес-уровень) + +Принят **вариант (c)** (решение Славы, 08.06): пустая строка эффорта трактуется как +«не задано» и откатывается на осмысленный per-role дефолт (а не на CLI-дефолт), +**устойчиво** к пустым env. Дополнительно — зафиксировать целевые дефолты в `config.py` +и `.env.example`. + +### Целевые значения эффорта (единственный апгрейд — `developer`) +| Агент | Эффорт | Обоснование | +|-------|--------|-------------| +| analyst | high | intelligence-роль | +| architect | high | intelligence-роль | +| **developer** | **xhigh** | coding/agentic, канон Opus 4.8 → апгрейд с `high` | +| reviewer | high | intelligence-роль | +| tester | medium | механическая роль | +| deployer | medium | механическая роль | + +`developer → xhigh` — единственное изменение относительно текущих config-дефолтов; +остальные значения подтверждают текущий замысел и фиксируются устойчиво. + +## 4. Грабли / ограничения (из бизнес-запроса) + +- **Хост-репо / env-правки НЕ переживают деплой**, если положены в git-managed файл + (урок 08.06 про docker-compose + TZ). Источник правды для реальных значений — + `.env` на хосте (gitignored), канон-шаблон — `.env.example`. Фикс обязан быть + **code-side robust**: даже если прод-`.env` снова окажется с пустыми + `ORCH_AGENT_EFFORT_*`, эффорт всё равно резолвится в целевые значения. +- **Self-hosting:** правка касается инструмента, который сейчас в проде обслуживает и + другие проекты. Прод-контейнер `orchestrator` не ронять в рамках задачи; деплой — + через штатный `deploy-staging` → `Confirm Deploy`. + +## 5. Не-цели + +- НЕ трогать model-резолв (`resolve_agent_model` — сделан в ORCH-074). +- НЕ включать G3 model-routing — все 6 агентов остаются на `claude-opus-4-8`. +- НЕ менять значения эффорта сверх согласованных (`high`/`medium`/`xhigh` для + developer). Иные значения — отдельное взвешенное решение. + +## 6. Затронутые стороны + +- Все агенты конвейера (analyst → deployer) во всех проектах общего инстанса. +- Операторы (правка прод-`.env`), документация (README таблица, `.env.example`). + + diff --git a/docs/work-items/ORCH-081/02-trz.md b/docs/work-items/ORCH-081/02-trz.md new file mode 100644 index 0000000..fa0a4cb --- /dev/null +++ b/docs/work-items/ORCH-081/02-trz.md @@ -0,0 +1,110 @@ +# 02 — ТЗ: ORCH-081 (ORCH-52h) + +**Work Item:** ORCH-081 · **Тип:** багфикс конфигурации · **Repo:** orchestrator + +Документ описывает ТРЕБУЕМОЕ ПОВЕДЕНИЕ и затронутые модули. Конкретный механизм +(field_validator vs изменение резолвера) — на усмотрение архитектора; ниже зафиксированы +инварианты, которым любая реализация обязана удовлетворять. + +## 1. Задействованные модули + +| Модуль | Роль в задаче | +|--------|----------------| +| `src/config.py` (`Settings`) | дефолты эффорта; устойчивость к пустому env (ядро фикса) | +| `src/agents/launcher.py` | `resolve_agent_effort` / `_resolve_agent_attr` (цепочка резолва), `VALID_EFFORTS`, сборка `--effort` в `_spawn` | +| `.env.example` | канон-шаблон значений эффорта по ролям | +| `docs/architecture/README.md` | таблица «Модель и эффорт по ролям» (строки ~47–54) | +| `CHANGELOG.md` | запись о фиксе | +| `tests/test_resolve_agent_effort.py` | расширить кейсами пустого env | + +## 2. Корень бага (точная механика) + +`launcher._resolve_agent_attr` (строки ~104–114): +``` +per_agent = getattr(settings, f"agent_effort_{agent}", "") # '' в проде -> falsy -> skip +default = getattr(settings, "agent_effort_default", "") # '' в проде -> falsy -> skip +return "" # уровень 4: без флага +``` +Pydantic: `ORCH_AGENT_EFFORT_*=` (пустая строка в env) перебивает дефолт класса → +поле `= ''`. Поскольку пустым оказывается **и** `agent_effort_default`, у резолва нет +непустого «пола» для отката → `''` → `--effort` не передаётся. + +## 3. Требования к фиксу (вариант c) + +### FR-1. Непустой floor на каждую роль при пустом env +При ЛЮБОЙ комбинации пустых `ORCH_AGENT_EFFORT_*` (включая `ORCH_AGENT_EFFORT_DEFAULT=`) +`resolve_agent_effort(agent)` обязан вернуть целевое непустое значение для каждой из 6 +ролей: + +| agent | результат | +|-------|-----------| +| analyst | `high` | +| architect | `high` | +| developer | `xhigh` | +| reviewer | `high` | +| tester | `medium` | +| deployer | `medium` | + +Замечание для реализации: floor должен быть **per-role**, а не единым на default — +иначе пустой `ORCH_AGENT_EFFORT_TESTER=` снапнется на `high` вместо `medium`. Т.е. +«пустая строка трактуется как не-задано» применяется так, чтобы каждая роль получала +СВОЙ канонический дефолт, а не общий. + +### FR-2. Приоритет резолва сохраняется +Порядок не меняется: project-override (`projects_json.agent_efforts`) > per-agent env > +default > floor. Непустой явный env/override по-прежнему ПОБЕЖДАЕТ floor (оператор может +осознанно задать, напр., `ORCH_AGENT_EFFORT_DEVELOPER=high`, и это применится). + +### FR-3. Валидация невалидного значения не регрессирует +Значение вне `VALID_EFFORTS` (`low|medium|high|xhigh|max`) по-прежнему логируется +(`logger.warning`) и **дропается** → `''` (без флага). Floor НЕ должен «спасать» явную +опечатку (`turbo`/`ultra`) — поведение ORCH-41 сохраняется (never-break, мусор не +уезжает в CLI). + +### FR-4. `developer → xhigh` зафиксирован явно +`config.py`: `agent_effort_developer` со значением `xhigh` (сейчас `high`). +`.env.example`: `ORCH_AGENT_EFFORT_DEVELOPER=xhigh` (сейчас `high`) + правка комментария +про split (developer теперь xhigh, не в группе «thinking → high»). + +### FR-5. `xhigh` принимается CLI-слоем +Подтвердить, что `xhigh` присутствует в `VALID_EFFORTS` +(`src/agents/launcher.py:22` — уже `frozenset({"low","medium","high","xhigh","max"})`, +**присутствует**; добавления не требуется, только верификация тестом). Эффорт реально +собирается в команду: `_spawn` строит `effort_flag = f"--effort {effort} "` при непустом +`effort` (строка ~434) — путь проброса не менять, только убедиться тестом сборки флага. + +## 4. Изменения API / схемы БД + +- **API endpoints:** нет. +- **Схема БД:** нет. +- **Конфиг (env-контракт):** значения `ORCH_AGENT_EFFORT_*` неизменны по ИМЕНАМ; + меняется лишь дефолт `developer` (high → xhigh) и устойчивость к пустым значениям. + Обратная совместимость: непустой явный env работает 1:1 как раньше. + +## 5. Требования к QG checks + +Новых QG checks не требуется. Гейты конвейера не затрагиваются. + +## 6. Артефакты pipeline (обновить в ТОМ ЖЕ PR) + +- `src/config.py` — дефолт developer + устойчивость к пустому env. +- `src/agents/launcher.py` — если фикс кладётся в резолвер (на усмотрение архитектора). +- `.env.example` — `ORCH_AGENT_EFFORT_DEVELOPER=xhigh` + правка комментария split. +- `docs/architecture/README.md` — таблица эффорта: developer `high` → `xhigh`; при + необходимости — ремарка про floor/устойчивость к пустому env. +- `CHANGELOG.md` — запись (`fix:`). +- `tests/test_resolve_agent_effort.py` — новые кейсы (см. 04-test-plan.yaml). + +## 7. Операционная часть (вне PR-кода, для деплой-лога) + +- Реальные значения — в прод-`.env` на хосте (gitignored). Рекомендуется привести + прод-`.env` к каноне `.env.example` (developer=xhigh, остальные непустые), НО фикс + обязан работать и без этого (FR-1). Не коммитить секреты/хост-env в git. +- Деплой — через `deploy-staging` (8501) → `Confirm Deploy`. Прод-контейнер не ронять + вне штатного хука. + +## 8. Definition of Done + +AC-1…AC-5 из `03-acceptance-criteria.md` выполнены; `pytest -q` зелёный; документация +(README + `.env.example` + CHANGELOG) синхронизирована в том же PR; never-break соблюдён. + diff --git a/docs/work-items/ORCH-081/03-acceptance-criteria.md b/docs/work-items/ORCH-081/03-acceptance-criteria.md new file mode 100644 index 0000000..efcba9f --- /dev/null +++ b/docs/work-items/ORCH-081/03-acceptance-criteria.md @@ -0,0 +1,60 @@ +# 03 — Критерии приёмки: ORCH-081 (ORCH-52h) + +Каждый критерий — чёткое условие PASS/FAIL. Пустой env моделируется в unit-тестах +(установка `agent_effort_* = ""`), проверка «в проде» — операционная (post-deploy). + +## AC-1 — осмысленный непустой эффорт для всех 6 агентов +**PASS:** `resolve_agent_effort(agent)` возвращает целевое непустое значение для каждой +роли при канонической конфигурации: + +| agent | ожидаемое | +|-------|-----------| +| analyst | `high` | +| architect | `high` | +| developer | `xhigh` | +| reviewer | `high` | +| tester | `medium` | +| deployer | `medium` | + +**FAIL:** любой агент возвращает `''` или значение, отличное от таблицы. + +## AC-2 — пустой env НЕ приводит к пустому эффорту (вариант c) +**PASS:** при `agent_effort_default = ""` И всех `agent_effort_ = ""` +(моделирование прод-env, где `ORCH_AGENT_EFFORT_*=` пусты) `resolve_agent_effort` для +каждой из 6 ролей возвращает значение по таблице AC-1 (floor per-role срабатывает: +developer=`xhigh`, tester/deployer=`medium`, остальные=`high`), а **не** `''`. +**FAIL:** хотя бы одна роль при полностью пустом env даёт `''`. + +## AC-3 — эффорт реально пробрасывается в запуск агента +**PASS:** в `launcher._spawn` (или эквивалентной сборке) при непустом резолвнутом +эффорте формируется `--effort ` во флагах команды; при пустом — флаг +отсутствует. Тест сборки флага подтверждает наличие `--effort xhigh ` для developer и +`--effort medium ` для tester. +**FAIL:** `--effort` отсутствует при непустом значении ИЛИ присутствует при пустом. + +## AC-4 — документация синхронизирована +**PASS:** `.env.example` содержит `ORCH_AGENT_EFFORT_DEVELOPER=xhigh` и корректный +комментарий про split; таблица «Модель и эффорт по ролям» в +`docs/architecture/README.md` показывает developer = `xhigh` (остальные без изменений); +`CHANGELOG.md` содержит запись о фиксе. +**FAIL:** любой из трёх артефактов рассинхронизирован с фактическими дефолтами config. + +## AC-5 — never-break, тесты зелёные +**PASS:** +- `pytest -q` целиком зелёный (включая существующие + `tests/test_resolve_agent_effort.py` и новые кейсы). +- Невалидное значение эффорта (`turbo`/`ultra`/`bogus`) по-прежнему логируется и + дропается в `''` (floor его НЕ маскирует) — регрессии валидации ORCH-41 нет. +- Непустой явный per-agent env / project-override по-прежнему побеждает floor + (приоритет резолва сохранён). +- `xhigh ∈ VALID_EFFORTS` (подтверждено тестом). + +**FAIL:** падение любого теста, регрессия валидации/приоритета, либо `xhigh` +отвергается как невалидный. + +## AC-6 (операционный, для деплой-стадии) — проверка в проде +**PASS:** после деплоя на проде `resolve_agent_effort` для 6 агентов даёт значения +AC-1 (проверяется в рантайме прод-инстанса / по логам запуска агента — наличие +`--effort` с верным уровнем). Фиксируется в `14-deploy-log.md`. +**FAIL:** в проде хотя бы один агент бежит без `--effort` или с неверным уровнем. + diff --git a/docs/work-items/ORCH-081/04-test-plan.yaml b/docs/work-items/ORCH-081/04-test-plan.yaml new file mode 100644 index 0000000..712b86a --- /dev/null +++ b/docs/work-items/ORCH-081/04-test-plan.yaml @@ -0,0 +1,86 @@ +work_item: ORCH-081 +description: > + Тест-план фикса ORCH-52h — устойчивость резолва эффорта к пустому env (вариант c) + + фиксация целевых дефолтов (developer -> xhigh). Расширяет существующий + tests/test_resolve_agent_effort.py. Пустой прод-env моделируется установкой + agent_effort_* = "" на settings (через monkeypatch), как уже делают текущие тесты. +tests: + - id: TC-01 + type: unit + description: > + Канонические дефолты: resolve_agent_effort для всех 6 ролей даёт + analyst/architect/reviewer=high, developer=xhigh, tester/deployer=medium. + module: tests/test_resolve_agent_effort.py + covers: [AC-1, FR-4] + expected: PASS + + - id: TC-02 + type: unit + description: > + Пустой env (вариант c): при agent_effort_default="" И всех + agent_effort_="" каждая из 6 ролей возвращает целевое значение по AC-1 + (НЕ ""). Ключевой кейс бага: developer -> xhigh, tester/deployer -> medium, + analyst/architect/reviewer -> high. + module: tests/test_resolve_agent_effort.py + covers: [AC-2] + expected: PASS + + - id: TC-03 + type: unit + description: > + Floor НЕ маскирует опечатку: невалидное значение (default/per-agent/override = + 'turbo'/'ultra'/'bogus') по-прежнему логируется и дропается в "" (валидация + ORCH-41 не регрессирует). Проверить, что floor не подменяет невалидный явный ввод + на дефолт. + module: tests/test_resolve_agent_effort.py + covers: [AC-5, FR-3] + expected: PASS + + - id: TC-04 + type: unit + description: > + Приоритет сохранён: непустой per-agent env побеждает floor/ default + (ORCH_AGENT_EFFORT_DEVELOPER=high -> "high", не "xhigh"); project-override + побеждает per-agent (agent_efforts={"developer":"xhigh"}). + module: tests/test_resolve_agent_effort.py + covers: [AC-5, FR-2] + expected: PASS + + - id: TC-05 + type: unit + description: > + xhigh валиден: xhigh ∈ VALID_EFFORTS и resolve_agent_effort с developer-дефолтом + xhigh не дропается. + module: tests/test_resolve_agent_effort.py + covers: [AC-5, FR-5] + expected: PASS + + - id: TC-06 + type: unit + description: > + Сборка флага: при resolve developer=xhigh во флагах присутствует "--effort xhigh ", + при tester=medium — "--effort medium "; при пустом эффорте "--effort" отсутствует + (mirror логики _spawn, как существующие test_flags_* кейсы). + module: tests/test_resolve_agent_effort.py + covers: [AC-3] + expected: PASS + + - id: TC-07 + type: integration + description: > + Документация синхронизирована: .env.example содержит + ORCH_AGENT_EFFORT_DEVELOPER=xhigh; README таблица эффорта показывает developer + xhigh. (Проверяется ревьюером/тестером по diff; опционально — текстовая ассерта.) + module: tests/test_resolve_agent_effort.py + covers: [AC-4] + expected: PASS + + - id: TC-08 + type: unit + description: > + Регрессия существующего набора: весь tests/test_resolve_agent_effort.py + + tests/test_resolve_agent_model.py остаются зелёными (never-break ORCH-41/074). + module: tests/test_resolve_agent_effort.py + covers: [AC-5] + expected: PASS +