diff --git a/docs/work-items/ORCH-092/01-brd.md b/docs/work-items/ORCH-092/01-brd.md new file mode 100644 index 0000000..b2d982d --- /dev/null +++ b/docs/work-items/ORCH-092/01-brd.md @@ -0,0 +1,169 @@ +--- +work_item: ORCH-092 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-09 +model_used: claude-opus-4-8 +--- + +# 01 — BRD (бизнес-требования): ORCH-092 — Промпт-аудит 6 агентов (расхардкод дат/модели, сверка гейтов, escalation, чистка мёртвых инструкций) + +Work Item: **ORCH-092** · Repo: **orchestrator** · Стадия: analysis + +## 1. Бизнес-контекст и проблема + +ORCH-092 — **эпилог эпика ORCH-52** (канонизация системных промптов). После слоёв 52d +(XML-канон) и 52e (трассировка маркеров) системный аудит 6 промптов (`.openclaw/agents/*.md`) +выявил класс системных дефектов, способных приводить к **дрейфу и багам** в self-hosting-конвейере: + +- **Хардкод даты в примерах.** Во всех 6 промптах пример frontmatter содержит жёсткое + `created_at: 2026-06-09`. Исполняющая модель — литеральный Opus 4.8: пример сильнее + инструкции «текущая дата». Риск — модель **копирует дату буквально** → все документы + всех задач получают одну и ту же дату, метаданные перестают отражать реальность. +- **Хардкод модели в примерах.** Пример несёт `model_used: claude-opus-4-8`. Если включат + model-routing (ORCH-41), промпты начнут **врать** про использованную модель — ровно та + боль, которую слой 52f чинил для README «Известные ограничения». +- **Несверённые имена гейтов.** Промпты называют имена QG-функций (`check_*`); при дрейфе + кода имя в промпте может разойтись с реальным реестром `QG_CHECKS`. *(Сверка кодом в рамках + анализа показала: текущие имена корректны — см. §6, допущение A-1; задача — закрепить сверку + как воспроизводимую проверку, а не «починить несуществующий баг».)* +- **Логические нестыковки в developer.md.** Инструкция «PR > 1500 строк → разбивай на меньшие + PR» **физически невыполнима**: конвейер = 1 задача = 1 ветка = 1 PR, разбить внутри стадии + нельзя. Инструкция `git rebase origin/main` в начале алгоритма **дублирует/конфликтует** с + автоматикой движка (serial-gate ORCH-088 режет ветку от свежего `origin/main`; + `auto_rebase_onto_main` ORCH-026 делает pre-merge rebase сам). +- **Размазанная эскалация.** Секцию `` имеет только `architect.md`. У developer / + reviewer / tester маршруты эскалации (негодное ТЗ, FAIL, REQUEST_CHANGES) растворены в + `` — нет единой видной точки «куда эскалировать при затыке». +- **Консистентность/качество.** `deployer.md` (самый большой, ~9.6 KB, на английском) рискует + «утопить» критичный self-hosting-запрет «НЕ рестартить 8500». `tester.md` (самый бедный, + ~4.7 KB) не фиксирует worktree-путь (были гонки checkout), не проверяет serial_gate-блок и + не требует покрытия ТЗ. `reviewer.md` содержит мёртвую инструкцию про «тот же экземпляр + Developer» (в конвейере reviewer всегда отдельный agent-run). + +**Это docs/prompts-only задача.** Код (`src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, схема БД) +**не трогается**. Промпт `cat`-ается из worktree в момент запуска агента, поэтому новые +промпты вступают в силу на следующем worktree от `main` **без рестарта прод-контейнера** — +что критично для self-hosting (рестарт 8500 встаёт конвейер всех проектов). + +## 2. Объём (scope) + +### В объёме +- Правка 6 промптов `.openclaw/agents/{analyst,architect,developer,reviewer,tester,deployer}.md`: + расхардкод даты (P0-1) и модели (P0-2) в **копируемых примерах**; сверка имён гейтов (P0-3); + переформулировка «PR>1500» в эскалацию (P1-1); добавление `` в developer/reviewer/ + tester (P1-3); рамка критичных запретов в deployer (P2-1); обогащение tester (P2-3); удаление + мёртвой инструкции reviewer (P2-4). +- **Решения, требующие архитектора** (формализованы как открытые в §6, решаются в `06-adr/`): + P1-2 (нужен ли ручной rebase у developer при наличной автоматике), P2-2 (язык deployer: + унификация en→ru ИЛИ явно зафиксированное исключение). +- Обновление обзорной документации: `CLAUDE.md`, `docs/architecture/README.md` (при + необходимости), `CHANGELOG.md`, ADR work item, и **новые/обновлённые структурные тесты** + `tests/test_agent_prompts_canon.py` (анти-регресс новых инвариантов). + +### Вне объёма +- ❌ Любая правка `src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`, схемы БД. +- ❌ Изменение машинных verdict-ключей (`verdict:` / `result:` / `staging_status:` / + `deploy_status:` / `security_status:`) — байт-в-байт неприкосновенны. +- ❌ Слом XML-канона 52d (5 обязательных секций в нормативном порядке), 52c-схемы (6 полей), + правила трассировки 52e. +- ❌ Включение enforcement frontmatter (`frontmatter_validation_strict` остаётся `False`). +- ❌ Артефакты других work item. + +## 3. Заинтересованные стороны +- **Заказчик / приёмка:** Owner (Слава) — BRD-гейт ручной; решения по P1-2/P2-2. +- **Затрагиваются:** все 6 ролей конвейера (исполняют обновлённые промпты), все проекты в + общем инстансе (self-hosting), сопровождающие агенты. +- **Принимает архитектурные развилки:** архитектор (стадия architecture, `06-adr/`). + +## 4. Бизнес-требования (BR) + +- **BR-1 (P0-1)** — В копируемых примерах frontmatter **всех 6** промптов `created_at` — + плейсхолдер `` (НЕ конкретная дата), сопровождённый явной инструкцией: подставить + фактическую текущую дату (`date +%F`), НЕ копировать из примера буквально. +- **BR-2 (P0-2)** — В копируемых примерах **всех 6** промптов `model_used` — плейсхолдер/резолв + (``, НЕ литеральный `claude-opus-4-8`), с оговоркой подставить фактическую + модель из конфига. Факт «сейчас `claude-opus-4-8`» допускается как **справка вне копируемого + блока** (например в таблице полей), но не как литерал в примере. +- **BR-3 (P0-3)** — Все имена гейтов/QG-функций, упомянутые в промптах, **сверены** с реальным + реестром `QG_CHECKS` (`src/qg/checks.py`). Реальные несовпадения (если бы нашлись) исправлены; + **ложные подозрения не трогаются** (`check_tests_passed` верен). Сверка закреплена + воспроизводимым тестом. +- **BR-4 (P1-1)** — Инструкция developer «PR > 1500 строк → разбивай на меньшие PR» заменена на + **эскалацию**: PR слишком большой → флагировать/эскалировать (задача слишком крупная, нужна + декомпозиция **на уровне задач**, не PR). +- **BR-5 (P1-3)** — developer / reviewer / tester получают явную секцию `` с чёткими + маршрутами: developer → `back-to:analysis` при негодном ТЗ; tester → `back-to:dev` при FAIL; + reviewer → `REQUEST_CHANGES`. (Существующая `` у architect — эталон формата.) +- **BR-6 (P2-1)** — Критичные self-hosting-запреты deployer (прежде всего «НЕ рестартить + прод 8500») вынесены в **видную рамку в начале** промпта, чтобы не утонуть в объёме. +- **BR-7 (P2-3)** — tester обогащён: явный worktree-путь (ветка vs `/repos` — устранить гонки + checkout); smoke добавляет проверку блока `serial_gate` в `/queue` (ORCH-088); `success_criteria` + упоминает **покрытие ТЗ** (каждый TC из `04-test-plan.yaml`), не только «файл записан». +- **BR-8 (P2-4)** — Мёртвая инструкция reviewer «не апрувь PR от того же экземпляра Developer» + удалена (защита от несуществующего кейса — reviewer всегда отдельный agent-run), при сохранении + всех живых инвариантов оси документации. +- **BR-9 (P1-2, решение архитектора)** — Зафиксировать в ADR: должен ли developer выполнять + ручной `git rebase origin/main`, или это полностью делает движок (serial-gate + auto_rebase). + Промпт приводится в соответствие с принятым решением (убрать/смягчить/оставить с пояснением). +- **BR-10 (P2-2, решение архитектора)** — Зафиксировать в ADR язык deployer: унифицировать + (en→ru) ЛИБО явно задокументировать исключение («deployer — en, т.к. критичные команды/ + контракты на en»). При любом исходе machine-verdict ключи и shell-команды **не ломаются**. +- **BR-11 (документация)** — Обновлены `CLAUDE.md` / `README` / ADR / `CHANGELOG.md` + (golden source = код); добавлены/обновлены структурные тесты анти-регресса новых инвариантов. + +## 5. Нефункциональные требования (NFR) + +- **NFR-1 (анти-регресс, критично)** — verdict-ключи `verdict:` / `result:` / `staging_status:` / + `deploy_status:` / `security_status:` сохраняются **байт-в-байт** (имя/регистр/значения); + XML-канон 52d (5 секций, нормативный порядок), 52c-схема (6 полей), правило трассировки 52e — + сохранены. `tests/test_agent_prompts_canon.py` и `tests/test_agent_frontmatter_no_model.py` — + **зелёные**. +- **NFR-2 (self-hosting безопасность)** — Изменение docs/prompts-only: `src/**` не тронут, + прод-контейнер 8500 **не перезапускается**. Новые промпты применяются на следующем worktree + от `main` без прод-рестарта. +- **NFR-3 (обратимость)** — Все правки текстовые и ревертируемы одним PR; нет миграций, нет + изменения схемы/состояния. +- **NFR-4 (консистентность канона)** — Все правки соблюдают канон Anthropic (запреты «❌ X → + ✅ Y», секции в нормативном порядке); новая секция `` размещается так, чтобы не + нарушать порядок 5 обязательных секций (после ``, как у architect). +- **NFR-5 (отсутствие enforcement)** — `frontmatter_validation_strict` остаётся `False`; + плейсхолдеры в примерах не вызывают hard-fail валидатора (warning-only). + +## 6. Допущения и ограничения + +- **A-1 (сверено кодом):** реестр `QG_CHECKS` (`src/qg/checks.py`) содержит: + `check_analysis_complete`, `check_analysis_approved`, `check_architecture_done`, + `check_ci_green`, `check_review_approved`, `check_tests_passed`, `check_reviewer_verdict`, + `check_deploy_status`, `check_staging_status`, `check_branch_mergeable`, `check_security_gate`, + `check_staging_image_fresh` (+ `check_tests_local` — DEPRECATED). Имена гейтов в промптах + (`check_ci_green`, `check_reviewer_verdict`, `check_tests_passed`, `check_deploy_status`, + `check_staging_status`, `check_security_gate`) **совпадают**. Реальных несовпадений на момент + анализа НЕТ → BR-3 = «закрепить сверку», а не «исправить». +- **A-2 (сверено кодом, основание для BR-9):** `auto_rebase_onto_main` (`src/merge_gate.py`) + вызывается автоматически в `check_branch_mergeable` (`src/qg/checks.py`) при + `premerge_rebase_always=True` (дефолт), а serial-gate (ORCH-088) откладывает срез ветки на + свежий `origin/main`. Ручной rebase developer пересекается с этой автоматикой → требует решения + архитектора (не менять вслепую). +- **A-3:** Канон-тест проверяет **наличие имён полей** `created_at`/`model_used` и **литеральные + строки** `author_agent: ` / `stage: ` в примере — плейсхолдеры даты/модели этого + не нарушают. Ни один тест не утверждает литерал `claude-opus-4-8` внутри промптов. +- **Ограничение:** P1-2 и P2-2 — зона архитектора; analyst фиксирует факты и требование-решение, + но НЕ принимает решение и НЕ правит вслепую. + +## 7. Критерии успеха + +Аудит-правки внесены во все 6 промптов согласно BR-1…BR-8; архитектурные развилки BR-9/BR-10 +решены в ADR и отражены в промптах; документация и анти-регресс-тесты обновлены (BR-11); +анти-регресс NFR-1 соблюдён (verdict-ключи и канон не сломаны, целевые тесты зелёные). +Детальные PASS/FAIL — `03-acceptance-criteria.md`. + +## 8. Риски + +- Случайный слом verdict-ключа/канона при массовой текстовой правке → митигируется + структурными тестами (NFR-1). +- Плейсхолдер `` / `` сам по себе мог бы быть скопирован буквально — + митигируется **явной инструкцией** «подставь фактическое, НЕ копируй». +- Принятие архитектурного решения (P1-2/P2-2) не аналитиком — митигируется явным выносом в `06-adr/`. +- Детальная карта рисков — `10-tech-risks.md` (заполняет архитектор). diff --git a/docs/work-items/ORCH-092/02-trz.md b/docs/work-items/ORCH-092/02-trz.md new file mode 100644 index 0000000..a24db04 --- /dev/null +++ b/docs/work-items/ORCH-092/02-trz.md @@ -0,0 +1,159 @@ +--- +work_item: ORCH-092 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-09 +model_used: claude-opus-4-8 +--- + +# 02 — ТЗ (TRZ): ORCH-092 — Промпт-аудит 6 агентов + +Work Item: **ORCH-092** · Repo: **orchestrator** · Стадия: analysis + +> ТЗ описывает **конкретные изменения к реализации**, выведенные из BRD и фактического кода. +> Архитектурное обоснование/решения (P1-2 rebase, P2-2 язык deployer) — задача архитектора (`06-adr/`). + +## 1. Сводка изменения + +Точечная правка 6 системных промптов `.openclaw/agents/*.md` + обзорной документации + структурных +анти-регресс-тестов. **Код приложения не трогается** (docs/prompts-only). Цель — устранить класс +дефектов промптов (хардкод даты/модели, размазанная эскалация, нереализуемые/конфликтующие +инструкции, мёртвые инструкции, недообогащённые промпты), сохранив канон 52d/52c/52e и +машинные verdict-ключи байт-в-байт. + +## 2. Задействованные модули / пути + +| Путь | Действие | +|------|----------| +| `.openclaw/agents/analyst.md` | изменить — расхардкод `created_at`/`model_used` в примере (FR-1, FR-2) | +| `.openclaw/agents/architect.md` | изменить — расхардкод `created_at`/`model_used` в примере (FR-1, FR-2) | +| `.openclaw/agents/developer.md` | изменить — расхардкод (FR-1/2); «PR>1500»→эскалация (FR-4); `` (FR-5); rebase по решению ADR (FR-9) | +| `.openclaw/agents/reviewer.md` | изменить — расхардкод (FR-1/2); `` (FR-5); удалить мёртвую инструкцию (FR-8) | +| `.openclaw/agents/tester.md` | изменить — расхардкод (FR-1/2); `` (FR-5); worktree-путь + serial_gate smoke + покрытие ТЗ (FR-7) | +| `.openclaw/agents/deployer.md` | изменить — расхардкод (FR-1/2); рамка критичных запретов (FR-6); язык по решению ADR (FR-10) | +| `tests/test_agent_prompts_canon.py` | изменить — добавить TC анти-регресса новых инвариантов (FR-11) | +| `CLAUDE.md` | изменить — отразить ORCH-092 (норматив промптов), при необходимости | +| `docs/architecture/README.md` | изменить — when-applicable (если затрагивается обзорная карта) | +| `CHANGELOG.md` | изменить — запись под `## [Unreleased]` | +| `docs/work-items/ORCH-092/06-adr/ADR-001-*.md` | создать (архитектор) — решения P1-2, P2-2 | +| `src/**`, `src/qg/checks.py`, `STAGE_TRANSITIONS`, `QG_CHECKS`, схема БД | **НЕ трогать** | + +## 3. Функциональные требования + +### FR-1 — Расхардкод `created_at` в примерах (BR-1, P0-1) +Во **всех 6** промптах в копируемом примере frontmatter заменить `created_at: 2026-06-09` на +плейсхолдер `created_at: `. Рядом — явная инструкция (в ``): «подставь +фактическую текущую дату (`date +%F`); НЕ копируй дату из примера буквально». Инвариант: имя поля +`created_at` остаётся (канон-тест проверяет наличие имени). + +### FR-2 — Расхардкод `model_used` в примерах (BR-2, P0-2) +Во **всех 6** промптах в копируемом примере заменить `model_used: claude-opus-4-8` на +`model_used: ` + оговорку «подставь фактическую модель из конфига, не копируй +буквально». Факт «сейчас `claude-opus-4-8`» допустимо оставить как **справку в таблице полей** +(вне копируемого блока). Инвариант: имя поля `model_used` остаётся. + +### FR-3 — Сверка имён гейтов с `QG_CHECKS` (BR-3, P0-3) +Пройти по каждому промпту, сверить все упомянутые `check_*`/имена QG-функций с реальным реестром +`QG_CHECKS` в `src/qg/checks.py`. **Установленный факт:** на момент анализа несовпадений НЕТ +(`check_ci_green`, `check_reviewer_verdict`, `check_tests_passed`, `check_deploy_status`, +`check_staging_status`, `check_security_gate` — все присутствуют в реестре; `check_tests_passed` +верен — подозрение было ложным). Требование: **исправлять только реально несовпадающие** имена +(не выдумывать); закрепить сверку воспроизводимым тестом (FR-11/TC-03). + +### FR-4 — «PR>1500» → эскалация (BR-4, P1-1) +В `developer.md` (секция ``) заменить запрет «❌ Не делай PR > 1500 строк без +декомпозиции → ✅ разбивай на меньшие PR» на эскалацию: PR оказался слишком большим → **флагируй/ +эскалируй** (задача слишком крупная, нужна декомпозиция **на уровне задач**, не внутри стадии; +1 задача = 1 ветка = 1 PR). Инвариант FR-6-анти-регресс: маркер «свой PR» («не мержи свой PR») +сохраняется отдельно. + +### FR-5 — Секция `` в developer/reviewer/tester (BR-5, P1-3) +Добавить секцию `` (формат — как у `architect.md`, **после** ``, +чтобы не нарушать нормативный порядок 5 обязательных секций): +- **developer:** негодное/нереализуемое ТЗ → вернуть в Анализ (`back-to:analysis`); нужна новая + архитектурная развилка → эскалация к архитектору. +- **tester:** обоснованный FAIL → откат на development (`back-to:dev`); смок-сбой инфраструктуры → + зафиксировать как FAIL с диагностикой. +- **reviewer:** любой P0/P1 → `REQUEST_CHANGES` (единая точка); неоднозначность требований → + finding со ссылкой на ТЗ/ADR. + +Эскалационные строки консолидируют (не дублируют слепо) то, что было размазано по ``. + +### FR-6 — Рамка критичных запретов в deployer (BR-6, P2-1) +В `deployer.md` вынести самые критичные self-hosting-запреты в **видную рамку в начале** (сразу +после frontmatter / в начале ``), как минимум: «**NEVER restart the prod `orchestrator` +(8500) container**». Существующий blockquote усилить/поднять. Инвариант анти-регресса: маркеры +`docker exec orchestrator-staging`, `pr_already_merged`, `8500`, `INFRA-WAIVED` сохраняются. + +### FR-7 — Обогащение tester (BR-7, P2-3) +В `tester.md`: +- **worktree-путь:** явно указать, что тесты гоняются в worktree ветки задачи (а не в общем + `/repos/orchestrator`), чтобы исключить гонки checkout; зафиксировать корректный путь алгоритма. +- **serial_gate smoke:** в smoke `/queue` добавить проверку наличия блока `serial_gate` + (ORCH-088) в ответе. +- **покрытие ТЗ:** в `` добавить, что готовность = каждый TC из + `04-test-plan.yaml` выполнен и сопоставлен с `03-acceptance-criteria.md`, а не только «файл + записан». Инвариант анти-регресса: маркеры `pytest`, `/health`, `/status`, `/queue` сохраняются. + +### FR-8 — Удаление мёртвой инструкции reviewer (BR-8, P2-4) +В `reviewer.md` удалить строку-запрет «❌ Не апрувь PR от того же экземпляра Developer → +✅ выноси независимый вердикт» (защита от несуществующего кейса — reviewer всегда отдельный +agent-run). Перед удалением убедиться, что ни один тест на неё не опирается (анти-регресс reviewer +держит только `REQUEST_CHANGES` и «НЕ обновлена» — они сохраняются). Ось «независимый вердикт по +4 осям» остаётся выражена через ``/``. + +### FR-9 — Ручной rebase developer по решению ADR (BR-9, P1-2) — **зона архитектора** +Установленный факт (A-2): движок уже выполняет rebase автоматически (`auto_rebase_onto_main` в +`check_branch_mergeable`, `premerge_rebase_always=True`; serial-gate режет ветку от свежего +`origin/main`). Требование: архитектор в ADR решает — убрать/смягчить/оставить-с-пояснением шаг +`git fetch origin && git rebase origin/main` в алгоритме developer; developer.md приводится в +соответствие. БЕЗ ADR-решения промпт-строку rebase **не менять**. + +### FR-10 — Язык deployer по решению ADR (BR-10, P2-2) — **зона архитектора** +Архитектор решает: унифицировать deployer на русский (как остальные 5) ЛИБО явно задокументировать +исключение («deployer — en по причине критичных команд/контрактов»). Инвариант: при любом исходе +machine-verdict ключи (`staging_status:`/`deploy_status:`/`security_status:` + значения +SUCCESS/FAILED/PASS/FAIL) и shell-команды НЕ переводятся/не ломаются. БЕЗ ADR-решения язык +**не менять**. + +### FR-11 — Анти-регресс-тесты новых инвариантов (BR-11) +В `tests/test_agent_prompts_canon.py` (pure-text, без импорта `src/`, кроме TC-03 сверки реестра) +добавить проверки: плейсхолдеры даты/модели в примерах (нет литерала `created_at: 2026-`/ +`model_used: claude-opus-4-8` в копируемом блоке); наличие `` у developer/reviewer/ +tester; отсутствие удалённой мёртвой строки reviewer; обогащение tester (serial_gate/worktree/ +покрытие ТЗ); рамка в deployer. Существующие проверки (5 секций, 6 полей, verdict-ключи, +анти-регресс-маркеры) остаются зелёными. + +## 4. Изменения API +Нет. Эндпоинты не добавляются и не меняются. + +## 5. Изменения схемы БД +Нет. Схема БД не трогается. + +## 6. Требования к новым/изменённым QG checks +Нет. `QG_CHECKS` / `check_*` / `STAGE_TRANSITIONS` **не трогаются**. Имена гейтов в промптах лишь +**сверяются** с существующим реестром (FR-3). `frontmatter_validation_strict` остаётся `False` +(enforcement не включается). + +## 7. Совместимость / регресс + +- **Машинные verdict-ключи** — байт-в-байт: `verdict:` (APPROVED|REQUEST_CHANGES), `result:` + (PASS|FAIL), `staging_status:`/`deploy_status:` (SUCCESS|FAILED), `security_status:` (PASS|FAIL). + Гарант — `test_machine_verdict_keys_preserved_exact_case`. +- **Канон 52d/52c/52e** — 5 секций в нормативном порядке (context→task→deliverables→constraints→ + output_format), 6 полей схемы, правило трассировки. `` добавляется как 6-я + необязательная секция ПОСЛЕ ``/`` — порядок обязательной + пятёрки не нарушается. Гаранты — `test_five_xml_sections_present`, + `test_six_schema_field_names_present`, `test_schema_pins_role_specific_author_and_stage`. +- **Frontmatter определения агента** — верхний `---`-блок (name/description, без `model:`) + не трогается; примеры схемы живут в теле. Гарант — `tests/test_agent_frontmatter_no_model.py`. +- **Область раската / обратимость** — docs/prompts-only; вступает в силу на следующем worktree + от `main`; прод-рестарт НЕ требуется; полностью ревертируемо одним PR. +- **Полный регресс** `pytest tests/ -q` остаётся зелёным. + +## 8. Артефакты pipeline, создаваемые/обновляемые этой задачей +- Анализ (этот пакет): `01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`, `04-test-plan.yaml`. +- Архитектура: `06-adr/ADR-001-*.md` (решения P1-2 FR-9, P2-2 FR-10), при сквозном эффекте — + возможный `10-tech-risks.md`. +- Разработка: 6 промптов + `tests/test_agent_prompts_canon.py` + `CLAUDE.md`/README/`CHANGELOG.md`. diff --git a/docs/work-items/ORCH-092/03-acceptance-criteria.md b/docs/work-items/ORCH-092/03-acceptance-criteria.md new file mode 100644 index 0000000..43bdd9e --- /dev/null +++ b/docs/work-items/ORCH-092/03-acceptance-criteria.md @@ -0,0 +1,151 @@ +--- +work_item: ORCH-092 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-09 +model_used: claude-opus-4-8 +--- + +# 03 — Критерии приёмки (Acceptance Criteria): ORCH-092 — Промпт-аудит 6 агентов + +Work Item: **ORCH-092** · Repo: **orchestrator** · Стадия: analysis + +Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** +(что считается провалом). Reviewer/tester проверяют буквально по файлам репозитория +(`.openclaw/agents/*.md`, `tests/`, `docs/`). + +--- + +## AC-1 — `created_at` в примерах всех 6 промптов — плейсхолдер (P0-1, BR-1, FR-1) + +**Условие:** В копируемом примере frontmatter каждого из 6 промптов дата не захардкожена. +- **PASS:** В `analyst/architect/developer/reviewer/tester/deployer.md` пример несёт + `created_at: ` (плейсхолдер); рядом — явная инструкция «подставь фактическую дату + (`date +%F`), НЕ копируй из примера». Литерала `created_at: 2026-06-09` (или иной конкретной + даты) в **копируемом блоке** нет. +- **FAIL:** Хотя бы один промпт оставляет конкретную дату в примере, или отсутствует инструкция + «не копируй буквально». + +--- + +## AC-2 — `model_used` в примерах — плейсхолдер/резолв (P0-2, BR-2, FR-2) + +**Условие:** В копируемом примере frontmatter каждого из 6 промптов модель не захардкожена. +- **PASS:** Пример несёт `model_used: ` (или эквивалентный плейсхолдер) + + оговорку «подставь фактическую модель из конфига». Литерал `claude-opus-4-8` в **копируемом + блоке** отсутствует (допускается как справка в таблице полей вне блока). +- **FAIL:** Хотя бы один промпт оставляет `model_used: claude-opus-4-8` в копируемом примере, + или нет оговорки про подстановку. + +--- + +## AC-3 — Имена гейтов сверены с `QG_CHECKS` (P0-3, BR-3, FR-3) + +**Условие:** Все `check_*`/имена QG-функций в промптах соответствуют реестру `QG_CHECKS`. +- **PASS:** Каждое имя гейта, встречающееся в 6 промптах, присутствует ключом в + `QG_CHECKS` (`src/qg/checks.py`). Реальные несовпадения (если бы были) исправлены; ложные + (напр. `check_tests_passed` — верен) НЕ тронуты. Сверка закреплена тестом (см. AC-10/TC-03). +- **FAIL:** В промпте остаётся имя гейта, которого нет в `QG_CHECKS`; ИЛИ исправлено верное имя + «вслепую» (придуманная замена). + +--- + +## AC-4 — developer: «PR>1500» → эскалация (P1-1, BR-4, FR-4) + +**Условие:** Нереализуемая инструкция о разбиении PR переформулирована. +- **PASS:** `developer.md` НЕ содержит инструкции «разбивай на меньшие PR»; вместо неё — + эскалация: слишком большой PR → флагировать/эскалировать (нужна декомпозиция на уровне задач, + 1 задача = 1 ветка = 1 PR). Маркер «свой PR» («не мержи свой PR») сохранён. +- **FAIL:** Старая формулировка «разбивай на меньшие PR» осталась; ИЛИ при правке удалён маркер + «свой PR». + +--- + +## AC-5 — `` в developer/reviewer/tester (P1-3, BR-5, FR-5) + +**Условие:** Три промпта получили секцию `` с чёткими маршрутами. +- **PASS:** `developer.md`, `reviewer.md`, `tester.md` содержат ``…`` + (после ``), с маршрутами: developer → `back-to:analysis`; tester → + `back-to:dev` (при FAIL); reviewer → `REQUEST_CHANGES`. Нормативный порядок 5 обязательных + секций НЕ нарушен. +- **FAIL:** Хотя бы у одного из трёх нет ``; ИЛИ её добавление сломало порядок/ + наличие 5 обязательных секций. + +--- + +## AC-6 — deployer: рамка запретов + решённый язык (P2-1/P2-2, BR-6/BR-10, FR-6/FR-10) + +**Условие:** Критичные self-hosting-запреты подняты в видную рамку; вопрос языка решён. +- **PASS:** `deployer.md` несёт **в начале** видную рамку с критичным запретом «NEVER restart + prod 8500». Язык deployer решён архитектором в `06-adr/`: либо унифицирован на ru, либо + зафиксировано явное исключение (en) с обоснованием. Маркеры `docker exec orchestrator-staging`, + `pr_already_merged`, `8500`, `INFRA-WAIVED` сохранены; verdict-ключи и команды не сломаны. +- **FAIL:** Критичный запрет не выделен/утоплен в тексте; ИЛИ язык не решён (нет ADR-решения); + ИЛИ потерян анти-регресс-маркер / сломан verdict-ключ при переводе. + +--- + +## AC-7 — tester обогащён (P2-3, BR-7, FR-7) + +**Условие:** tester получил worktree-путь, serial_gate smoke и покрытие ТЗ. +- **PASS:** `tester.md`: (а) явно указывает worktree-путь ветки задачи (а не общий + `/repos/orchestrator`) для прогона тестов; (б) smoke `/queue` проверяет наличие блока + `serial_gate` (ORCH-088); (в) `` требует покрытия каждого TC из + `04-test-plan.yaml` (а не только «файл записан»). Маркеры `pytest`/`/health`/`/status`/`/queue` + сохранены. +- **FAIL:** Отсутствует любой из трёх пунктов; ИЛИ потерян анти-регресс-маркер tester. + +--- + +## AC-8 — Удалена мёртвая инструкция reviewer (P2-4, BR-8, FR-8) + +**Условие:** Строка про «тот же экземпляр Developer» удалена без потери живых инвариантов. +- **PASS:** `reviewer.md` НЕ содержит «не апрувь PR от того же экземпляра Developer». Маркеры + `REQUEST_CHANGES` и «НЕ обновлена», ось документации, ось трассировки (`TRACEABILITY.md`), + ось обзорных доков (`Известные ограничения`, `ORCH-079`) сохранены. +- **FAIL:** Мёртвая строка осталась; ИЛИ при удалении пострадал живой инвариант reviewer. + +--- + +## AC-9 — АНТИ-РЕГРЕСС: verdict-ключи + канон + `src/` не тронут (NFR-1/2, BR-11) + +**Условие:** Машинные контракты и канон сохранены, код не тронут. +- **PASS:** verdict-ключи `verdict:`/`result:`/`staging_status:`/`deploy_status:`/ + `security_status:` (+ значения APPROVED/REQUEST_CHANGES/PASS/FAIL/SUCCESS/FAILED) — байт-в-байт. + 5 XML-секций в нормативном порядке + 6 полей 52c во всех 6 промптах. `src/**`, + `STAGE_TRANSITIONS`, `QG_CHECKS`, схема БД — без изменений в diff. `git diff --stat` не содержит + `src/`. `tests/test_agent_prompts_canon.py` и `tests/test_agent_frontmatter_no_model.py` — + зелёные. +- **FAIL:** Любой verdict-ключ изменён по имени/регистру/значению; нарушен порядок/наличие 5 + секций или 6 полей; есть правка `src/`; целевые тесты красные. + +--- + +## AC-10 — Документация и тесты обновлены (BR-11, FR-11) + +**Условие:** Обзорная документация и анти-регресс-тесты отражают изменение. +- **PASS:** `CHANGELOG.md` несёт запись ORCH-092; `CLAUDE.md`/`docs/architecture/README.md` + обновлены при необходимости; `06-adr/ADR-001-*.md` фиксирует решения P1-2/P2-2; новые + структурные TC (плейсхолдеры даты/модели, ``, удаление мёртвой строки, обогащение + tester, рамка deployer, сверка гейтов) добавлены в `tests/test_agent_prompts_canon.py` и + зелёные; полный `pytest tests/ -q` зелёный. +- **FAIL:** Отсутствует ADR-решение P1-2/P2-2; нет записи в CHANGELOG; новые инварианты не + покрыты тестом; регресс красный. + +--- + +## Сводная матрица AC ↔ FR/BR + +| AC | Покрывает | +|----|-----------| +| AC-1 | BR-1 / FR-1 | +| AC-2 | BR-2 / FR-2 | +| AC-3 | BR-3 / FR-3 | +| AC-4 | BR-4 / FR-4 | +| AC-5 | BR-5 / FR-5 | +| AC-6 | BR-6 / BR-10 / FR-6 / FR-10 | +| AC-7 | BR-7 / FR-7 | +| AC-8 | BR-8 / FR-8 | +| AC-9 | NFR-1 / NFR-2 / FR-9 (rebase по ADR без слома канона) | +| AC-10 | BR-9 / BR-11 / FR-9 / FR-11 | diff --git a/docs/work-items/ORCH-092/04-test-plan.yaml b/docs/work-items/ORCH-092/04-test-plan.yaml new file mode 100644 index 0000000..98fce05 --- /dev/null +++ b/docs/work-items/ORCH-092/04-test-plan.yaml @@ -0,0 +1,89 @@ +work_item: ORCH-092 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-09 +model_used: claude-opus-4-8 +title: "Промпт-аудит 6 агентов: расхардкод дат/модели, сверка гейтов, escalation, чистка" +framework: pytest +scope: > + Покрываются структурные (pure-text) инварианты 6 промптов .openclaw/agents/*.md после + аудита ORCH-092, плюс анти-регресс канона 52d/52c/52e и машинных verdict-ключей. Вне + покрытия: поведение src/ (НЕ трогается), запуск реальных агентов. Полный регресс tests/ + должен оставаться зелёным. Новые TC живут в tests/test_agent_prompts_canon.py; TC-03 — + единственный с импортом QG_CHECKS (integration). + +notes: > + Все правки docs/prompts-only — src/ не изменяется, прод-контейнер 8500 не перезапускается. + Регрессом считается: слом любого verdict-ключа (verdict:/result:/staging_status:/ + deploy_status:/security_status:) по имени/регистру/значению; нарушение порядка/наличия 5 + XML-секций или 6 полей 52c; красный test_agent_prompts_canon.py или + test_agent_frontmatter_no_model.py. P1-2 (rebase) и P2-2 (язык deployer) фиксируются ADR — + TC проверяют лишь, что промпт согласован и канон/ключи не сломаны. + +tests: + - id: TC-01 + type: unit + description: "AC-1: во всех 6 промптах пример frontmatter использует created_at: (нет литерала конкретной даты в копируемом блоке) и несёт инструкцию 'не копируй дату буквально'." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-02 + type: unit + description: "AC-2: во всех 6 промптах пример несёт model_used: (нет литерала claude-opus-4-8 в копируемом блоке) + оговорку про подстановку фактической модели." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-03 + type: integration + description: "AC-3: каждое имя check_* в 6 промптах присутствует ключом в QG_CHECKS (импорт src.qg.checks). check_tests_passed подтверждён валидным; нет имён вне реестра." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-04 + type: unit + description: "AC-4: developer.md не содержит 'разбивай на меньшие PR'; содержит эскалацию для слишком большого PR (декомпозиция на уровне задач); маркер 'свой PR' сохранён." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-05 + type: unit + description: "AC-5: developer.md, reviewer.md, tester.md содержат секцию с маршрутами back-to:analysis / back-to:dev / REQUEST_CHANGES соответственно." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-06 + type: unit + description: "AC-7: tester.md содержит явный worktree-путь, smoke-проверку блока serial_gate в /queue (ORCH-088) и упоминание покрытия ТЗ (каждый TC из 04-test-plan) в success_criteria; маркеры pytest//health//status//queue сохранены." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-07 + type: unit + description: "AC-6: deployer.md несёт в начале видную рамку с запретом рестарта прод-8500; анти-регресс-маркеры docker exec orchestrator-staging / pr_already_merged / 8500 / INFRA-WAIVED сохранены." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-08 + type: unit + description: "AC-8: reviewer.md не содержит 'того же экземпляра Developer'; маркеры REQUEST_CHANGES, 'НЕ обновлена', TRACEABILITY.md, 'Известные ограничения', ORCH-079 сохранены." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-09 + type: unit + description: "AC-9 анти-регресс: verdict-ключи (verdict:/result:/staging_status:/deploy_status:/security_status:) и значения (APPROVED/REQUEST_CHANGES/PASS/FAIL/SUCCESS/FAILED) присутствуют байт-в-байт; 5 XML-секций в нормативном порядке + 6 полей 52c во всех 6 промптах (существующие канон-проверки зелёные)." + module: tests/test_agent_prompts_canon.py + expected: PASS + + - id: TC-10 + type: unit + description: "AC-9: верхний frontmatter определения агента остаётся валидным YAML с name/description и без ключа model: во всех 6 промптах (регресс test_agent_frontmatter_no_model.py)." + module: tests/test_agent_frontmatter_no_model.py + expected: PASS + + - id: TC-11 + type: integration + description: "AC-9/AC-10: полный регресс pytest tests/ -q зелёный; git diff не содержит правок src/ (docs/prompts-only)." + module: tests/ + expected: PASS