architect(ET): auto-commit from architect run_id=460

This commit is contained in:
2026-06-09 14:48:03 +03:00
committed by orchestrator-deployer
parent bd5d681083
commit b21e9d8898
5 changed files with 362 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
---
work_item: ORCH-077
stage: architecture
author_agent: architect
status: proposed
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# ADR-001: Канон Anthropic для 6 системных промптов + добровольная эмиссия frontmatter-схемы 52c
Work Item: **ORCH-077** — ORCH-52d: оптимизация 6 системных промптов по Anthropic (замыкающий слой эпика ORCH-52)
Стадия: **architecture**
Сквозная регистрация: **`docs/architecture/adr/adr-0021-prompt-canon-anthropic.md`** (решение кросс-каттинговое — задаёт долгоживущий стандарт формы ВСЕХ агент-промптов прода).
## Статус
Proposed
## Контекст
Эпик **ORCH-52** строит сквозной контракт документации конвейера тремя слоями:
- **52b (ORCH-075)** — описательный стандарт: `docs/_standards/PIPELINE_DOCS.md` + скелеты `docs/_templates/`.
- **52c (ORCH-076)** — машинный контракт: `src/frontmatter.py` (reader + writer + валидатор
`validate_schema`/`REQUIRED_FIELDS`) + спека `docs/_standards/HANDOFF_PROTOCOL.md` с обязательной
схемой `(work_item, stage, author_agent, status, created_at, model_used)`.
- **52d (эта задача, ORCH-077)** — слой промптов: замыкающее звено.
**Две проблемы (сверено с кодом и файлами репозитория):**
1. **Разрыв цепочки 52b→52c→52d.** 52c заложила writer и валидатор обязательной схемы, но работает
warning-only (`frontmatter_validation_strict=False`, дефолт; `src/frontmatter.py`,
`HANDOFF_PROTOCOL.md §1`). Агенты **физически не проставляют** 6 полей схемы — на входе валидатора
нет данных. Петля 52 не замкнута: writer есть, валидатор есть, эмиттера (промпта) нет.
2. **Разнородная форма промптов.** 6 системных промптов `.openclaw/agents/*.md` написаны в свободной
форме (analyst/architect/developer/reviewer/tester — RU, deployer — EN), без единой структуры.
Это снижает предсказуемость поведения агентов прода и затрудняет сопровождение.
**Факты загрузки промпта (сверено с `src/agents/launcher.py`):**
- Маппинг роль → путь промпта — `launcher` строки ~297323 (`"system_prompt": ".openclaw/agents/<role>.md"`).
- Промпт передаётся в Claude CLI как `--system-prompt "$(cat {system_prompt})"` (`launcher` ~577):
файл **читается из рабочего git-worktree агента в момент запуска**, путь относительный, НЕ запечён в
образ (`Dockerfile` копирует только `src/`, не `.openclaw/`).
- Модель/эффорт берутся ТОЛЬКО из config (`resolve_agent_model`/`resolve_agent_effort`, ORCH-41);
frontmatter `model:` удалён как мёртвый (ORCH-074, `tests/test_agent_frontmatter_no_model.py`).
Все 6 ролей сейчас на `claude-opus-4-8`.
Эти факты определяют две неочевидные следствия (см. D6): прод-рестарт для применения новых промптов
**не требуется**, и новые промпты **частично самоприменяются внутри этой же ветки** (in-vivo A/B).
## Решение
### Сводка
Переписать тело всех 6 промптов в едином XML-каноне Anthropic с фиксированным порядком из 5
обязательных секций; научить каждый промпт **добровольно** (warning-only, без enforcement) эмитить
6-польную frontmatter-схему 52c **аддитивно** — поверх существующих machine-verdict ключей, не меняя
их имя/регистр/значения. Изменение — **docs/prompts-only**: `src/**` не трогается. Стандарт формы
фиксируется сквозным ADR adr-0021 как обязательный для всех будущих правок промптов.
### D1 — Канонический скелет: фиксированный порядок 5 обязательных секций (BR-1 / FR-1 / AC-1)
Тело каждого из 6 промптов строится строго в этом порядке (XML-теги — разделители смысловых блоков):
1. `<context>` — кто агент, проект orchestrator, стек, self-hosting; **обязательный первый пункт:
«прочти `CLAUDE.md` и `docs/architecture/README.md` перед любым действием»**.
2. `<task>` — что делает роль на своей стадии; **допускается вложенная `<thinking>`-подсказка**
(D4) для решающих ролей.
3. `<deliverables>` — какие файлы и куда роль создаёт через Write tool; ссылки на скелеты
`docs/_templates/` и эталоны (D3).
4. `<constraints>` — запреты и обязательные правила; каждый запрет — с позитивной альтернативой (D3).
5. `<output_format>` — точный формат выходных документов: frontmatter-схема (D2) + machine-verdict
ключи + success-criteria (FR-5).
Дополнительные семантические секции (`<success_criteria>`, `<escalation>`) допустимы ПОСЛЕ пяти
обязательных. **Обоснование порядка:** роль/контекст вперёд (приоритет интерпретации), формат вывода
последним (recency — лучшее следование схеме у Opus 4.8). Порядок — нормативный (структурный тест
проверяет наличие всех 5 тегов; см. test-plan).
### D2 — Аддитивная эмиссия схемы 52c, machine-verdict ключи неприкосновенны (BR-2/BR-4 / FR-2 / NFR-1)
Секция `<output_format>` каждого промпта **явно перечисляет 6 полей** схемы с конкретными для роли
значениями. Инвариант размещения:
- **Markdown-документы с frontmatter** (`12`/`13`/`14`/`15`/`17`, а также `01`/`02`/`03`, `06-adr`,
`07`/`08`/`10`): 6 полей схемы добавляются в **ведущий YAML-frontmatter-блок РЯДОМ** с существующим
machine-verdict ключом. Machine-verdict ключ сохраняет **имя, регистр и набор значений байт-в-байт**
(`verdict:` `APPROVED|REQUEST_CHANGES`; `result:` `PASS|FAIL`; `staging_status:`/`deploy_status:`
`SUCCESS|FAILED`; `security_status:` `PASS|FAIL`). Порядок ключей в YAML-mapping парсеру безразличен
(`frontmatter.parse_frontmatter` читает по имени), но схему ставим ПОСЛЕ verdict-ключа, чтобы
визуально не «утопить» вердикт.
- **`04-test-plan.yaml`** — чистый YAML (без `---`-fence; сверено со скелетом `docs/_templates/`):
5 недостающих полей (`stage`/`author_agent`/`status`/`created_at`/`model_used`) кладутся как
**top-level ключи рядом** с уже присутствующими `work_item:` и `tests:`. Структура `tests:` не
трогается.
**Карта роль → значения схемы** (нормативна; источник `model_used` — README §«Модель и эффорт», ORCH-41):
| Роль | `stage` | `author_agent` | `status` (пример) | Документы со схемой | Machine-key (НЕ трогать) |
|------|---------|----------------|-------------------|---------------------|--------------------------|
| analyst | `analysis` | `analyst` | `ready-for-review` | `01`,`02`,`03`,`04` | — |
| architect | `architecture` | `architect` | `proposed`/`accepted` | `06-adr/*`,`07`,`08`,`10` | — |
| developer | `development` | `developer` | `in-progress`/`done` | `07`/`08`/`10` (when-applicable) | — (гейт `check_ci_green`) |
| reviewer | `review` | `reviewer` | согласован с `verdict:` | `12-review.md` | `verdict:` |
| tester | `testing` | `tester` | согласован с `result:` | `13-test-report.md` | `result:` |
| deployer | `deploy-staging`,`deploy` | `deployer` | согласован с `*_status:` | `15`,`14`,`17` (w-a) | `staging_status:`,`deploy_status:`,`security_status:` |
`model_used: claude-opus-4-8` для всех ролей на текущий момент (промпт ссылается на резолв ORCH-41,
а не хардкодит «навсегда» — при будущем model-routing значение пересматривается, вне ORCH-077).
`created_at` — текущая дата `YYYY-MM-DD` (источник — `date +%F` через Bash там, где Bash в `tools:`;
иначе подставляется агентом из контекста задачи).
### D3 — Few-shot и позитивные альтернативы (BR-3 / FR-3 / AC-3)
В каждом промпте: (а) ссылка на копируемый скелет роли в `docs/_templates/`; (б) ссылка на ≥1 эталон
(**ORCH-073** и/или **ORCH-088** — заполненные work item высокого качества); (в) каждый запрет в
`<constraints>` — в формате **«❌ не делай X → ✅ делай Y»** (литеральность Opus 4.8: позитивный
пример рядом с запретом снижает мисинтерпретацию). Эталоны даются **ссылкой**, не инлайном (контроль
объёма, R-4).
### D4 — Явное место для рассуждения (CoT/thinking) у решающих ролей (FR-4)
Роли, выносящие вердикт/классификацию, несут `<thinking>`-подсказку «сначала рассуди, потом пиши
вердикт» внутри `<task>`: **architect** (выбор решения), **reviewer** (APPROVED/REQUEST_CHANGES),
**tester** (PASS/FAIL/BLOCKED), **deployer** (трактовка exit-кодов, ORCH-061 waiver). Для механических
ролей (analyst/developer) — не обязательно. `<thinking>` — рассуждение агента, не часть выходного
документа.
### D5 — Анти-регресс через построчный инвентарь + структурные тесты (BR-4 / FR-6 / AC-4, критично)
Self-hosting: промпт = поведение агента прода для ВСЕХ проектов. Потеря рабочей инструкции = регресс
выхода для enduro-trails и orchestrator. Защита в три слоя:
1. **Построчная карта переноса** «старая инструкция → секция нового промпта» — developer ведёт в
`12-review.md`/коммите как чек-лист; reviewer проверяет ПОСТРОЧНО против инвентаря TRZ §FR-6.
2. **Структурные тесты** (`tests/test_agent_prompts_canon.py`, чистый pytest, БЕЗ запуска агентов,
НЕ трогают `src/`): присутствие 5 XML-секций; присутствие 6 имён полей схемы; присутствие
machine-verdict ключей в точном регистре; присутствие ключевых анти-регресс-маркеров (deployer:
`docker exec orchestrator-staging`, `pr_already_merged`, «не рестартить 8500»; reviewer: правило
«src/ изменён, доки нет → REQUEST_CHANGES»; developer: `--no-verify`/`--force-push`/«не мержить
свой PR»).
3. **Существующий `test_agent_frontmatter_no_model.py`** остаётся зелёным (FR-7): frontmatter промпта
(`name`/`description`/`tools`) сохраняется, `model:` не возвращается.
### D6 — Rollout & loading-model: без прод-рестарта; in-vivo A/B (BR-6 / FR-7 / NFR-2/NFR-5)
Из фактов загрузки (Контекст): промпт `cat`-ается из worktree в момент запуска агента, не из образа.
Следствия:
- **Применение без рестарта прода.** После merge ветки в `main` следующий worktree, срезанный от
`main`, уже содержит новые промпты — они вступают в силу **без `docker compose up`/рестарта 8500**.
Это снимает классический self-hosting-риск «правка инструмента требует рестарта прода» (CLAUDE.md
§Self-hosting): данная задача его структурно не несёт.
- **In-vivo A/B (метод для BR-6/AC-6).** Worktree последующих стадий ORCH-077 срезается на HEAD
ветки → как только developer закоммитит новые промпты, **reviewer/tester самой ORCH-077 исполнятся
уже под новыми промптами**. Это естественный A/B: достаточно зафиксировать в `13-test-report.md`
сравнение «старый vs новый» на ≥1 репрезентативной стадии — структурная полнота артефакта,
парсимость machine-verdict, число циклов `REQUEST_CHANGES` (критерий: новый **не хуже**). Метод
**offline**, без прод-рестарта и без деструктива (NFR-2). Дополнительно допустимо ручное сравнение
артефакта одной стадии, сгенерированного под обоими промптами на фиксированном входе.
- **Обратимость (NFR-5).** Изменение чисто текстовое → откат = `git revert` PR, без миграций
состояния/БД.
### D7 — Enforcement НЕ включается (граница scope)
`frontmatter_validation_strict` остаётся `False` (warning-only). 52d учит промпты эмитить схему
**добровольно**; включение hard-fail = правка `src/config.py` = вне scope (BR-5/AC-5). Гейты читают
вердикты ровно как раньше — схема в boolean-вердикте не участвует (NFR-1). Этот ADR фиксирует границу
явно, чтобы будущий reviewer не принял отсутствие enforcement за недоделку.
## Альтернативы
- **Включить hard-fail валидации схемы сразу (52d = enforcement).** Отвергнуто: правка `src/config.py`
вне scope; рискованно для self-hosting (любой агент, забывший поле, заваливает гейт всех проектов).
Сначала научить эмитить (этот ADR), enforcement — отдельной задачей после накопления данных.
- **Свободный порядок секций / «рекомендация, не норма».** Отвергнуто: теряется предсказуемость и
машинная проверяемость (AC-1), эпик 52 требует именно контракт, не пожелание.
- **Инлайнить эталонные артефакты целиком в промпт.** Отвергнуто: раздувание (R-4) «утопит» ключевые
запреты; ссылка на ORCH-073/088 даёт тот же few-shot-эффект дешевле.
- **Запечь промпты в образ + версионировать через рестарт.** Отвергнуто: противоречит текущей
loading-model (cat из worktree), добавил бы прод-рестарт-зависимость, которой сейчас нет.
## Последствия
- **+** Петля 52 замкнута: схема 52c наполняется реальными данными на каждой стадии всех проектов.
- **+** Единый канон → предсказуемее выход агентов, проще сопровождение, дешевле будущие правки.
- **+** Применение без прод-рестарта (D6) — нулевой self-hosting-риск выкатки промптов.
- **** Объём промптов вырастет (XML + few-shot). Митигейшн: ссылки вместо инлайна, контроль объёма
(NFR-4), структурный тест без жёсткого лимита строк.
- **** Риск потери рабочей инструкции при рефакторе формы (R-1). Митигейшн: D5 (карта + тесты +
построчный review).
- **** In-vivo самоприменение (D6) означает, что баг в новом промпте мог бы повлиять на reviewer/
tester самой ORCH-077. Митигейшн: анти-регресс D5 + откат revert; вердикт-логика гейтов не зависит
от промпта (читается из frontmatter кодом).
- **Откат:** `git revert` PR — промпты возвращаются к свободной форме, схема перестаёт эмититься,
гейты работают идентично (machine-verdict ключи не менялись). Без миграций.
## Ссылки
- BRD: `docs/work-items/ORCH-077/01-brd.md`
- TRZ: `docs/work-items/ORCH-077/02-trz.md`
- Acceptance: `docs/work-items/ORCH-077/03-acceptance-criteria.md`
- Tech-risks: `docs/work-items/ORCH-077/10-tech-risks.md`
- Сквозной ADR: `docs/architecture/adr/adr-0021-prompt-canon-anthropic.md`
- Стандарты эпика: `docs/_standards/PIPELINE_DOCS.md` (52b), `docs/_standards/HANDOFF_PROTOCOL.md` (52c),
`src/frontmatter.py::REQUIRED_FIELDS`
- Сверено по коду: `src/agents/launcher.py` (~297323, ~577), `Dockerfile`,
`src/config.py::frontmatter_validation_strict`, `tests/test_agent_frontmatter_no_model.py`

