Merge pull request 'ORCH-079 — ORCH-52f: синхронизация README/доков с кодом + reviewer-ось обзорных доков' (#96) from feature/ORCH-079-orch-52f-readme-reviewer into main
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit was merged in pull request #96.
This commit is contained in:
@@ -48,6 +48,11 @@ tools:
|
||||
`docs/architecture/README.md` и/или `docs/architecture/internals.md`? конфигурация → `README.md`
|
||||
(таблица env)? новый компонент → `docs/architecture/README.md`? обновлён `CHANGELOG.md`?
|
||||
архитектурное решение → есть ADR?
|
||||
- **Обзорные доки (ORCH-079):** если PR закрывает/меняет пункт из `README.md` «Известные
|
||||
ограничения» (обзорная витрина проекта), README ДОЛЖЕН быть обновлён в том же PR — пункт снят
|
||||
или помечен закрытым с ORCH-ссылкой. Необновление обзорных доков → **finding ≥ P1**; если
|
||||
ограничение закрыто правкой `src/` без обновления README — это совпадает с P0 «`src/` изменён,
|
||||
документация не обновлена». Это усиление трактовки оси, а не отдельная ось.
|
||||
</task>
|
||||
|
||||
<deliverables>
|
||||
@@ -65,6 +70,9 @@ frontmatter-вердиктом, см. `<output_format>`).
|
||||
- ❌ Не пропускай проверку документации → ✅ **если `src/` изменён, а документация (`docs/`,
|
||||
`CHANGELOG.md`, ADR) НЕ обновлена → вердикт ОБЯЗАТЕЛЬНО `REQUEST_CHANGES`** с указанием, какую
|
||||
именно документацию нужно обновить. Документация = golden source наравне с кодом.
|
||||
- ❌ PR закрыл пункт из `README.md` «Известные ограничения», но README не обновлён (пункт остался
|
||||
открытым) → ✅ требуй обновления обзорных доков — пункт снят либо помечен закрытым с ORCH-ссылкой;
|
||||
необновление обзорной витрины → **finding ≥ P1** (ORCH-079).
|
||||
|
||||
**Severity:**
|
||||
- **P0 (blocker):** не реализовано требование ТЗ; нарушен ADR; критическая уязвимость;
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
Формат: [Keep a Changelog](https://keepachangelog.com/). Записи — на смысловой PR/задачу.
|
||||
|
||||
## [Unreleased]
|
||||
- **Синхронизация обзорных доков (README) с кодом + reviewer-ось «обзорные доки»** (ORCH-079 / ORCH-52f, `docs`): слой 5 (финал) эпика ORCH-52, замыкающий цепочку 52b (структура) / 52c (frontmatter) / 52d (промпты) / 52e (трассировка). Корневой `README.md` — обзорная витрина проекта — **выдавал решённое за открытое**: секция «Известные ограничения» имела битую нумерацию (`1,2,3,4,3,4`) и пункты, опровергнутые кодом. **Docs + prompt-only:** `src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`/`_parse_*`, `src/frontmatter.py`, схема БД — **не тронуты**; `frontmatter_validation_strict` остаётся `False`; новый QG не вводится; правило обзорных доков нормативно-описательное (не машинный гейт), как ось трассировки ORCH-078.
|
||||
- **`README.md` приведён в честное состояние по коду (FR-1/FR-2/FR-3, AC-1/AC-2/AC-3):** перенумерация «Известные ограничения» сквозная без повторов; 6 решённых/устаревших пунктов перенесены в трейл **«Закрыто (история)»** с ORCH-ссылками (worktree → `ensure_worktree`+ORCH-026/088; in-process daemon → очередь ORCH-1; «Gitea CI не настроен» → `check_ci_green`; «no retry» → backoff/breaker `queue_worker.py`+ORCH-045; issue-ID → зрелый `plane_sync` ORCH-010/066/068; Playwright-timeout → watchdog ORCH-7); в «открытых» — только реально открытые, верифицированные кодом/задачей (Telegram-48h ORCH-087, task-deps intra-repo v1 ORCH-026, serial-gate Этап 1 ORCH-088). Точечная сверка с кодом: стадия `development` в таблице — `check_ci_green` (был устаревший `check_tests_local`); строка event-routing `status` — авторитетный гейт развития `check_ci_green` (ORCH-045), убран legacy-текст «больше не authoritative».
|
||||
- **Reviewer-ось «обзорные доки» (FR-5, AC-5):** `.openclaw/agents/reviewer.md` ось 4 «Документация» (`<task>`) + `<constraints>` несут точечную врезку «❌→✅» (канон 52d): *PR закрыл пункт README «Известные ограничения», README не обновлён → finding ≥P1*; при закрытии правкой `src/` без обновления README — совпадает с существующим P0. Машинный ключ `verdict: APPROVED|REQUEST_CHANGES` — байт-в-байт; 5 XML-секций и 6 полей схемы 52c сохранены. Правило в одном промпте (без выноса в `docs/_standards/`, в отличие от 52e).
|
||||
- **Эпик ORCH-52 закрыт:** 52b (adr-0019) → 52c (adr-0020) → 52d (adr-0021) → 52e (adr-0022) → **52f (adr-0023)**. Сквозной `docs/architecture/adr/adr-0023-overview-docs-reviewer-axis-and-epic52-close.md` + per-work-item `docs/work-items/ORCH-079/06-adr/ADR-001-readme-sync-and-reviewer-overview-docs-axis.md`.
|
||||
- **Анти-регресс (FR-6, AC-6):** новый структурный `tests/test_readme_limitations.py` (нумерация без повторов; решённые пункты не значатся открытыми; трейл «Закрыто» с ORCH-ссылками); расширен `tests/test_agent_prompts_canon.py` (assert наличия оси обзорных доков в `reviewer.md`); канон 52d (5 секций, 6 полей, регистр verdict-ключей) и `test_agent_frontmatter_no_model.py` зелёные; полный регресс `tests/` зелёный (1257). Документация: `README.md`, `docs/architecture/README.md` (слой 5 эпика 52), `CLAUDE.md`. Полностью обратимо `git revert` (нет машинного поведения/состояния/kill-switch).
|
||||
- **Стандарт маркеров-трассировки `ORCH-NNN` + правило чтения ADR перед правкой** (ORCH-078 / ORCH-52e, `docs`): слой 4 (трассировка) эпика ORCH-52, замыкающий цепочку 52b (структура) / 52c (frontmatter) / 52d (промпты). Маркеры `ORCH-NNN`/`ET-NNN` в коде (де-факто 51 уникальный в `src/`) привязывают нетривиальные инварианты к породившему их work item — была сложившаяся практика без формального контракта. **Docs + prompts-only:** `src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`/`_parse_*`, `src/frontmatter.py`, схема БД — **не тронуты**; `frontmatter_validation_strict` остаётся `False`; новый QG не вводится; массовый ретро-фит 51 маркера вне объёма (стандарт нормативен «на будущее»).
|
||||
- **Новый стандарт `docs/_standards/TRACEABILITY.md`** (рядом с `PIPELINE_DOCS.md`/`HANDOFF_PROTOCOL.md`): формат маркера, правило размещения (рядом с нетривиальным инвариантом), чтение истории с реальным проверяемым примером (`src/serial_gate.py` → ORCH-088 → `ADR-001-serial-gate.md`), fallback-доступ (`git show origin/main:docs/work-items/...`), анти-археология (3+ маркеров → сводный сквозной ADR), каноничный текст правила чтения (единый источник).
|
||||
- **Точечные врезки в промпты (аддитивно, 52d-канон не переписан):** `developer.md` — правило чтения чужого маркера + fallback («❌ X → ✅ Y»); `architect.md` — правило чтения + анти-археология (3+ → сквозной ADR); `reviewer.md` — усиление оси «Соответствие ADR» под-пунктом «правка маркированного кода сверена с ADR; слом → finding ≥P1». Все три **ссылаются** на единый текст в `TRACEABILITY.md`, не копируют (анти-дубль BR-6).
|
||||
|
||||
@@ -130,7 +130,7 @@ created → analysis → architecture → development → review → testing →
|
||||
3. Никогда не править артефакты других этапов.
|
||||
4. Никогда не комментировать ТЗ задним числом — если ТЗ не годится, возвращай в Анализ.
|
||||
5. Никогда не закрывать задачу самостоятельно — это делает CI / финальная стадия.
|
||||
6. **Reviewer проверяет: обновлена ли документация. Нет → REQUEST_CHANGES.**
|
||||
6. **Reviewer проверяет: обновлена ли документация. Нет → REQUEST_CHANGES.** Это включает **обзорные доки** (ORCH-079, 52f — финал эпика 52): если PR закрывает пункт `README.md` «Известные ограничения», но README не обновлён → finding ≥P1 (витрина проекта не должна выдавать решённое за открытое).
|
||||
7. Не использовать `--no-verify` без явного одобрения Owner.
|
||||
8. Секреты — только в `.env`/`.env.staging` на хосте, в гит НЕ коммитятся (канон — `.env.example`).
|
||||
9. **Трассировка маркеров (ORCH-078, ORCH-52e):** правишь строку/блок с маркером `ORCH-NNN` →
|
||||
|
||||
26
README.md
26
README.md
@@ -29,7 +29,7 @@ created → analysis → architecture → development → review → testing →
|
||||
| created | — | — | Plane webhook (work_item.created) |
|
||||
| analysis | analyst | Файлы BRD/TRZ/AC/TestPlan | Push docs/ |
|
||||
| architecture | architect | ADR или infra-requirements | Push docs/ |
|
||||
| development | developer | check_tests_local (орк сам гоняет `make test`) | Auto-advance после developer |
|
||||
| development | developer | check_ci_green (Gitea CI зелёный на ветке) | Auto-advance после developer |
|
||||
| review | reviewer | check_reviewer_verdict (`verdict:` во frontmatter 12-review.md) | Auto-advance после reviewer |
|
||||
| testing | tester | check_tests_passed (test-report.md) | Auto-advance после tester |
|
||||
| deploy-staging | deployer | check_staging_status (15-staging-log.md) | Auto-advance после tester |
|
||||
@@ -223,7 +223,7 @@ stdout/stderr агента перенаправляются СРАЗУ в `/app/
|
||||
Gitea events роутятся по типу:
|
||||
- `push` → проверка файлов, advance architecture/development
|
||||
- `pull_request*` (wildcard) → review approved/rejected, PR merge
|
||||
- `status` → (legacy) Gitea CI; С-1: больше не authoritative, `failure` логируется на debug и не блокирует/не алертит (QG развития = локальный `check_tests_local`)
|
||||
- `status` → Gitea CI статус; ORCH-045: авторитетный гейт развития (`development → review`) — `check_ci_green` читает статус ветки с polling-retry (устраняет гонку «pending сразу после push»)
|
||||
|
||||
## Тесты
|
||||
|
||||
@@ -233,9 +233,19 @@ pytest tests/ -v
|
||||
|
||||
## Известные ограничения
|
||||
|
||||
1. **Single-task / shared `/repos` checkout** — одновременно безопасно обрабатывается одна задача: все агенты и `check_tests_local` делают `git checkout` в одном `/repos/<repo>` → гонки при параллельных задачах. Исправление — git worktree per task (S-4, отдельно).
|
||||
2. **Plane sync** — маппинг issue ID может быть некорректным (P3, в работе)
|
||||
3. **In-process daemon-потоки** — агенты живут в потоках uvicorn; при рестарте ловит orphan-recovery. Целевое — очередь задач (F-2b)
|
||||
4. **Gitea CI не настроен** — тесты гоняет сам оркестратор локально
|
||||
3. **Tester timeout** — e2e тесты с Playwright могут занимать >25 мин на тяжёлых фичах
|
||||
4. **No retry on API errors** — httpx вызовы к Gitea/Plane без retry logic
|
||||
Реально открытые ограничения (сверено с кодом, ORCH-079):
|
||||
|
||||
1. **Telegram 48h** — карточки-сироты старше 48 часов неудаляемы (лимит Telegram Bot API); зачистка сирот самозалечивает только свежие (ORCH-087).
|
||||
2. **Зависимости задач — только intra-repo (v1)** — `job_deps` выражают связи в пределах одного репозитория; кросс-репо зависимости пока не поддержаны (ORCH-026).
|
||||
3. **Пакетный автоном — Этап 1** — per-repo serial gate сериализует задачи одного репо (ORCH-088); полный пакетный автономный прогон «10–20 задач за ночь» — в развитии (эпик ORCH-088).
|
||||
|
||||
### Закрыто (история)
|
||||
|
||||
Пункты, ранее значившиеся ограничениями, закрыты кодом — оставлены как трассировка:
|
||||
|
||||
- **Single-task / shared `/repos` checkout** → git worktree per task (`ensure_worktree`) + serial-gate (ORCH-088) + task-deps (ORCH-026).
|
||||
- **In-process daemon-потоки** → персистентная очередь задач (SQLite `jobs`, `src/queue_worker.py`), restart-safe (ORCH-1).
|
||||
- **Gitea CI не настроен** → активный гейт стадии `development` — `check_ci_green` (`src/qg/checks.py`); `check_tests_local` помечен DEPRECATED.
|
||||
- **No retry on API errors** → exp-backoff + circuit breaker в `queue_worker.py` (`ORCH_BACKOFF_*` / `ORCH_BREAKER_*` / `ORCH_TRANSIENT_MAX_ATTEMPTS`) + retry-loop в `check_ci_green` (ORCH-1 resilience / ORCH-045).
|
||||
- **Plane sync — маппинг issue ID** → зрелый `src/plane_sync.py` (`find_issue_id`, `fetch_issue_sequence_id`) со статус-моделью и TTL-самозалечиванием (ORCH-010 / 066 / 068).
|
||||
- **Tester timeout — Playwright e2e** → orchestrator является pytest-сервисом (Playwright неприменим); реальный механизм — конфигурируемый watchdog (`agent_timeout_seconds`, ORCH-7).
|
||||
|
||||
@@ -103,6 +103,31 @@ enforcement не включается).
|
||||
- ADR: [adr-0022](adr/adr-0022-traceability-marker-standard.md); детально —
|
||||
`docs/work-items/ORCH-078/06-adr/ADR-001-traceability-marker-standard.md`.
|
||||
|
||||
#### Слой обзорных доков: reviewer-ось README-ограничений + закрытие эпика 52 (ORCH-079, 52f — слой 5/финал)
|
||||
**Слой 5 (финал).** 52b–52e привели в порядок структуру доков, машинный frontmatter, канон промптов
|
||||
и трассировку, но **корневой `README.md`** — обзорная витрина проекта — остался незакрытым и **выдавал
|
||||
решённое за открытое**: секция «Известные ограничения» имела битую нумерацию (`1,2,3,4,3,4`) и пункты,
|
||||
опровергнутые кодом (worktree-гонки → `ensure_worktree`+ORCH-026/088; in-process daemon → очередь
|
||||
ORCH-1; «Gitea CI не настроен» → `check_ci_green`; «no retry» → backoff/breaker `queue_worker.py`;
|
||||
устаревшие issue-ID → зрелый `plane_sync` ORCH-010/066/068; Playwright-timeout → watchdog ORCH-7).
|
||||
ORCH-079 синхронизирует витрину с кодом и закрывает **процессный пробел**: reviewer не контролировал
|
||||
обновление обзорных доков. Это **docs + prompt-only** изменение: `src/**`, `STAGE_TRANSITIONS`,
|
||||
`QG_CHECKS`, схема БД — **не трогаются**.
|
||||
- **Reviewer-ось «обзорные доки»:** `.openclaw/agents/reviewer.md` ось 4 «Документация» + `<constraints>`
|
||||
несут врезку «❌→✅»: *PR закрыл пункт README «Известные ограничения», README не обновлён → finding*
|
||||
(≥P1; при закрытии правкой `src/` без обновления README — совпадает с существующим P0). Канон 52d
|
||||
(5 секций) и `verdict: APPROVED|REQUEST_CHANGES` — байт-в-байт; правило нормативно-описательное (не
|
||||
машинный гейт), как ось трассировки ORCH-078.
|
||||
- **Витрина по коду (NFR-3):** решённые пункты сняты/перенесены в «Закрыто (история)» с ORCH-ссылками;
|
||||
в «открытых» — только реально открытые, верифицированные кодом/задачей; запрет изобретать
|
||||
ограничения (анти-scope-creep).
|
||||
- **Эпик ORCH-52 закрыт:** 52b (adr-0019) → 52c (adr-0020) → 52d (adr-0021) → 52e (adr-0022) →
|
||||
**52f (adr-0023)**.
|
||||
- **Анти-регресс:** `tests/test_agent_prompts_canon.py` (assert наличия оси обзорных доков); канон 52d
|
||||
и `test_agent_frontmatter_no_model.py` зелёные.
|
||||
- ADR: [adr-0023](adr/adr-0023-overview-docs-reviewer-axis-and-epic52-close.md); детально —
|
||||
`docs/work-items/ORCH-079/06-adr/ADR-001-readme-sync-and-reviewer-overview-docs-axis.md`.
|
||||
|
||||
### Модель и эффорт по ролям (ORCH-41, валидация ORCH-74)
|
||||
Модель и `--effort` каждого агента берутся из config (`src/config.py`), резолвятся `launcher.resolve_agent_model` / `resolve_agent_effort` по приоритету **project-override (`projects_json` `agent_models`/`agent_efforts`) > `ORCH_AGENT_MODEL_<AGENT>`/`ORCH_AGENT_EFFORT_<AGENT>` > `*_default` > CLI-дефолт (без флага)**. **Эффорт (ORCH-081):** ниже `*_default` добавлен непустой **per-role floor** — class-default поля `agent_effort_<role>` из `config.py` (его пустой env перебить не может). Floor — строго последний уровень (ниже default) и срабатывает ТОЛЬКО когда все уровни пусты, поэтому пустые прод-`ORCH_AGENT_EFFORT_*=` (которые pydantic трактует как явное `''` и обнуляют дефолт) больше не приводят к запуску без `--effort`: каждая роль получает свой канонический пол (developer=`xhigh`, tester/deployer=`medium`, прочие=`high`). Непустой явный конфиг по-прежнему побеждает floor; опечатка вне `VALID_EFFORTS` дропается валидацией ДО floor (never-break, не маскируется). См. `docs/work-items/ORCH-081/06-adr/ADR-001-effort-resolution-floor.md`. frontmatter `model:` в `.openclaw/agents/*.md` **удалён** (ORCH-74 G1) — он был мёртвой/лживой декларацией (launcher его не читает); config — единственный источник правды о модели. Model-routing (G3) НЕ включён — все 6 агентов на `claude-opus-4-8`.
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
work_item: ORCH-079
|
||||
stage: architecture
|
||||
author_agent: architect
|
||||
status: proposed
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# adr-0023: Reviewer-ось «обзорные доки» (README-ограничения) + закрытие эпика ORCH-52
|
||||
|
||||
- **Статус:** proposed
|
||||
- **Дата:** 2026-06-09
|
||||
- **Источник:** ORCH-079 (эпик ORCH-52, слой 52f — обзорные доки, слой 5/финал)
|
||||
- **Связи:** замыкает цепочку стандартов эпика 52 — adr-0019 (52b, `PIPELINE_DOCS.md`),
|
||||
adr-0020 (52c, frontmatter-контракт), adr-0021 (52d, канон промптов), adr-0022 (52e,
|
||||
трассировка маркеров). Детально — `docs/work-items/ORCH-079/06-adr/ADR-001-readme-sync-and-reviewer-overview-docs-axis.md`.
|
||||
|
||||
## Контекст
|
||||
|
||||
Эпик ORCH-52 строит сквозной контракт «документация = golden source наравне с кодом» слоями:
|
||||
**52b** (adr-0019) — описательный стандарт документов + скелеты; **52c** (adr-0020) — машинный
|
||||
frontmatter-контракт + `HANDOFF_PROTOCOL.md`; **52d** (adr-0021) — 6 промптов в каноне Anthropic +
|
||||
добровольная эмиссия 52c-схемы; **52e** (adr-0022) — стандарт трассировки маркеров + reviewer-ось
|
||||
«соответствие ADR». Закрыты слои структуры, машинного вердикта, формы промптов и трассировки кода —
|
||||
но **обзорная витрина проекта (корневой `README.md`) не охвачена**.
|
||||
|
||||
Факты, сверенные с кодом `main`:
|
||||
- Секция `README.md` «Известные ограничения» (`:236–241`) имеет битую нумерацию (`1,2,3,4,3,4`) и
|
||||
**выдаёт решённое за открытое**: worktree-гонки (закрыто `ensure_worktree` + ORCH-026/088),
|
||||
in-process daemon (закрыто очередью ORCH-1), «Gitea CI не настроен» (опровергнуто `check_ci_green`,
|
||||
`src/qg/checks.py:82`), «no retry» (опровергнуто backoff/breaker в `queue_worker.py`), плюс
|
||||
устаревшие issue-ID (зрелый `plane_sync` ORCH-010/066/068) и Playwright-timeout (неприменим к
|
||||
pytest-сервису; реальный механизм — watchdog ORCH-7).
|
||||
- **Процессный пробел:** reviewer (ось «Документация») проверяет обновление *конвейерных* доков, но
|
||||
**обзорные** разделы (README «Известные ограничения») в правиле не названы → витрина копит
|
||||
рассинхрон, т.к. закрытие ограничения не обязывает автора снять пункт.
|
||||
|
||||
## Решение
|
||||
|
||||
Закрыть слой 5 (финал) эпика 52: **синхронизировать обзорные доки с кодом по факту** и добавить
|
||||
reviewer'у **нормативную под-ось «обзорные доки»** (по образцу оси трассировки 52e). Это **docs +
|
||||
prompt-only**, нулевое касание кода; правило — описательно-нормативное, **не машинный гейт**.
|
||||
|
||||
1. **Reviewer-ось «обзорные доки» (cross-cutting).** В `.openclaw/agents/reviewer.md` ось 4
|
||||
«Документация» + `<constraints>` несут точечную врезку «❌→✅»: *PR закрыл пункт README «Известные
|
||||
ограничения», README не обновлён → finding*. Severity **≥ P1**; при закрытии ограничения правкой
|
||||
`src/` без обновления README — совпадает с существующим **P0** «`src/` изменён, доки не обновлены».
|
||||
Канон 52d (5 секций, формат запретов, `<thinking>`), 6 полей схемы 52c и ключ
|
||||
`verdict: APPROVED|REQUEST_CHANGES` — байт-в-байт.
|
||||
2. **Витрина приведена к коду (NFR-3).** Все 6 устаревших пунктов сняты/перенесены в «Закрыто
|
||||
(история)» с ORCH-ссылками; в «открытых» остаются ТОЛЬКО реально открытые, верифицированные
|
||||
кодом/задачей; нумерация сквозная. Запрет на изобретение ограничений (только уже
|
||||
задокументированные known-limitations — анти-scope-creep).
|
||||
3. **Точечная сверка** `README.md` / `docs/architecture/README.md` с `src/` (стадии/`QG_CHECKS`/
|
||||
модели-эффорты/компоненты), минимально инвазивно.
|
||||
4. **Анти-регресс машинно:** расширение `tests/test_agent_prompts_canon.py` (tests-only) — assert
|
||||
присутствия оси обзорных доков; проверки 52d и `test_agent_frontmatter_no_model.py` зелёные.
|
||||
|
||||
**Границы:** `src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`, `_parse_*`, `src/frontmatter.py`,
|
||||
схема БД — **не трогаются**. `frontmatter_validation_strict` остаётся `False`; новый QG не вводится.
|
||||
|
||||
### Эпик ORCH-52 — закрыт (карта слоёв)
|
||||
|
||||
| Слой | Задача | Глобальный ADR | Артефакт |
|
||||
|------|--------|----------------|----------|
|
||||
| 52b — структура доков | ORCH-075 | adr-0019 | `docs/_standards/PIPELINE_DOCS.md` + `_templates/` |
|
||||
| 52c — машинный frontmatter | ORCH-076 | adr-0020 | `src/frontmatter.py` + `HANDOFF_PROTOCOL.md` |
|
||||
| 52d — канон промптов | ORCH-077 | adr-0021 | 6 промптов `.openclaw/agents/*.md` |
|
||||
| 52e — трассировка маркеров | ORCH-078 | adr-0022 | `docs/_standards/TRACEABILITY.md` |
|
||||
| **52f — обзорные доки** (финал) | **ORCH-079** | **adr-0023** | `README.md` + reviewer-ось |
|
||||
|
||||
## Альтернативы
|
||||
- **Машинный enforcement (новый QG «README актуален»).** Отвергнуто: вне scope; для self-hosting
|
||||
ложный fail валит конвейер всех проектов; правило остаётся нормативным, как 52e. Enforcement —
|
||||
возможная будущая задача (как hard-fail схемы 52c).
|
||||
- **Отдельный `docs/_standards/` для правила обзорных доков.** Отвергнуто: одно правило, один
|
||||
артефакт (README) — врезки в промпт достаточно; новый стандарт-файл избыточен.
|
||||
- **Только per-work-item ADR.** Отвергнуто: рвёт цепочку эпика 52 (52b–e имеют глобальный ADR); нет
|
||||
явной точки «эпик 52 закрыт».
|
||||
|
||||
## Последствия
|
||||
- **+** Витрина проекта честна; самоподдерживающаяся синхронность (reviewer-ось).
|
||||
- **+** Эпик 52 формально закрыт сквозным ADR — единая точка входа для будущих агентов.
|
||||
- **+** Self-hosting без рестарта: промпт `cat`-ается из worktree → правило с следующего worktree
|
||||
от `main` без рестарта 8500.
|
||||
- **+** Полная обратимость: чисто текстовое изменение, нет миграций/состояния/kill-switch.
|
||||
- **−** Правило нормативно, не enforced машинно → дисциплина + ревью (осознанный компромисс).
|
||||
- **−** Рост `reviewer.md` на короткую врезку (митигейшн: точечность, без переписывания).
|
||||
- **Откат:** `git revert` PR — доки/промпт/тест откатываются, поведение кода/гейтов идентично.
|
||||
|
||||
## Связи
|
||||
- Замыкает: adr-0019 (52b), adr-0020 (52c), adr-0021 (52d), adr-0022 (52e).
|
||||
- Per-work-item: `docs/work-items/ORCH-079/06-adr/ADR-001-readme-sync-and-reviewer-overview-docs-axis.md`.
|
||||
- Сверено по коду: `src/agents/launcher.py` (`ensure_worktree`, `_resolve_timeout`),
|
||||
`src/queue_worker.py` (backoff/breaker), `src/qg/checks.py:82,381`, `src/plane_sync.py:451,541`,
|
||||
`README.md:236–241`, `.openclaw/agents/reviewer.md`, `tests/test_agent_prompts_canon.py`.
|
||||
</content>
|
||||
7
docs/work-items/ORCH-079/00-business-request.md
Normal file
7
docs/work-items/ORCH-079/00-business-request.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Business Request: ORCH-52f: синхронизация README/доков с кодом + reviewer-гейт обзорных доков
|
||||
|
||||
Work Item ID: ORCH-079
|
||||
|
||||
## Description
|
||||
|
||||
TBD
|
||||
140
docs/work-items/ORCH-079/01-brd.md
Normal file
140
docs/work-items/ORCH-079/01-brd.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
work_item: ORCH-079
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 01 — BRD (бизнес-требования): ORCH-079 — ORCH-52f: синхронизация README/доков с кодом + reviewer-гейт обзорных доков
|
||||
|
||||
Work Item: **ORCH-079** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
## 1. Бизнес-контекст и проблема
|
||||
|
||||
ORCH-079 — **слой 5 (финал) эпика ORCH-52** «доки = golden source наравне с кодом».
|
||||
Предыдущие слои привели в порядок *структуру* конвейерных доков (52b — `PIPELINE_DOCS.md`),
|
||||
*машинный frontmatter-контракт* (52c — `src/frontmatter.py`), *канон промптов* (52d — ORCH-077)
|
||||
и *стандарт трассировки* (52e — ORCH-078). Незакрытым остался **корневой `README.md` и
|
||||
`docs/architecture/README.md`** — обзорная документация, которую читатель воспринимает как
|
||||
«паспорт состояния проекта».
|
||||
|
||||
**Установленный факт (проверено в `main`, `README.md`, секция «Известные ограничения»,
|
||||
строки 234–242):**
|
||||
|
||||
1. **Битая нумерация** списка: `1, 2, 3, 4, 3, 4` — номера `3` и `4` повторяются дважды
|
||||
(строки 238–242). Список визуально некорректен.
|
||||
2. **Устаревшие пункты помечают РЕШЁННОЕ как открытое** — обзорный док лжёт о состоянии
|
||||
системы. Подтверждено сверкой с кодом:
|
||||
- п.1 «Single-task / shared `/repos` checkout … гонки при параллельных … исправление —
|
||||
git worktree per task (S-4, отдельно)» → **РЕШЕНО**: `src/agents/launcher.py` импортирует
|
||||
и использует `ensure_worktree` (git worktree per task), плюс serial-gate ORCH-088 и
|
||||
зависимости задач ORCH-026 — оба в проде (см. `CLAUDE.md`, `docs/architecture/README.md`).
|
||||
- п.3 «In-process daemon-потоки … целевое — очередь задач (F-2b)» → **РЕШЕНО**: персистентная
|
||||
очередь `jobs` (ORCH-1, `src/queue_worker.py`), restart-safe; описана в самом `README.md`
|
||||
(«Очередь задач (ORCH-1 / F-2b)»).
|
||||
- п.4 «Gitea CI не настроен — тесты гоняет сам оркестратор локально» → **УСТАРЕЛО**: гейт
|
||||
стадии `development` — `check_ci_green` (`src/qg/checks.py:82`, реальные обращения к Gitea
|
||||
status API с ретраями); `check_tests_local` помечен `DEPRECATED: replaced by check_ci_green`
|
||||
(`src/qg/checks.py:381`).
|
||||
- «No retry on API errors — httpx вызовы … без retry logic» → **УСТАРЕЛО**: queue-слой несёт
|
||||
exp-backoff + circuit breaker (`ORCH_BACKOFF_*`, `ORCH_TRANSIENT_MAX_ATTEMPTS`,
|
||||
`ORCH_BREAKER_*`, `src/queue_worker.py`), а `check_ci_green` содержит явный retry-loop
|
||||
(`src/qg/checks.py:128–137`).
|
||||
|
||||
Дополнительно отсутствует **процессный контроль**: когда PR решает один из пунктов «Известные
|
||||
ограничения», ничто не заставляет автора снять/обновить соответствующий пункт README — поэтому
|
||||
обзорные доки и копят рассинхрон. Reviewer сегодня обязан проверять обновление *конвейерной*
|
||||
документации (`docs/architecture/README.md`, `internals.md`, env-таблица), но **обзорные**
|
||||
разделы (README «Известные ограничения») в его правиле не названы явно.
|
||||
|
||||
Боль: читатель (Owner, новый агент, внешний наблюдатель) принимает решения по неверной картине;
|
||||
эпик 52 не может считаться закрытым, пока витрина проекта противоречит коду.
|
||||
|
||||
## 2. Объём (scope)
|
||||
|
||||
### В объёме
|
||||
- Починка нумерации и содержимого секции **«Известные ограничения»** корневого `README.md`:
|
||||
решённые пункты убрать/пометить закрытыми с явной ссылкой на ORCH-решение; оставить **только
|
||||
реально открытые** ограничения (каждое — сверено с кодом/закрытыми задачами).
|
||||
- Сверка остального содержимого `README.md` и **`docs/architecture/README.md`** с фактическим
|
||||
кодом (стадии, гейты, модели/эффорты, env, компоненты) — устранение точечного рассинхрона.
|
||||
- **Точечное** дополнение `.openclaw/agents/reviewer.md`: ось «Документация» должна явно покрывать
|
||||
**обзорные доки** (README «Известные ограничения») — если PR решает пункт из «ограничений»,
|
||||
reviewer требует обновить README (finding). XML-канон 52d сохраняется (правка точечная, не
|
||||
переписывание промпта).
|
||||
- Обновление `CLAUDE.md` (при необходимости), `CHANGELOG.md`, ADR.
|
||||
|
||||
### Вне объёма
|
||||
- ❌ Любые изменения `src/**` (`STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`, схема БД) — задача
|
||||
чисто документная + одно точечное правило в промпте reviewer.
|
||||
- ❌ Переписывание промпта reviewer целиком (52d уже зафиксировала канон) или иных 5 промптов.
|
||||
- ❌ Изменение имён/регистра/значений machine-verdict ключей (`verdict:` и др.).
|
||||
- ❌ Машинный enforcement reviewer-правила (новый QG/код-проверка) — правило остаётся
|
||||
нормативно-описательным в промпте, как и ось трассировки ORCH-078.
|
||||
- ❌ Массовая ревизия `docs/operations/**`, `internals.md` сверх обнаруженного рассинхрона
|
||||
по стадиям/гейтам/моделям.
|
||||
|
||||
## 3. Заинтересованные стороны
|
||||
- **Заказчик / приёмка:** Owner (Слава) — BRD-гейт ручной; финал эпика 52.
|
||||
- **Затрагиваются:** все агенты (читают `README.md` / `docs/architecture/README.md` как контекст);
|
||||
reviewer (новое правило обзорных доков); будущие задачи (получают честную витрину состояния).
|
||||
- **Источник истины:** код (`src/`) и закрытые ORCH-задачи — каждый снятый пункт обязан быть
|
||||
подтверждён кодом/решением, «решено» не выдумывается.
|
||||
|
||||
## 4. Бизнес-требования (BR)
|
||||
- **BR-1** — Секция «Известные ограничения» корневого `README.md` имеет **последовательную
|
||||
нумерацию** (без повторов `3`/`4`).
|
||||
- **BR-2** — Каждый решённый пункт (single-task/worktree, daemon-потоки, Gitea CI, no-retry)
|
||||
**убран или явно помечен закрытым** с указанием ORCH-решения, которым закрыт (worktree per task —
|
||||
ORCH-026/088; очередь — ORCH-1; CI — `check_ci_green`; retry/breaker — ORCH-1 resilience).
|
||||
- **BR-3** — Каждое **оставшееся** в списке ограничение **реально открыто** — подтверждено сверкой
|
||||
с кодом/задачами; неподтверждённые/неверифицируемые пункты не остаются в формулировке «открыто».
|
||||
- **BR-4** — `docs/architecture/README.md` **согласован с фактическим кодом** в части, затронутой
|
||||
задачей: таблица стадий/гейтов, реестр `QG_CHECKS`, таблица моделей/эффортов, перечень
|
||||
компонентов — без расхождений с `src/`.
|
||||
- **BR-5** — `.openclaw/agents/reviewer.md` **обязывает** проверять обновление **обзорных** доков:
|
||||
если PR решает пункт из README «Известные ограничения», отсутствие обновления README — **finding**
|
||||
(ось «Документация»). XML-канон 52d (5 секций, формат «❌→✅», `<thinking>`) сохранён.
|
||||
- **BR-6** — `CLAUDE.md` (если затронуто), `CHANGELOG.md` и ADR (per-work-item `06-adr/` +
|
||||
при необходимости сквозной) обновлены в том же PR.
|
||||
|
||||
## 5. Нефункциональные требования (NFR)
|
||||
- **NFR-1 (анти-регресс кода)** — `src/**` не изменяется; `STAGE_TRANSITIONS`, `QG_CHECKS`,
|
||||
`check_*`, схема БД — байт-в-байт; полный регресс `pytest tests/` остаётся зелёным.
|
||||
- **NFR-2 (сохранность machine-verdict контракта)** — в `reviewer.md` ключ `verdict:` и его
|
||||
значения `APPROVED|REQUEST_CHANGES` — байт-в-байт; 6-польная frontmatter-схема 52c и 5 XML-секций
|
||||
сохранены (структурные тесты `tests/test_agent_prompts_canon.py` зелёные).
|
||||
- **NFR-3 (истинность)** — ни один пункт не объявляется «решённым» без подтверждения кодом или
|
||||
закрытой ORCH-задачей; источник истины — код.
|
||||
- **NFR-4 (минимальность правки промпта)** — дополнение reviewer.md точечное (врезка в существующую
|
||||
ось «Документация»), без переписывания и без дрейфа канона.
|
||||
- **NFR-5 (loading-model совместимость)** — правка `reviewer.md` вступает в силу на следующем
|
||||
worktree от `main` без прод-рестарта (промпт `cat`-ается launcher'ом); рестарт прод-контейнера
|
||||
не требуется (self-hosting, общий прод).
|
||||
|
||||
## 6. Допущения и ограничения
|
||||
- Self-hosting: прод-контейнер общий для всех проектов; задача — docs + промпт, прод НЕ
|
||||
перезапускается ради неё (промпт подхватится со следующего worktree).
|
||||
- Источник истины о «решённости» — текущий код в `main` и закрытые задачи (ORCH-1/026/088 и пр.),
|
||||
а не память/устные договорённости.
|
||||
- Пункты с неочевидным статусом (например, «Plane sync — маппинг issue ID», «Tester timeout —
|
||||
Playwright e2e») требуют отдельной сверки: либо подтвердить, что реально открыты (оставить с
|
||||
корректной формулировкой), либо переформулировать/убрать — решение принимается по коду, а не
|
||||
переносится «как было».
|
||||
- Лейбл `autoDeploy` на задаче: орк сам деплоит после staging; BRD-гейт ручной (Слава).
|
||||
|
||||
## 7. Критерии успеха
|
||||
Нумерация в «Известные ограничения» последовательна; решённые пункты сняты/помечены закрытыми с
|
||||
ORCH-ссылкой; оставшиеся — реально открыты (сверено с кодом); `docs/architecture/README.md`
|
||||
согласован с кодом; `reviewer.md` требует обновлять обзорные доки при решении пункта; `src/` не
|
||||
тронут, verdict-ключи и XML-канон 52d сохранены, регресс зелёный; `CLAUDE.md`/`CHANGELOG`/ADR
|
||||
обновлены. Детальные PASS/FAIL — в `03-acceptance-criteria.md`.
|
||||
|
||||
## 8. Риски
|
||||
- Ложное объявление «решено» для пункта, который частично открыт (напр. Plane sync) → митигировать
|
||||
сверкой с кодом и сохранением реально открытых пунктов.
|
||||
- Дрейф канона 52d при правке `reviewer.md` → митигировать точечной врезкой и структурными тестами.
|
||||
- Случайное затрагивание verdict-ключа/схемы 52c → митигировать NFR-2 и `test_agent_prompts_canon`.
|
||||
- (Детальный разбор — `10-tech-risks.md`, заполняет архитектор.)
|
||||
128
docs/work-items/ORCH-079/02-trz.md
Normal file
128
docs/work-items/ORCH-079/02-trz.md
Normal file
@@ -0,0 +1,128 @@
|
||||
---
|
||||
work_item: ORCH-079
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 02 — ТЗ (TRZ): ORCH-079 — ORCH-52f: синхронизация README/доков с кодом + reviewer-гейт обзорных доков
|
||||
|
||||
Work Item: **ORCH-079** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
> ТЗ описывает **конкретные изменения к реализации**, выведенные из BRD и фактического кода.
|
||||
> Архитектурное обоснование/решения — задача архитектора (`06-adr/`). Это **docs + prompt-only**
|
||||
> изменение: `src/**` не трогается.
|
||||
|
||||
## 1. Сводка изменения
|
||||
|
||||
Три блока правок, все вне `src/`:
|
||||
1. **`README.md`** — починить нумерацию секции «Известные ограничения»; снять/пометить закрытыми
|
||||
решённые пункты с явной ORCH-ссылкой; оставить только реально открытые ограничения; точечно
|
||||
сверить остальной текст (стадии/гейты/env) с кодом.
|
||||
2. **`docs/architecture/README.md`** — сверить таблицу стадий/гейтов, реестр `QG_CHECKS`, таблицу
|
||||
моделей/эффортов и перечень компонентов с фактическим `src/`; устранить найденный рассинхрон.
|
||||
3. **`.openclaw/agents/reviewer.md`** — точечно расширить ось «Документация»: обзорные доки (README
|
||||
«Известные ограничения») включаются в обязательную проверку; решение пункта без обновления README
|
||||
→ finding. XML-канон 52d и `verdict:`-контракт сохраняются.
|
||||
|
||||
Плюс сопроводительные: `CLAUDE.md` (при необходимости), `CHANGELOG.md`, ADR, структурный тест.
|
||||
|
||||
## 2. Задействованные модули / пути
|
||||
|
||||
| Путь | Действие |
|
||||
|------|----------|
|
||||
| `README.md` | **изменить** — секция «Известные ограничения» (нумерация + содержимое); точечная сверка стадий/env |
|
||||
| `docs/architecture/README.md` | **изменить** — сверить стадии/гейты/`QG_CHECKS`/модели/компоненты с кодом |
|
||||
| `.openclaw/agents/reviewer.md` | **изменить** — точечная врезка про обзорные доки в ось «Документация» (`<task>` ось 4 + `<constraints>`) |
|
||||
| `CLAUDE.md` | **изменить** (при необходимости) — упоминание правила обзорных доков / финала эпика 52 |
|
||||
| `CHANGELOG.md` | **изменить** — запись в `## [Unreleased]` (merge=union по `.gitattributes`) |
|
||||
| `docs/work-items/ORCH-079/06-adr/ADR-001-*.md` | **создать** — решение «синхронизация README + reviewer-правило обзорных доков» |
|
||||
| `docs/architecture/adr/adr-00NN-*.md` | **создать** (на усмотрение архитектора) — сквозной ADR, замыкающий эпик 52 |
|
||||
| `tests/test_agent_prompts_canon.py` | **изменить** — добавить структурный assert «reviewer.md покрывает обзорные доки/README-ограничения» (анти-регресс правила) |
|
||||
| Только для чтения (сверка, НЕ менять): `src/stages.py`, `src/qg/checks.py`, `src/queue_worker.py`, `src/agents/launcher.py`, `src/config.py` | сверка истины |
|
||||
|
||||
> Точные источники истины для сверки (read-only): `src/stages.py::STAGE_TRANSITIONS`,
|
||||
> `src/qg/checks.py::QG_CHECKS` + `check_ci_green` (стр. 82) + `check_tests_local` DEPRECATED
|
||||
> (стр. 379–381), `src/queue_worker.py` (backoff/breaker), `src/agents/launcher.py` (`ensure_worktree`,
|
||||
> `resolve_agent_model`/`resolve_agent_effort`).
|
||||
|
||||
## 3. Функциональные требования
|
||||
|
||||
### FR-1 — Починка нумерации «Известные ограничения» (BR-1)
|
||||
В `README.md` секция «Известные ограничения» обязана иметь **строго последовательную** нумерацию
|
||||
`1, 2, 3, …` без повторов. Текущее состояние `1,2,3,4,3,4` (строки 236–242) исправляется как часть
|
||||
переработки содержимого (FR-2): после удаления/пометки решённых пунктов список перенумеровывается
|
||||
сквозно.
|
||||
|
||||
### FR-2 — Снятие/пометка решённых пунктов с ORCH-ссылкой (BR-2, BR-3, NFR-3)
|
||||
Для каждого пункта определить статус **по коду** и применить действие:
|
||||
|
||||
| Текущий пункт | Статус | Подтверждение в коде/задаче | Действие |
|
||||
|---------------|--------|------------------------------|----------|
|
||||
| Single-task / shared `/repos` checkout (worktree S-4) | РЕШЕНО | `launcher.py` `ensure_worktree` (worktree per task) + serial-gate ORCH-088 + deps ORCH-026 | убрать из «открытых»; при желании — строка «Закрыто: ORCH-026/088» |
|
||||
| In-process daemon-потоки (целевое — очередь F-2b) | РЕШЕНО | `src/queue_worker.py`, таблица `jobs`, restart-safe (ORCH-1) | убрать; при желании — «Закрыто: ORCH-1» |
|
||||
| Gitea CI не настроен | УСТАРЕЛО | `check_ci_green` (`qg/checks.py:82`) — активный гейт `development`; `check_tests_local` `DEPRECATED` | убрать |
|
||||
| No retry on API errors | УСТАРЕЛО | `queue_worker.py` exp-backoff + breaker (`ORCH_BACKOFF_*`/`ORCH_BREAKER_*`/`ORCH_TRANSIENT_MAX_ATTEMPTS`); retry-loop в `check_ci_green` | убрать |
|
||||
| Plane sync — маппинг issue ID (P3, в работе) | СВЕРИТЬ | `src/plane_sync.py` после ORCH-066/068 | подтвердить открытость по коду → оставить с корректной формулировкой ИЛИ снять/переформулировать |
|
||||
| Tester timeout — Playwright e2e >25 мин | СВЕРИТЬ | watchdog 30 мин (`launcher`); Playwright для orchestrator неактуален | подтвердить → оставить/переформулировать; не оставлять как «открыто» без основания |
|
||||
|
||||
**Контракт FR-2:** ни один пункт не помечается решённым без подтверждения кодом/задачей (NFR-3);
|
||||
оставшиеся в списке — только реально открытые (BR-3). Допустимы оба формата снятия: полное удаление
|
||||
ИЛИ перенос в строку «Закрыто (ORCH-NNN)» — на усмотрение исполнителя, лишь бы открытыми остались
|
||||
только открытые.
|
||||
|
||||
### FR-3 — Сверка `README.md` с кодом (точечно) (BR-4)
|
||||
Сверить и при расхождении поправить: блок «Стадии пайплайна» (таблица стадий/гейтов/триггеров),
|
||||
таблицу env-переменных (наличие описанных флагов в `src/config.py`), описание очереди. Минимально
|
||||
инвазивно — править только подтверждённые расхождения.
|
||||
|
||||
### FR-4 — Сверка `docs/architecture/README.md` с кодом (BR-4)
|
||||
Сверить с фактическим `src/`:
|
||||
- таблица «Стадия → Агент → Quality Gate → Артефакт» ↔ `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/`.
|
||||
Расхождения — устранить; совпадающее — не трогать.
|
||||
|
||||
### FR-5 — Reviewer покрывает обзорные доки (BR-5, NFR-2, NFR-4)
|
||||
В `.openclaw/agents/reviewer.md` **ось 4 «Документация»** (`<task>`) и соответствующий пункт
|
||||
`<constraints>` дополняются явным требованием: **если PR решает пункт из README «Известные
|
||||
ограничения» (обзорные доки), reviewer обязан проверить, что README обновлён; необновление →
|
||||
finding.** Severity: рекомендуется ≥ P1 (по образцу оси трассировки ORCH-078); при изменении `src/`,
|
||||
закрывающем ограничение, без обновления README — согласуется с существующим P0 «`src/` изменён,
|
||||
документация не обновлена». Формулировка — в формате «❌ X → ✅ Y» (канон 52d), точечно, без
|
||||
переписывания промпта. `verdict:`/значения, 6 полей схемы 52c, 5 XML-секций — без изменений.
|
||||
|
||||
### FR-6 — Анти-регресс правила структурным тестом (BR-5, NFR-1)
|
||||
В `tests/test_agent_prompts_canon.py` добавить assert: `reviewer.md` содержит маркер покрытия
|
||||
обзорных доков / README-ограничений (напр. подстрока «Известные ограничения» или «README»
|
||||
в контексте оси «Документация»). Тест фиксирует наличие правила (анти-дрейф), как существующие
|
||||
`test_reviewer_carries_traceability_control_axis` и `test_machine_verdict_keys_preserved_exact_case`.
|
||||
|
||||
## 4. Изменения API
|
||||
Нет. Эндпоинты (`/health`, `/status`, `/queue`, `/webhook/*`) не затрагиваются.
|
||||
|
||||
## 5. Изменения схемы БД
|
||||
Нет. Таблицы/миграции/индексы не затрагиваются.
|
||||
|
||||
## 6. Требования к новым/изменённым QG checks
|
||||
Нет. `QG_CHECKS`, `check_*`, `STAGE_TRANSITIONS`, `_parse_*` — без изменений (NFR-1). Reviewer-правило
|
||||
обзорных доков — **нормативно-описательное** в промпте (как ось трассировки ORCH-078), машинный
|
||||
enforcement не вводится.
|
||||
|
||||
## 7. Совместимость / регресс
|
||||
- **Обратная совместимость:** изменения — только Markdown-доки + один промпт + один тест; runtime-код
|
||||
не затронут → нулевая функциональная регрессия для всех проектов (enduro-trails не задет).
|
||||
- **machine-verdict контракт:** `verdict: APPROVED|REQUEST_CHANGES` в `reviewer.md` — байт-в-байт;
|
||||
6 полей схемы 52c и 5 XML-секций сохранены → гейт `check_reviewer_verdict` читает вердикт как
|
||||
прежде. Структурные тесты `test_agent_prompts_canon.py` остаются зелёными (+ новый assert FR-6).
|
||||
- **Loading-model / self-hosting:** новый `reviewer.md` подхватывается launcher'ом (`cat`
|
||||
`.openclaw/agents/reviewer.md`) на следующем worktree от `main` — **прод НЕ перезапускается**.
|
||||
- **Артефакты pipeline:** задача создаёт/обновляет `docs/work-items/ORCH-079/01..04`, `06-adr/`,
|
||||
`12-review.md`, `13-test-report.md`, `14/15-*` по ходу конвейера; обновляет `README.md`,
|
||||
`docs/architecture/README.md`, `CLAUDE.md`, `CHANGELOG.md`. Обновлять только doc-артефакты —
|
||||
чужие work item не трогать.
|
||||
- **Обратимость:** kill-switch не требуется (нет рантайм-поведения); откат = revert PR.
|
||||
109
docs/work-items/ORCH-079/03-acceptance-criteria.md
Normal file
109
docs/work-items/ORCH-079/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
work_item: ORCH-079
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 03 — Критерии приёмки (Acceptance Criteria): ORCH-079 — ORCH-52f: синхронизация README/доков с кодом + reviewer-гейт обзорных доков
|
||||
|
||||
Work Item: **ORCH-079** · Repo: **orchestrator** · Стадия: analysis
|
||||
|
||||
Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL**
|
||||
(что считается провалом). Reviewer/tester проверяет их буквально по файлам репозитория и коду.
|
||||
|
||||
---
|
||||
|
||||
## AC-1 — Последовательная нумерация «Известные ограничения»
|
||||
|
||||
**Условие:** Секция «Известные ограничения» в корневом `README.md` пронумерована сквозно без
|
||||
повторов.
|
||||
- **PASS:** номера в списке идут `1, 2, 3, …` строго по возрастанию без дубликатов; повторов `3`/`4`
|
||||
(текущее `1,2,3,4,3,4`) нет.
|
||||
- **FAIL:** есть повторяющиеся номера, пропуски или не-последовательная нумерация.
|
||||
|
||||
---
|
||||
|
||||
## AC-2 — Решённые пункты сняты/помечены закрытыми с ORCH-ссылкой
|
||||
|
||||
**Условие:** Четыре решённых/устаревших пункта (single-task/worktree, in-process daemon-потоки,
|
||||
Gitea CI, no-retry) не присутствуют как **открытые** ограничения; если упомянуты — то как
|
||||
закрытые, с указанием ORCH-решения.
|
||||
- **PASS:** ни один из этих пунктов не стоит в списке открытых ограничений; для каждого упоминания
|
||||
(если оставлено) указана закрывшая задача/механизм (worktree — ORCH-026/088; очередь — ORCH-1;
|
||||
CI — `check_ci_green`; retry/breaker — ORCH-1 resilience).
|
||||
- **FAIL:** хотя бы один из четырёх пунктов остался в формулировке «открыто/не настроено/в работе»
|
||||
без пометки закрытия и без ORCH-ссылки.
|
||||
|
||||
---
|
||||
|
||||
## AC-3 — Оставшиеся ограничения реально открыты (сверено с кодом)
|
||||
|
||||
**Условие:** Каждый пункт, оставшийся в списке открытых ограничений, подтверждён открытым по коду
|
||||
или закрытой/незакрытой задаче.
|
||||
- **PASS:** для каждого оставшегося пункта в `02-trz.md`/`12-review.md` прослеживается подтверждение
|
||||
открытости (ссылка на код/задачу); ни один открытый пункт не противоречит фактическому коду.
|
||||
- **FAIL:** в списке открытых остаётся пункт, который по коду уже решён, либо пункт без какого-либо
|
||||
подтверждения открытости.
|
||||
|
||||
---
|
||||
|
||||
## AC-4 — `docs/architecture/README.md` согласован с кодом
|
||||
|
||||
**Условие:** В части, затронутой задачей, `docs/architecture/README.md` не противоречит `src/`.
|
||||
- **PASS:** таблица стадий/гейтов соответствует `STAGE_TRANSITIONS`; реестр `QG_CHECKS`
|
||||
соответствует `src/qg/checks.py::QG_CHECKS`; таблица моделей/эффортов соответствует резолву
|
||||
(`claude-opus-4-8`; developer=`xhigh`, tester/deployer=`medium`, прочие=`high`); перечень
|
||||
компонентов соответствует модулям `src/`.
|
||||
- **FAIL:** найдено хотя бы одно фактическое расхождение в перечисленных таблицах, оставшееся
|
||||
непоправленным.
|
||||
|
||||
---
|
||||
|
||||
## AC-5 — Reviewer требует обновлять обзорные доки (README limitations)
|
||||
|
||||
**Условие:** `.openclaw/agents/reviewer.md` явно обязывает: при решении пункта из README «Известные
|
||||
ограничения» необновление README — finding.
|
||||
- **PASS:** в оси «Документация» (`<task>`) и/или `<constraints>` `reviewer.md` присутствует явное
|
||||
упоминание обзорных доков / README «Известные ограничения» с трактовкой «не обновлено → finding»;
|
||||
формулировка в каноне 52d («❌→✅»).
|
||||
- **FAIL:** правило отсутствует, упоминает только конвейерные доки, или внесено вне канона
|
||||
(сломаны 5 XML-секций / формат запретов).
|
||||
|
||||
---
|
||||
|
||||
## AC-6 — Анти-регресс: код не тронут, verdict-ключи и канон 52d сохранены, тесты зелёные
|
||||
|
||||
**Условие:** Изменения не затрагивают рантайм; контракт reviewer сохранён; регресс зелёный.
|
||||
- **PASS:** `git diff` не содержит изменений в `src/**` (особенно `STAGE_TRANSITIONS`, `QG_CHECKS`,
|
||||
`check_*`, схема БД); в `reviewer.md` ключ `verdict:` и значения `APPROVED|REQUEST_CHANGES` —
|
||||
байт-в-байт, 6 полей схемы 52c и 5 XML-секций на месте; `pytest tests/ -q` зелёный, включая
|
||||
`tests/test_agent_prompts_canon.py` и `tests/test_agent_frontmatter_no_model.py`.
|
||||
- **FAIL:** есть правка `src/**`; изменён `verdict:`/его значения; сломан XML-канон/схема 52c;
|
||||
любой тест регресса красный.
|
||||
|
||||
---
|
||||
|
||||
## AC-7 — `CLAUDE.md` / `CHANGELOG` / ADR обновлены
|
||||
|
||||
**Условие:** Сопроводительная документация обновлена в том же PR.
|
||||
- **PASS:** `CHANGELOG.md` содержит запись об ORCH-079 в `## [Unreleased]`; создан
|
||||
`docs/work-items/ORCH-079/06-adr/ADR-001-*.md`; `CLAUDE.md` обновлён, если правило/финал эпика
|
||||
его затрагивает (иначе — обоснованно не затронут).
|
||||
- **FAIL:** отсутствует запись в `CHANGELOG.md`, либо нет ADR задачи, либо `CLAUDE.md` устарел
|
||||
относительно внесённого правила.
|
||||
|
||||
---
|
||||
|
||||
## Сводная матрица AC ↔ FR/BR
|
||||
| AC | Покрывает |
|
||||
|----|-----------|
|
||||
| AC-1 | BR-1 / FR-1 |
|
||||
| AC-2 | BR-2 / FR-2 |
|
||||
| AC-3 | BR-3 / FR-2 |
|
||||
| AC-4 | BR-4 / FR-3, FR-4 |
|
||||
| AC-5 | BR-5 / FR-5 |
|
||||
| AC-6 | NFR-1, NFR-2 / FR-6 |
|
||||
| AC-7 | BR-6 |
|
||||
56
docs/work-items/ORCH-079/04-test-plan.yaml
Normal file
56
docs/work-items/ORCH-079/04-test-plan.yaml
Normal file
@@ -0,0 +1,56 @@
|
||||
work_item: ORCH-079
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
title: "ORCH-52f: синхронизация README/доков с кодом + reviewer-гейт обзорных доков"
|
||||
framework: pytest
|
||||
scope: >
|
||||
Покрывается: структурная валидность секции README «Известные ограничения» (нумерация,
|
||||
отсутствие решённых пунктов), наличие reviewer-правила про обзорные доки в каноне 52d,
|
||||
анти-регресс machine-verdict ключей и схемы 52c, согласованность docs/architecture/README.md
|
||||
с кодом по гейтам/моделям. Вне покрытия: рантайм-поведение (src/ не меняется), машинный
|
||||
enforcement reviewer-правила (его нет — правило нормативно-описательное).
|
||||
notes: >
|
||||
Это docs + prompt-only задача — основной анти-регресс структурный (Markdown/промпт), а не
|
||||
поведенческий. Новые проверки добавляются в tests/test_agent_prompts_canon.py (структурный
|
||||
анти-дрейф промптов) и при необходимости в отдельный tests/test_readme_limitations.py.
|
||||
Полный регресс pytest tests/ должен оставаться зелёным; src/ не тронут.
|
||||
|
||||
tests:
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: "reviewer.md покрывает обзорные доки: содержит явное упоминание README «Известные ограничения» / обзорных доков в оси «Документация» (анти-дрейф правила FR-5/AC-5)."
|
||||
module: tests/test_agent_prompts_canon.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: "Анти-регресс reviewer machine-verdict: ключ `verdict:` и значения APPROVED|REQUEST_CHANGES присутствуют байт-в-байт (существующий test_machine_verdict_keys_preserved_exact_case остаётся зелёным, AC-6/NFR-2)."
|
||||
module: tests/test_agent_prompts_canon.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: unit
|
||||
description: "Анти-регресс канона 52d: reviewer.md (и все 6 промптов) сохраняют 5 обязательных XML-секций и 6 полей схемы 52c (существующие test_five_xml_sections_present / test_six_schema_field_names_present зелёные, AC-6)."
|
||||
module: tests/test_agent_prompts_canon.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: unit
|
||||
description: "frontmatter agent-промптов без мёртвого `model:` остаётся валидным (test_agent_frontmatter_no_model.py зелёный после правки reviewer.md, AC-6)."
|
||||
module: tests/test_agent_frontmatter_no_model.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: unit
|
||||
description: "README «Известные ограничения»: нумерация строго последовательна без повторов (AC-1) и не содержит решённых пунктов как открытых — single-task/worktree, in-process daemon, Gitea CI, no-retry (AC-2). Реализуется как новый структурный тест README."
|
||||
module: tests/test_readme_limitations.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: integration
|
||||
description: "Полный регресс pytest tests/ зелёный; git diff не содержит изменений в src/** (STAGE_TRANSITIONS/QG_CHECKS/check_*/схема БД) — проверяется ревьюером/тестером на стадии review/testing (AC-6/NFR-1)."
|
||||
module: tests/
|
||||
expected: PASS
|
||||
@@ -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:236–241`): фактический порядок
|
||||
списка — `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` (`:128–137`) |
|
||||
|
||||
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:236–241`, `.openclaw/agents/reviewer.md`,
|
||||
`tests/test_agent_prompts_canon.py`.
|
||||
</content>
|
||||
</invoke>
|
||||
38
docs/work-items/ORCH-079/10-tech-risks.md
Normal file
38
docs/work-items/ORCH-079/10-tech-risks.md
Normal 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>
|
||||
96
docs/work-items/ORCH-079/12-review.md
Normal file
96
docs/work-items/ORCH-079/12-review.md
Normal file
@@ -0,0 +1,96 @@
|
||||
---
|
||||
verdict: APPROVED
|
||||
work_item: ORCH-079
|
||||
stage: review
|
||||
author_agent: reviewer
|
||||
status: approved
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
type: review
|
||||
work_item_id: ORCH-079
|
||||
version: 1
|
||||
---
|
||||
|
||||
# Review ORCH-079 — ORCH-52f: синхронизация README/доков с кодом + reviewer-ось обзорных доков
|
||||
|
||||
## Summary
|
||||
|
||||
PR — финальный слой (52f) эпика ORCH-52, **docs + prompt-only**. Чистый PR без правок `src/`:
|
||||
коммит реализации `131d002` трогает только `README.md`, `.openclaw/agents/reviewer.md`, `CLAUDE.md`,
|
||||
`CHANGELOG.md` и два тест-файла. (Файлы `architect.md`/`developer.md`/`docs/architecture/README.md`/
|
||||
`TRACEABILITY.md` в `git diff main...HEAD` — артефакты ORCH-078, попавшие в трёхточечный diff из-за
|
||||
merge-base раньше мержа ORCH-078; к этому PR отношения не имеют и тоже не являются `src/`.)
|
||||
|
||||
Проверены все четыре оси; каждое утверждение README сверено с фактическим кодом. Findings P0/P1/P2
|
||||
отсутствуют. **Вердикт: APPROVED.**
|
||||
|
||||
## Findings
|
||||
|
||||
### P0 — Blocker
|
||||
- (нет)
|
||||
|
||||
### P1 — Must fix
|
||||
- (нет)
|
||||
|
||||
### P2 — Should fix
|
||||
- (нет)
|
||||
|
||||
### P3 — Nice to have
|
||||
- (нет существенных)
|
||||
|
||||
## Оси проверки
|
||||
|
||||
### 1. Соответствие ТЗ / Acceptance Criteria
|
||||
- **AC-1 (нумерация):** секция «Известные ограничения» перенумерована сквозно `1,2,3` (было
|
||||
`1,2,3,4,3,4`); закреплено тестом `test_open_limitations_numbered_sequentially`. **PASS.**
|
||||
- **AC-2 (решённые сняты с ORCH-ссылкой):** все 4 решённых/устаревших пункта (single-task/worktree,
|
||||
in-process daemon-потоки, Gitea CI, no-retry) перенесены в блок «Закрыто (история)» с ORCH-ссылками;
|
||||
ни один не стоит как «открытый». Дополнительно закрыты Plane-sync и Tester-timeout с обоснованием.
|
||||
Тест `test_resolved_items_not_listed_as_open`. **PASS.**
|
||||
- **AC-3 (оставшиеся реально открыты):** три открытых пункта подтверждены кодом/задачами — Telegram-48h
|
||||
(ORCH-087, known-limitation в CLAUDE.md), intra-repo deps (ORCH-026), serial-gate Этап 1 (ORCH-088).
|
||||
**PASS.**
|
||||
- **AC-5 / FR-5 (reviewer-ось):** в `reviewer.md` добавлена ось обзорных доков (ось 4 `<task>` +
|
||||
`<constraints>`) в каноне «❌→✅» с severity ≥P1. **PASS.**
|
||||
- **AC-7 / FR-6:** ADR-001, сквозной `adr-0023`, `CHANGELOG.md`, `CLAUDE.md` (правило 6) обновлены;
|
||||
новый тест `test_reviewer_carries_overview_docs_axis`. **PASS.**
|
||||
|
||||
### 2. Соответствие ADR / трассировка
|
||||
- Заявленные изменения соответствуют `06-adr/ADR-001` и сквозному `adr-0023` (закрытие эпика 52).
|
||||
- Трассировка: правки сверены с источниками истины; маркированные инварианты конвейера
|
||||
(`STAGE_TRANSITIONS`, `QG_CHECKS`, `verdict:`-контракт) **не тронуты** — глобальные ADR не нарушены.
|
||||
- Точечная синхронизация стадийной таблицы README: `development → check_ci_green` совпадает с
|
||||
`src/stages.py::STAGE_TRANSITIONS` (`"development": {... "qg": "check_ci_green"}`). Корректно.
|
||||
|
||||
### 3. Качество кода
|
||||
- Рантайм-кода нет. Новые тесты содержательны (проверка нумерации, отсутствия решённых среди
|
||||
открытых, наличия closed-trail с ORCH-ссылками, наличия reviewer-оси) — не тривиальны. `pytest`
|
||||
по `test_readme_limitations.py` + `test_agent_prompts_canon.py` + `test_agent_frontmatter_no_model.py`
|
||||
зелёный (**57 passed**).
|
||||
- **Сверка README-утверждений с `src/` (выполнена явно):** `check_ci_green` (qg/checks.py:82) активен,
|
||||
`check_tests_local` DEPRECATED (qg/checks.py:379–381); `ensure_worktree` (launcher); очередь
|
||||
`queue_worker.py`/`jobs`; backoff+breaker (`backoff_*`/`transient_max_attempts`/`breaker_*` в
|
||||
config.py + `CircuitBreaker` в queue_worker.py; env-префикс `ORCH_` корректно даёт
|
||||
`ORCH_BACKOFF_*`/`ORCH_BREAKER_*`/`ORCH_TRANSIENT_MAX_ATTEMPTS`); `find_issue_id`/
|
||||
`fetch_issue_sequence_id` (plane_sync.py); watchdog `agent_timeout_seconds`. Все утверждения точны.
|
||||
|
||||
### 4. Документация (обязательная проверка)
|
||||
- **`src/` НЕ изменён** → P0 «код изменён, доки не обновлены» неприменим.
|
||||
- Это сам по себе docs-PR, и документация обновлена полно и согласованно.
|
||||
- **AC-4 (`docs/architecture/README.md` ↔ код):** файл этим PR не правился; проверено, что он уже НЕ
|
||||
противоречит коду в затронутых областях — стадийная таблица (стр.33 `development | check_ci_green`),
|
||||
реестр `QG_CHECKS` (стр.40, полный список совпадает с `src/qg/checks.py::QG_CHECKS`), таблица
|
||||
моделей/эффортов (стр.136–141: все `claude-opus-4-8`; developer=`xhigh`, tester/deployer=`medium`,
|
||||
прочие=`high`) — соответствует резолву. Отсутствие правки обосновано (расхождений нет). **PASS.**
|
||||
- **ORCH-079 / правило обзорных доков соблюдено самим PR:** README — обзорная витрина — приведён в
|
||||
соответствие с кодом, решённые ограничения помечены закрытыми с ORCH-ссылками. Reviewer-ось,
|
||||
закрепляющая это правило на будущее, добавлена в промпт и тест.
|
||||
|
||||
## Документация
|
||||
|
||||
Обновлено и проверено: `README.md` (нумерация + closed-trail + точечная сверка), `.openclaw/agents/
|
||||
reviewer.md` (ось обзорных доков, канон 52d, `verdict:`/5 XML-секций/6 полей схемы 52c байт-в-байт —
|
||||
подтверждено `test_agent_prompts_canon.py`), `CLAUDE.md` (правило 6), `CHANGELOG.md` (`[Unreleased]`,
|
||||
ORCH-079), `docs/work-items/ORCH-079/06-adr/ADR-001-…`, `docs/architecture/adr/adr-0023-…` (закрытие
|
||||
эпика 52). `docs/architecture/README.md` правки не требовал (уже согласован с кодом). Документация в
|
||||
полном порядке — `REQUEST_CHANGES` по оси документации не требуется.
|
||||
74
docs/work-items/ORCH-079/13-test-report.md
Normal file
74
docs/work-items/ORCH-079/13-test-report.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
result: PASS
|
||||
work_item: ORCH-079
|
||||
stage: testing
|
||||
author_agent: tester
|
||||
status: pass
|
||||
created_at: 2026-06-09
|
||||
model_used: claude-opus-4-8
|
||||
type: test-report
|
||||
work_item_id: ORCH-079
|
||||
---
|
||||
|
||||
# Test Report — ORCH-079
|
||||
|
||||
ORCH-52f: синхронизация README/доков с кодом + reviewer-ось обзорных доков (финал эпика 52).
|
||||
**docs + prompt-only**: `src/**` не тронут (подтверждено git diff). Review-вердикт — `APPROVED`.
|
||||
|
||||
## Окружение
|
||||
- Python: 3.12.13
|
||||
- pytest: 8.3.3
|
||||
- Worktree: `/repos/_wt/orchestrator/feature_ORCH-079-orch-52f-readme-reviewer`
|
||||
- Ветка: `feature/ORCH-079-orch-52f-readme-reviewer`
|
||||
- Дата: 2026-06-09
|
||||
|
||||
## Smoke API (read-only, прод 8500)
|
||||
| Endpoint | Результат |
|
||||
|----------|-----------|
|
||||
| `GET /health` | `{"status":"ok","service":"orchestrator"}` — OK |
|
||||
| `GET /status` | OK — ORCH-079 (id 72) на стадии `testing`, активная очередь читается |
|
||||
| `GET /queue` | OK — breaker `closed`, preflight_ok, `done:1019`, `failed:4` (исторические) |
|
||||
|
||||
Прод-контейнер не трогался (read-only smoke, без рестарта — self-hosting инвариант соблюдён).
|
||||
|
||||
## Результаты (покрытие ТЗ — TC из 04-test-plan.yaml)
|
||||
|
||||
| TC ID | Описание | AC | Результат |
|
||||
|-------|----------|----|-----------|
|
||||
| TC-01 | `reviewer.md` покрывает обзорные доки (README «Известные ограничения») — `test_reviewer_carries_overview_docs_axis` | AC-5/FR-5 | PASS |
|
||||
| TC-02 | Анти-регресс machine-verdict: `verdict: APPROVED\|REQUEST_CHANGES` байт-в-байт — `test_machine_verdict_keys_preserved_exact_case` | AC-6/NFR-2 | PASS |
|
||||
| TC-03 | Канон 52d: 5 XML-секций + 6 полей схемы 52c во всех 6 промптах — `test_five_xml_sections_present` / `test_six_schema_field_names_present` | AC-6 | PASS |
|
||||
| TC-04 | frontmatter без мёртвого `model:` остаётся валидным — `test_agent_frontmatter_no_model.py` (12 тестов) | AC-6 | PASS |
|
||||
| TC-05 | README «Известные ограничения»: последовательная нумерация + решённые не значатся открытыми + closed-trail с ORCH-ссылками — `test_readme_limitations.py` (3 теста) | AC-1/AC-2/AC-3 | PASS |
|
||||
| TC-06 | Полный регресс `pytest tests/` зелёный; `git diff --name-only main...HEAD -- 'src/**'` пуст (STAGE_TRANSITIONS/QG_CHECKS/check_*/схема БД не тронуты) | AC-6/NFR-1 | PASS |
|
||||
|
||||
**Примечание к TC-06:** трёхточечный `git diff main...HEAD` показывает также артефакты ORCH-078
|
||||
(`architect.md`/`developer.md`/`TRACEABILITY.md` и др.) — это следствие merge-base до мержа ORCH-078,
|
||||
к данному PR отношения не имеют и тоже не входят в `src/`. Фильтр `-- 'src/**'` пуст → рантайм-код
|
||||
не изменён.
|
||||
|
||||
## Вывод pytest
|
||||
|
||||
Целевой набор (TC-01..05):
|
||||
```
|
||||
tests/test_readme_limitations.py ......... (3)
|
||||
tests/test_agent_prompts_canon.py ........ (42)
|
||||
tests/test_agent_frontmatter_no_model.py . (12)
|
||||
57 passed, 1 warning in 0.45s
|
||||
```
|
||||
|
||||
Полный регресс (TC-06):
|
||||
```
|
||||
python -m pytest tests/ -q
|
||||
............................................................ [100%]
|
||||
1257 passed, 1 warning in 34.10s
|
||||
```
|
||||
|
||||
(Единственный warning — `PydanticDeprecatedSince20` в `src/config.py`, исторический, не связан с
|
||||
задачей и не влияет на результат.)
|
||||
|
||||
## Итог
|
||||
Все TC (TC-01…TC-06) — **PASS**; smoke `/health`, `/status`, `/queue` — OK; `src/**` не тронут;
|
||||
полный регресс `1257 passed`. Машинный вердикт:
|
||||
|
||||
**PASS**
|
||||
12
docs/work-items/ORCH-079/14-deploy-log.md
Normal file
12
docs/work-items/ORCH-079/14-deploy-log.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
deploy_status: SUCCESS
|
||||
work_item: ORCH-079
|
||||
hook_exit_code: 0
|
||||
deployed_by: deploy-finalizer
|
||||
---
|
||||
|
||||
# Deploy log — ORCH-036 executable self-deploy
|
||||
|
||||
Прод-деплой завершён хост-хуком с exit-code `0` -> `deploy_status: SUCCESS`.
|
||||
|
||||
Вердикт зафиксирован детерминированным finalizer'ом (Фаза C), не LLM.
|
||||
@@ -258,3 +258,24 @@ def test_claude_md_and_readme_reference_traceability_standard():
|
||||
assert "TRACEABILITY.md" in _read_repo("docs", "architecture", "README.md"), (
|
||||
"architecture README does not reference docs/_standards/TRACEABILITY.md"
|
||||
)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# ORCH-079 (ORCH-52f): reviewer overview-docs axis (layer 5 of epic ORCH-52).
|
||||
# Pure-text anti-drift check (TRZ §FR-6 / AC-5), NO `src/` import.
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
def test_reviewer_carries_overview_docs_axis():
|
||||
"""ORCH-079 TC-01 (AC-5): reviewer.md covers the README overview-docs axis.
|
||||
|
||||
The reviewer must require README ("Известные ограничения") to be updated when
|
||||
a PR closes a documented limitation. This guards the rule against silent drift
|
||||
in a future prompt refactor, exactly like the traceability control axis.
|
||||
"""
|
||||
text = _read("reviewer")
|
||||
assert "Известные ограничения" in text, (
|
||||
"reviewer.md does not mention the README 'Известные ограничения' overview-docs axis"
|
||||
)
|
||||
assert "ORCH-079" in text, (
|
||||
"reviewer.md does not anchor the overview-docs axis to ORCH-079"
|
||||
)
|
||||
|
||||
88
tests/test_readme_limitations.py
Normal file
88
tests/test_readme_limitations.py
Normal file
@@ -0,0 +1,88 @@
|
||||
"""ORCH-079 (ORCH-52f): structural anti-drift for README "Известные ограничения".
|
||||
|
||||
Layer 5 (final) of epic ORCH-52: the root README overview showcase must not lie
|
||||
about the project state. These are pure-text structural checks (NO `src/` import,
|
||||
NO agent runs) guarding two invariants (TRZ §FR-1/FR-2, AC-1/AC-2):
|
||||
|
||||
* the OPEN limitations list is numbered strictly 1, 2, 3, … without repeats
|
||||
(the historical bug was `1,2,3,4,3,4`);
|
||||
* resolved/obsolete items (single-task worktree, in-process daemon, "Gitea CI
|
||||
not configured", "no retry") are NOT listed as OPEN limitations — if mentioned
|
||||
at all, only under the "Закрыто (история)" trail.
|
||||
|
||||
Covers test-plan TC-05.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
|
||||
_REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
_README = os.path.join(_REPO_ROOT, "README.md")
|
||||
|
||||
# Heading of the limitations section and the closed-history subsection that ends
|
||||
# the OPEN portion.
|
||||
_SECTION_HEAD = "## Известные ограничения"
|
||||
_CLOSED_HEAD = "Закрыто (история)"
|
||||
|
||||
# Phrases that mark a RESOLVED/obsolete item. They must not appear in the OPEN
|
||||
# portion of the section (only allowed under "Закрыто (история)").
|
||||
_RESOLVED_MARKERS = (
|
||||
"Single-task",
|
||||
"shared `/repos`",
|
||||
"daemon-потоки",
|
||||
"не настроен", # "Gitea CI не настроен"
|
||||
"No retry",
|
||||
)
|
||||
|
||||
|
||||
def _read_readme() -> str:
|
||||
with open(_README, encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def _limitations_section() -> str:
|
||||
"""Text of the '## Известные ограничения' section up to the next '## ' heading."""
|
||||
text = _read_readme()
|
||||
idx = text.find(_SECTION_HEAD)
|
||||
assert idx != -1, "README.md has no '## Известные ограничения' section"
|
||||
rest = text[idx + len(_SECTION_HEAD):]
|
||||
# Stop at the next top-level (##) heading, if any.
|
||||
nxt = re.search(r"\n## ", rest)
|
||||
return rest[: nxt.start()] if nxt else rest
|
||||
|
||||
|
||||
def _open_portion(section: str) -> str:
|
||||
"""The OPEN-limitations portion: everything before the 'Закрыто (история)' trail."""
|
||||
cut = section.find(_CLOSED_HEAD)
|
||||
return section[:cut] if cut != -1 else section
|
||||
|
||||
|
||||
def test_open_limitations_numbered_sequentially():
|
||||
"""AC-1: the OPEN limitations list is numbered 1, 2, 3, … with no repeats/gaps."""
|
||||
open_part = _open_portion(_limitations_section())
|
||||
# Leading numbered list items: lines like "1. **...".
|
||||
numbers = [int(m) for m in re.findall(r"^(\d+)\.\s", open_part, flags=re.MULTILINE)]
|
||||
assert numbers, "no numbered OPEN limitations found in README section"
|
||||
assert numbers == list(range(1, len(numbers) + 1)), (
|
||||
f"OPEN limitations numbering is not strictly sequential: {numbers}"
|
||||
)
|
||||
|
||||
|
||||
def test_resolved_items_not_listed_as_open():
|
||||
"""AC-2: resolved/obsolete items are not present as OPEN limitations."""
|
||||
open_part = _open_portion(_limitations_section())
|
||||
leaked = [m for m in _RESOLVED_MARKERS if m in open_part]
|
||||
assert not leaked, (
|
||||
f"resolved items leaked into OPEN limitations (must be under 'Закрыто'): {leaked}"
|
||||
)
|
||||
|
||||
|
||||
def test_closed_history_trail_present_with_orch_refs():
|
||||
"""AC-2: the 'Закрыто (история)' trail exists and carries ORCH references."""
|
||||
section = _limitations_section()
|
||||
assert _CLOSED_HEAD in section, (
|
||||
"README limitations section lacks the 'Закрыто (история)' trail"
|
||||
)
|
||||
closed = section[section.find(_CLOSED_HEAD):]
|
||||
assert re.search(r"ORCH-\d+", closed), (
|
||||
"the 'Закрыто (история)' trail has no ORCH-NNN references"
|
||||
)
|
||||
Reference in New Issue
Block a user