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

This commit is contained in:
2026-06-09 16:16:42 +03:00
committed by orchestrator-deployer
parent 7d1346d90f
commit 07a2d6ad1e
4 changed files with 322 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
---
work_item: ORCH-079
stage: architecture
author_agent: architect
status: proposed
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# ADR-001: Синхронизация обзорных доков (README) с кодом + reviewer-ось «обзорные доки»
Work Item: **ORCH-079** — ORCH-52f: финальный слой эпика 52 «доки = golden source наравне с кодом».
Стадия: **architecture**
Сквозная регистрация: **`docs/architecture/adr/adr-0023-overview-docs-reviewer-axis-and-epic52-close.md`**
(решение кросс-каттинговое — меняет нормативную ось ревью-гейта для ВСЕХ задач/проектов и
закрывает эпик 52).
## Статус
Proposed
## Контекст
Эпик ORCH-52 строит сквозной контракт документации конвейера слоями: **52b** (adr-0019,
`PIPELINE_DOCS.md`) — структура доков; **52c** (adr-0020, `src/frontmatter.py`) — машинный
frontmatter-контракт; **52d** (adr-0021, ORCH-077) — 6 промптов в каноне Anthropic; **52e**
(adr-0022, ORCH-078) — стандарт трассировки маркеров. Приведены в порядок *конвейерные* доки и
*промпты*, но **корневой `README.md`** — «паспорт состояния проекта», который читатель (Owner,
новый агент, внешний наблюдатель) воспринимает как витрину истины — остался незакрытым и **лжёт о
состоянии системы**.
Факты, сверенные с кодом `main`:
1. **Битая нумерация** секции «Известные ограничения» (`README.md:236241`): фактический порядок
списка — `1, 2, 3, 4, 3, 4` (номера `3`/`4` повторяются). Список визуально некорректен.
2. **Устаревшие пункты выдают РЕШЁННОЕ за открытое.** Сверка каждого пункта с кодом:
| Пункт README | Статус | Доказательство в коде |
|--------------|--------|------------------------|
| п.1 Single-task / shared `/repos` checkout (worktree S-4) | **РЕШЕНО** | `src/agents/launcher.py` использует `ensure_worktree` (git worktree per task) + serial-gate ORCH-088 + task-deps ORCH-026 — все в проде |
| п.2 Plane sync — маппинг issue ID (P3, в работе) | **НЕ открыто** | `src/plane_sync.py`: `find_issue_id` (451), `fetch_issue_sequence_id` M-6 (541), статус-модель ORCH-066, TTL-самозалечивание ORCH-068 — зрелый слой, активной задачи нет |
| п.3 In-process daemon-потоки (целевое — очередь F-2b) | **РЕШЕНО** | `src/queue_worker.py`, таблица `jobs`, restart-safe (ORCH-1) |
| п.4 Gitea CI не настроен | **УСТАРЕЛО** | `check_ci_green` (`src/qg/checks.py:82`) — активный гейт `development`; `check_tests_local` помечен `DEPRECATED` (`:381`) |
| п.«Tester timeout — Playwright e2e >25 мин» | **УСТАРЕЛО** | orchestrator — pytest-сервис, Playwright неприменим; реальный механизм — конфигурируемый watchdog `_resolve_timeout`/`agent_timeout_seconds` (ORCH-7 M-2, `launcher.py:642`) |
| п.«No retry on API errors» | **УСТАРЕЛО** | queue-слой: exp-backoff + circuit breaker (`ORCH_BACKOFF_*`/`ORCH_BREAKER_*`/`ORCH_TRANSIENT_MAX_ATTEMPTS`, `src/queue_worker.py`); retry-loop в `check_ci_green` (`:128137`) |
3. **Процессный пробел.** Reviewer обязан проверять обновление *конвейерной* документации
(`docs/architecture/README.md`, `internals.md`, env-таблица), но **обзорные** разделы (README
«Известные ограничения») в его правиле **не названы явно** → когда PR закрывает ограничение,
ничто не заставляет автора снять пункт → витрина копит рассинхрон.
Боль: читатель принимает решения по неверной картине; эпик 52 не может считаться закрытым, пока
витрина противоречит коду. Это **docs + prompt-only** изменение: `src/**` не трогается.
## Решение
### Сводка
Привести «Известные ограничения» в честное состояние **по коду** (а не по памяти), точечно сверить
обзорные доки с `src/`, и **закрыть процессный пробел** добавив reviewer'у нормативную под-ось
«обзорные доки» (по образцу оси трассировки ORCH-078). Без машинного enforcement, без касания
`STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/схемы БД. Это замыкающий (5-й) слой эпика 52 → дополнительно
сквозной `adr-0023`.
### D1 — Перенумерация + триаж секции «Известные ограничения» (FR-1/FR-2; BR-1/2/3; NFR-3)
Все 6 текущих пунктов по сверке выше — **решены / устарели / не являются tracked-ограничением**.
Контракт триажа (NFR-3, источник истины — код): **ни один пункт не объявляется решённым без
подтверждения кодом/задачей; в списке открытых остаются ТОЛЬКО реально открытые.**
Решение по форме (developer имеет латитуду FR-2 «удаление ИЛИ перенос в „Закрыто“»):
- **Рекомендованная форма (A):** заменить 6 устаревших пунктов на (а) короткий трейл
**«Закрыто (история)»** с ORCH-ссылками — worktree → ORCH-026/088; очередь → ORCH-1; CI →
`check_ci_green`; retry/breaker → ORCH-1 resilience; issue-ID → зрелый `plane_sync` (ORCH-010/066/068);
agent-timeout → конфигурируемый watchdog ORCH-7; и (б) короткий список **реально открытых**
ограничений **только из уже задокументированных** known-limitations (анти-scope-creep, см. D4):
Telegram-48h сироты (ORCH-087), task-deps только intra-repo v1 (ORCH-026), serial-gate — Этап 1
эпика ORCH-088 (пакетный автоном — в развитии).
- **Допустимая форма (B):** полное удаление 6 пунктов + минимальная честная секция.
Перенумерация сквозная `1,2,3,…` без повторов (AC-1) выполняется как следствие переработки
содержимого.
### D2 — Reviewer-ось «обзорные доки» (FR-5; BR-5; NFR-2/NFR-4)
В `.openclaw/agents/reviewer.md` **ось 4 «Документация»** (`<task>`) и соответствующий пункт
`<constraints>` дополняются точечной врезкой в формате «❌ X → ✅ Y» (канон 52d):
> ❌ PR закрыл пункт из README «Известные ограничения», но README не обновлён → ✅ требуй обновления
> README (снять/пометить закрытым с ORCH-ссылкой) — это **finding**.
**Severity (нормативно):** базово **≥ P1** (по образцу под-оси трассировки ORCH-078). Когда
ограничение закрывает **изменение `src/`** без обновления README — это совпадает с уже
существующим **P0** «`src/` изменён, документация не обновлена» (усиление трактовки, не новая ось).
**Границы правки промпта (NFR-2/NFR-4):** машинный ключ `verdict: APPROVED | REQUEST_CHANGES`
байт-в-байт; 6 полей схемы 52c и 5 XML-секций сохранены; врезка точечная (без переписывания
промпта). Единый источник правила — текст промпта; новая ось НЕ дублируется в отдельный стандарт
(в отличие от 52e, где правило вынесено в `TRACEABILITY.md`), т.к. касается одного промпта и одного
артефакта (README) — выноса в `docs/_standards/` не требует.
### D3 — Точечная сверка обзорных доков с кодом (FR-3/FR-4; BR-4)
`README.md` (блок «Стадии пайплайна», env-таблица, описание очереди) и `docs/architecture/README.md`
(таблица «Стадия→Агент→QG→Артефакт» ↔ `STAGE_TRANSITIONS`; реестр `QG_CHECKS`
`src/qg/checks.py::QG_CHECKS`; таблица моделей/эффортов ↔ `resolve_agent_model`/`resolve_agent_effort`,
6 ролей `claude-opus-4-8`, эффорты developer=`xhigh`/tester+deployer=`medium`/прочие=`high`; перечень
компонентов ↔ модули `src/`) приводятся в соответствие коду. **Минимально инвазивно:** править
только подтверждённые расхождения, совпадающее не трогать.
### D4 — Анти-scope-creep при наполнении «открытых» (NFR-3; BRD §2 «Вне объёма»)
**Запрет на изобретение ограничений.** Новые «открытые» пункты берутся ТОЛЬКО из уже
задокументированных known-limitations (CLAUDE.md / README / ADR); массовый майнинг кодовой базы на
предмет «а что ещё может быть ограничением» — **вне объёма**. Триаж ограничен ровно 6 исходными
пунктами + перечисленным в D1 множеством уже-документированных границ. Честность важнее длины:
короткая секция с верифицируемыми пунктами лучше длинной с выдуманными.
### D5 — Анти-регресс правила структурным тестом (FR-6; NFR-1)
`tests/test_agent_prompts_canon.py` (tests-only) получает assert: `reviewer.md` содержит маркер оси
обзорных доков (подстрока «Известные ограничения»/«README» в контексте оси «Документация»). Канон 52d
(5 секций, 6 полей, точный регистр verdict-ключей) и `test_agent_frontmatter_no_model.py` остаются
зелёными.
## Альтернативы
- **Машинный enforcement reviewer-правила (новый QG / код-проверка «README актуален»).** Отвергнуто:
правка `src/`/`QG_CHECKS` вне scope; для self-hosting рискованно (ложный fail валит конвейер всех
проектов); правило остаётся нормативно-описательным, как ось трассировки ORCH-078. Enforcement —
потенциальная будущая задача (как hard-fail схемы 52c).
- **Вынести правило обзорных доков в отдельный `docs/_standards/`.** Отвергнуто: касается одного
промпта и одного артефакта (README) — врезки в промпт достаточно; новый стандарт-файл — overkill.
- **Сохранить пункты «как было», лишь починив нумерацию.** Отвергнуто: нарушает NFR-3/BR-3 (витрина
продолжит лгать).
- **Объявить плановую issue-ID / Playwright-timeout «решёнными конкретным тикетом».** Отвергнуто:
нет тикета, который их «закрыл»; честная формулировка — «не tracked-ограничение / устаревшая
формулировка», с переносом в историю или удалением (NFR-3).
- **Только per-work-item ADR без глобального.** Отвергнуто: рвёт цепочку эпика 52 (52b/c/d/e имеют
глобальный ADR); нет точки входа «эпик 52 закрыт» для будущих агентов.
## Последствия
- **+** Витрина проекта (README) перестаёт лгать; читатель принимает решения по честной картине.
- **+** Замкнут слой 5 (финал) эпика 52: reviewer получает ось контроля обзорных доков →
самоподдерживающаяся синхронность витрины (закрыл ограничение — обнови README, иначе finding).
- **+** Self-hosting без рестарта: `reviewer.md` `cat`-ается launcher'ом → правило действует на
следующем worktree от `main` без рестарта прод-контейнера 8500 (NFR-5).
- **+** Нулевая функциональная регрессия: только Markdown + один промпт + один тест; runtime-код,
verdict-контракт, схема БД не тронуты (enduro-trails не задет).
- **** Reviewer-правило нормативно, но не enforced машинно → соблюдение на дисциплине + ревью
(осознанный компромисс, как ORCH-078).
- **** Секция «открытых» может стать короткой/почти пустой — приемлемо (честность > длина, D4).
- **Откат:** `git revert` PR — доки/промпт/тест возвращаются к прежнему состоянию; поведение
кода/гейтов идентично (kill-switch не нужен — нет рантайм-поведения).
## Ссылки
- BRD: `docs/work-items/ORCH-079/01-brd.md`
- TRZ: `docs/work-items/ORCH-079/02-trz.md`
- Acceptance: `docs/work-items/ORCH-079/03-acceptance-criteria.md`
- Tech-risks: `docs/work-items/ORCH-079/10-tech-risks.md`
- Сквозной ADR: `docs/architecture/adr/adr-0023-overview-docs-reviewer-axis-and-epic52-close.md`
- Цепочка эпика 52: adr-0019 (52b), adr-0020 (52c), adr-0021 (52d), adr-0022 (52e).
- Сверено по коду: `src/agents/launcher.py` (`ensure_worktree`, `_resolve_timeout`),
`src/queue_worker.py` (backoff/breaker), `src/qg/checks.py:82,381` (`check_ci_green`/
`check_tests_local` DEPRECATED), `src/plane_sync.py:451,541` (`find_issue_id`/
`fetch_issue_sequence_id`), `README.md:236241`, `.openclaw/agents/reviewer.md`,
`tests/test_agent_prompts_canon.py`.
</content>
</invoke>

View File

@@ -0,0 +1,38 @@
---
work_item: ORCH-079
stage: architecture
author_agent: architect
status: proposed
created_at: 2026-06-09
model_used: claude-opus-4-8
---
# 10 — Технические риски: ORCH-079 — ORCH-52f: синхронизация README + reviewer-ось обзорных доков
Work Item: **ORCH-079** · Repo: **orchestrator** · Стадия: architecture
> Информационный (гейтом не парсится). Перечисляет риски реализации и их митигейшн.
> Задача — **docs + prompt-only**; рантайм-код не изменяется → класс рисков узкий.
## Реестр рисков
| ID | Риск | Вер. | Влия. | Митигейшн |
|----|------|------|-------|-----------|
| TR-1 | **Ложное «решено».** Пункт объявлен закрытым, но открыт частично (особенно issue-ID `plane_sync`, Playwright-timeout) → витрина снова лжёт, обратный знак | Низ. | Сред. | NFR-3: каждый снятый пункт подтверждён ссылкой на код/задачу (D1-таблица ADR-001); спорные (issue-ID/timeout) переформулированы как «не tracked / устаревшая формулировка», не «закрыто тикетом»; reviewer сверяет по AC-3 |
| TR-2 | **Дрейф канона 52d** при правке `reviewer.md` (сломаны 5 XML-секций / формат «❌→✅» / порядок) | Низ. | Выс. | Точечная врезка в существующую ось 4 (NFR-4), без переписывания; структурные тесты `test_agent_prompts_canon.py` (`test_five_xml_sections_present`, `test_six_schema_field_names_present`) ловят слом |
| TR-3 | **Касание machine-verdict контракта.** Случайно изменён `verdict:`/значения `APPROVED\|REQUEST_CHANGES` или 6 полей схемы 52c → гейт `check_reviewer_verdict` ложно падает на ВСЕХ задачах | Низ. | Выс. | NFR-2: ключ байт-в-байт; `test_machine_verdict_keys_preserved_exact_case` зелёный; reviewer проверяет diff `reviewer.md` по AC-6 |
| TR-4 | **Scope-creep.** Майнинг кодовой базы порождает «новые» открытые ограничения → раздувание, недоказуемые пункты | Сред. | Низ. | D4 ADR-001: «открытые» берутся ТОЛЬКО из уже задокументированных known-limitations; триаж ограничен 6 исходными пунктами; честность > длина |
| TR-5 | **Незамеченное касание `src/**`.** Правка/перенос вышли за docs+prompt+test → функциональная регрессия | Низ. | Выс. | NFR-1: `git diff` не содержит `src/**` (AC-6); полный `pytest tests/ -q` зелёный; reviewer гейтит diff |
| TR-6 | **Неполная сверка обзорных доков** с кодом: расхождение в таблице стадий/`QG_CHECKS`/моделей осталось непоправленным | Сред. | Низ. | FR-3/FR-4 чек-лист (D3 ADR-001) со ссылками на `STAGE_TRANSITIONS`/`QG_CHECKS`/`resolve_agent_*`; tester сверяет по AC-4 |
| TR-7 | **Stale-промпт до следующего worktree.** Reviewer текущей задачи исполняется под СТАРЫМ промптом (промпт `cat`-ается на старте worktree) | Низ. | Низ. | Ожидаемо by design (loading-model NFR-5): правило вступает в силу со следующего worktree от `main`; прод-рестарт НЕ требуется и НЕ выполняется (self-hosting) |
## Сводный вывод
Доминирующий класс — **риск целостности контракта ревью-гейта** (TR-2/TR-3): низкая вероятность, но
высокое влияние, т.к. `reviewer.md` исполняется на каждой задаче всех проектов. Полностью покрыт
структурными тестами `test_agent_prompts_canon.py` + `test_agent_frontmatter_no_model.py` (анти-дрейф)
и точечностью правки (NFR-2/NFR-4). Рантайм-рисков нет — `src/`/`STAGE_TRANSITIONS`/`QG_CHECKS`/схема
БД не трогаются, kill-switch не требуется, откат = revert PR. **Эскалация `arch:major-change` не
требуется; возврат в анализ не требуется.** Остаточный риск для прод-конвейера (self-hosting) —
**низкий**.
</content>