View File

@@ -0,0 +1,45 @@
---
work_item: ORCH-077
stage: architecture
author_agent: architect
status: ready-for-review
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# 10 — Технические риски: ORCH-077 — ORCH-52d: оптимизация 6 системных промптов по Anthropic
Work Item: **ORCH-077** · Repo: **orchestrator** (self-hosting) · Стадия: architecture
> Информационный (гейтом не парсится). Перечисляет риски реализации и митигейшн.
> Главный класс риска — **анти-регресс поведения агента прода**: промпт исполняется на КАЖДОЙ
> задаче ВСЕХ проектов (orchestrator + enduro-trails) из общего инстанса.
## Реестр рисков
| ID | Риск | Вер. | Влия. | Митигейшн |
|----|------|------|-------|-----------|
| TR-1 | **Регресс поведения агента**: при рефакторе формы потеряна рабочая инструкция → агент ломает выход для всех проектов | Сред. | Выс. | Построчная карта переноса (ADR D5) + структурные тесты `test_agent_prompts_canon.py` + построчный review против инвентаря TRZ §FR-6; in-vivo A/B (D6) |
| TR-2 | **Ложный гейт-провал**: случайно изменён регистр/имя/значения machine-verdict ключа (`verdict:`/`result:`/`staging_status:`/`deploy_status:`/`security_status:`) → парсер не находит вердикт | Низ. | Выс. | Эмиссия схемы строго аддитивна (ADR D2); структурный тест проверяет точный регистр ключей и значений; `frontmatter.parse_frontmatter` читает по имени (порядок неважен) |
| TR-3 | **Потеря self-hosting-запрета deployer'а**: пропал «не рестартить 8500 изнутри» / canonical `docker exec orchestrator-staging` / merge-guard `pr_already_merged` → агент роняет прод-конвейер всех проектов | Низ. | Крит. | deployer — самый строгий инвентарь §FR-6; отдельные структурные ассерты на 3 маркера; reviewer проверяет deployer построчно в первую очередь |
| TR-4 | **Раздувание промпта**: XML-канон + few-shot «утопят» ключевые запреты, агент их проигнорирует | Сред. | Сред. | Эталоны ссылкой, не инлайном (D3); контроль объёма (NFR-4); запреты — компактным списком ❌→✅ в `<constraints>` |
| TR-5 | **Некорректный `model_used`**: захардкожена неверная модель вместо резолва ORCH-41 | Низ. | Низ. | Промпт ссылается на резолв ORCH-41 и таблицу README; текущее значение `claude-opus-4-8` для всех ролей; информационное поле (не гейт) |
| TR-6 | **Сломан frontmatter промпта**: правка тела случайно затронула YAML-шапку (`name`/`description`/`tools`) или вернула `model:` | Низ. | Сред. | `test_agent_frontmatter_no_model.py` остаётся зелёным (FR-7); правится только тело ниже frontmatter |
| TR-7 | **In-vivo самоприменение** (D6): дефект нового промпта влияет на reviewer/tester самой ORCH-077 | Низ. | Сред. | Вердикт-логика гейтов читается кодом из frontmatter, не зависит от текста промпта; анти-регресс D5; откат `git revert` |
| TR-8 | **Расползание scope в код**: соблазн «заодно» включить `frontmatter_validation_strict` или тронуть `src/` | Низ. | Выс. | AC-5 (git diff только `.openclaw/*`, `docs/**`, `CHANGELOG.md`, новые `tests/test_*`); ADR D7 фиксирует границу; reviewer проверяет diff |
| TR-9 | **Несогласованность `status` с machine-verdict**: например `status: ready` при `verdict: REQUEST_CHANGES` → путаница наблюдателя | Низ. | Низ. | Карта ADR D2 предписывает `status`, согласованный с вердиктом для вердикт-ролей; информационное поле, гейт не зависит |
## Сводный вывод
Доминирующий класс — **анти-регресс поведения агентов прода** (TR-1/TR-3), критичный из-за
self-hosting и общего инстанса. Изменение при этом **docs/prompts-only**, чисто текстовое, обратимое
`git revert` без миграций; loading-model (cat промпта из worktree, ADR D6) исключает прод-рестарт →
выкатка не несёт классического self-hosting-риска рестарта.
**Эскалация `arch:major-change` НЕ требуется**: новых стадий/компонентов/QG/смены БД нет;
`STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/схема БД не трогаются (BR-5). **Возврат в анализ НЕ
требуется**: ТЗ выполнимо в рамках принципов архитектуры.
Остаточный риск для прод-конвейера — **низкий при соблюдении D5** (построчная карта + структурные
тесты + приоритетный review deployer/reviewer). Ключевое предписание исполнителю: рефакторить форму
**без потери ни одной функциональной строки**; при сомнении «перенести или выбросить» — переносить.