diff --git a/CHANGELOG.md b/CHANGELOG.md index 18554b1..3c1ea53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Формат: [Keep a Changelog](https://keepachangelog.com/). Записи — на смысловой PR/задачу. ## [Unreleased] +- **Стандарт документов конвейера: `docs/_standards/PIPELINE_DOCS.md` + `docs/_templates/` + ADR-naming** (ORCH-075 / ORCH-52b, `docs`): зафиксирован golden source структуры номерных документов work item (`00-business-request.md` … `17-security-report.md`). **Docs-only**, нулевой рантайм-риск: `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / `src/stage_engine.py` / схема БД — **не трогаются** (изменения только под `docs/**` + `CLAUDE.md`). + - **Манифест** `docs/_standards/PIPELINE_DOCS.md` — карта «стадия → агент → документ → категория (`required`/`when-applicable`/`optional`) → гейт/механизм → frontmatter machine-key», сверенная с `src/stages.py` (`STAGE_TRANSITIONS`) и `src/qg/checks.py` (`_parse_*`). Манифест **документирует** поведение гейтов, но НЕ источник истины (источник — код, ADR-001 §D2); честно различает machine-verdict доки (`12`→`verdict:`, `13`→`result:`, `14`→`deploy_status:`, `15`→`staging_status:`, `17`→`security_status:`) и информационные (`00/08/10/16` — гейтом не парсятся). Под-гейты ребра `deploy-staging→deploy` (security/merge/image-freshness) помечены как врезки в `advance_stage`, а не строки `STAGE_TRANSITIONS`. + - **Шаблоны** `docs/_templates/*` (15 копируемых скелетов) — для каждого `required`/`when-applicable` дока; машинные доки несут точный frontmatter-ключ из ground-truth (`_parse_*`), чтобы скопированный скелет проходил гейт без угадывания. Служебные каталоги `docs/_standards/` / `docs/_templates/` лежат ВНЕ `docs/work-items//` → невидимы гейтам наличия файлов (`check_architecture_done`/`check_analysis_complete`). + - **ADR-naming** зафиксирован: `docs/work-items//06-adr/ADR-NNN-.md` (NNN с `001`); сквозные решения дублируются в `docs/architecture/adr/adr-NNNN-.md` (4-значная нумерация). Точки-ссылки: `CLAUDE.md` (раздел «Артефакты задачи» + правило 2), `docs/architecture/README.md` (раздел «Стандарт документов конвейера»). Тесты: `tests/test_orch_52b_docs_standard.py` (TC-01…TC-20, структурные проверки наличия/секций/frontmatter). ADR: `docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md`, сквозной `docs/architecture/adr/adr-0019-pipeline-docs-standard.md`. - **Авто-режим по лейблам: autoApprove (авто-BRD) + autoDeploy (авто-деплой)** (ORCH-089, `feat`): сняты **два** человеческих гейта конвейера, тормозящих пакетный автономный прогон (эпик ORCH-088) — гейт BRD (`analysis`: ручной `Approved`) и гейт прод-деплоя (`deploy` Phase A: ручной `Confirm Deploy`, ORCH-059). Решение выборочно (лейбл Plane на задаче), декларативно, обратимо и **не трогает ни одной технической проверки**. Аддитивно по образцу условных под-гейтов (ORCH-035/043/058/088): leaf `src/labels.py` (never-raise) + две точечные врезки + флаги; `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/схема БД — **без изменений**. - **`autoApprove`** → врезка в `stage_engine._handle_analysis_approved_flow` (ветка `files_ok`) ПОСЛЕ `In Review`+коммента: `set_issue_approved` (индикация) + лог/Telegram/Plane-коммент + `advance_stage(..., finished_agent=None)` — **тот же путь, что человеческий Approved** (`approved-via-status` → `analysis → architecture` + `mark_brd_review_ended`). Без дублирования переходной логики; re-entrancy безопасна (вложенный вызов идёт с `finished_agent=None`, не входит в analyst-ветку). - **`autoDeploy`** → врезка в `stage_engine._handle_self_deploy_phase_a` сразу после advance на `deploy`+`clear_state` (ДО «ask-human»): лог/Telegram/Plane-коммент + `_handle_self_deploy_phase_b(...)` (idempotency-маркер `INITIATED`, статус `Deploying`, finalizer). Пропускаются лишь индикативно-человеческие шаги (`APPROVE_REQUESTED`+`Awaiting Deploy`+«смените на Confirm Deploy»). **BR-5 структурно:** Phase A достигается только после зелёных под-гейтов ребра `deploy-staging → deploy` (security → merge-gate → image-freshness → staging) → autoDeploy физически не деплоит сломанное. diff --git a/CLAUDE.md b/CLAUDE.md index 5ab30f8..a2bca7c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -122,9 +122,11 @@ created → analysis → architecture → development → review → testing → ## Артефакты задачи (`docs/work-items//`) `00-business-request.md`, `01-brd.md`, `02-trz.md`, `03-acceptance-criteria.md`, `04-test-plan.yaml`, `06-adr/ADR-NNN-slug.md`, `07-infra-requirements.md`, `08-data-requirements.md`, `10-tech-risks.md`, `12-review.md`, `13-test-report.md`, `14-deploy-log.md`, `15-staging-log.md`, `16-post-deploy-log.md` (post-deploy наблюдение, ORCH-021), `17-security-report.md` (security-гейт: `security_status:`/secrets/deps, ORCH-022). +**Стандарт документов (ORCH-075, ORCH-52b):** структура каждого дока, карта «стадия→агент→документ→гейт→machine-key» и конвенция ADR-naming зафиксированы в `docs/_standards/PIPELINE_DOCS.md` (golden source); копируемые скелеты — в `docs/_templates/`. Перед написанием номерного дока бери скелет из `docs/_templates/` и не меняй имя machine-key frontmatter (регистр чувствителен — иначе гейт упадёт ложно). + ## Правила для агентов 1. Перед любым действием прочесть этот файл и `docs/architecture/README.md`. -2. **Документация = golden source наравне с кодом.** Изменил функционал → обнови доку В ТОМ ЖЕ PR. Архитектурное решение → заведи ADR. Обнови `CHANGELOG.md`. +2. **Документация = golden source наравне с кодом.** Изменил функционал → обнови доку В ТОМ ЖЕ PR. Архитектурное решение → заведи ADR (формат — `docs/_standards/PIPELINE_DOCS.md` §4). Структура номерных доков и шаблоны — `docs/_standards/PIPELINE_DOCS.md` + `docs/_templates/`. Обнови `CHANGELOG.md`. 3. Никогда не править артефакты других этапов. 4. Никогда не комментировать ТЗ задним числом — если ТЗ не годится, возвращай в Анализ. 5. Никогда не закрывать задачу самостоятельно — это делает CI / финальная стадия. diff --git a/docs/_standards/PIPELINE_DOCS.md b/docs/_standards/PIPELINE_DOCS.md new file mode 100644 index 0000000..a5fa33f --- /dev/null +++ b/docs/_standards/PIPELINE_DOCS.md @@ -0,0 +1,138 @@ +# PIPELINE_DOCS — стандарт документов конвейера (golden source структуры) + +> **Назначение.** Единая карта «стадия → агент → документ → категория → гейт/механизм → +> frontmatter machine-key» + конвенция ADR-naming. Это **golden source структуры** номерных +> документов work item (`00-business-request.md` … `17-security-report.md`), который каждая +> агентская роль пишет на своей стадии. +> +> **Статус истины (важно).** Манифест **документирует** текущее поведение гейтов, но НЕ является +> их источником истины. Источник истины — код: `src/stages.py` (`STAGE_TRANSITIONS`), +> `src/qg/checks.py` (`QG_CHECKS` / `check_*` / `_parse_*`), `src/stage_engine.py`. При будущей +> правке гейта первична правка кода, манифест обновляется следом (ORCH-075 / ADR-001 §D2). +> +> **Копируемые скелеты** каждого документа — в каталоге [`docs/_templates/`](../_templates/): +> «скопировал → заполнил → не угадываешь структуру/ключ». + +Введён задачей **ORCH-075** (ORCH-52b — слой 1 эпика ORCH-52). Сквозной ADR: +[`docs/architecture/adr/adr-0019-pipeline-docs-standard.md`](../architecture/adr/adr-0019-pipeline-docs-standard.md); +детально — `docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md`. + +--- + +## 1. Конвейер стадий (ground-truth `STAGE_TRANSITIONS`) + +``` +created → analysis → architecture → development → review → testing → deploy-staging → deploy → done + ↑ │ + └──── REQUEST_CHANGES ──────┘ (откат на development, max 3 retries) +``` + +Каждое ребро несёт ровно один exit-гейт (`src/stages.py`): +`check_analysis_approved → check_architecture_done → check_ci_green → check_reviewer_verdict → +check_tests_passed → check_staging_status → check_deploy_status`. + +**Под-гейты ребра `deploy-staging → deploy`** (`check_security_gate` → `check_branch_mergeable` → +`check_staging_image_fresh`) — это **врезки в `advance_stage`**, а НЕ строки `STAGE_TRANSITIONS`. +Аналогично под-гейт ребра `deploy → done` (`_handle_merge_verify`, ORCH-071/073) — врезка, не +зарегистрированный QG. Карта стадий о них не «лжёт»: они не являются стадиями. + +--- + +## 2. Манифест: документ → агент → категория → стадия → гейт → machine-key + +Категории: **required** (пишется всегда), **when-applicable** (пишется при наличии предмета: +инфра / данные / security / post-deploy — отсутствие не нарушение), **optional** / **legacy**. + +| Документ | Владелец-агент | Категория | Стадия написания | Гейт / механизм проверки | Frontmatter machine-key | +|----------|----------------|-----------|------------------|--------------------------|-------------------------| +| `00-business-request.md` | система (Plane webhook `_create_initial_docs`) / заказчик | required | `created` (инициализация) | не гейтится (вход) | — | +| `01-brd.md` | analyst | required | `analysis` | exit-гейт `analysis→architecture` = `check_analysis_approved` (Approved + полнота файлов); helper `check_analysis_complete` (наличие `01/02/03/04`) | — | +| `02-trz.md` | analyst | required | `analysis` | то же | — | +| `03-acceptance-criteria.md` | analyst | required | `analysis` | то же | — | +| `04-test-plan.yaml` | analyst | required | `analysis` | то же | — | +| `06-adr/ADR-NNN-.md` | architect | required | `architecture` | `check_architecture_done` (наличие каталога `06-adr/` ≥1 файл ИЛИ `07-infra-requirements.md`) | — | +| `07-infra-requirements.md` | architect | when-applicable | `architecture` | `check_architecture_done` (учитывается при наличии) | — | +| `08-data-requirements.md` | architect | when-applicable | `architecture` | информационный (гейтом не парсится) | — | +| `10-tech-risks.md` | architect | required | `architecture` | информационный (гейтом не парсится) | — | +| `12-review.md` | reviewer | required | `review` | `check_reviewer_verdict` | `verdict:` (`APPROVED` \| `REQUEST_CHANGES`) | +| `13-test-report.md` | tester | required | `testing` | `check_tests_passed` (`_parse_tests_verdict`) | `result:` / `verdict:` / `status:` (`PASS` \| `FAIL` \| `BLOCKED`; три равноранговых, ORCH-047) | +| `14-deploy-log.md` | deployer / deploy-finalizer | required | `deploy` | `check_deploy_status` (`_parse_deploy_status`) | `deploy_status:` (`SUCCESS` \| `FAILED`) | +| `15-staging-log.md` | deployer | required (self-hosting) | `deploy-staging` | `check_staging_status` (self-hosting; иначе N/A — ORCH-35) | `staging_status:` (`SUCCESS` \| `FAILED`) | +| `16-post-deploy-log.md` | post-deploy-monitor | when-applicable | пост-`done` наблюдение (ORCH-021; не ребро `STAGE_TRANSITIONS`) | информационный (гейтом не парсится) | `post_deploy_status:` (`HEALTHY` \| `DEGRADED`) | +| `17-security-report.md` | security-гейт (детерминированный, ORCH-022) | when-applicable | под-гейт ребра `deploy-staging→deploy` | `check_security_gate` (врезка в `advance_stage`) | `security_status:` (`PASS` \| `FAIL`) | + +### Примечания манифеста (нормативные) + +- **Под-гейты ребра `deploy-staging→deploy`** (`check_security_gate` → `check_branch_mergeable` → + `check_staging_image_fresh`) исполняются как врезки в `advance_stage`, а НЕ строки + `STAGE_TRANSITIONS`. Не путать с exit-гейтами рёбер. +- **`09-review.md`** — legacy fallback от старой нумерации; **канон — `12-review.md`**. В основную + таблицу как канон не вносится; reviewer пишет `12-review.md`. +- **Категория `when-applicable`** = документ пишется при наличии соответствующего предмета + (инфра / данные / security / post-deploy). Его отсутствие — не нарушение приёмки. +- **`05-…` / `09-…` / `11-…`** — зарезервированные/legacy номера, в текущем каноне не используются. + +--- + +## 3. Machine-verdict доки vs информационные (честный механизм проверки) + +**Machine-verdict доки** — гейт читает ТОЛЬКО YAML-frontmatter (никогда прозу), маппит ключ в +вердикт. Имя ключа чувствительно к регистру; значение парсер приводит к верхнему регистру. + +| Документ | Machine-key | Парсер (`src/qg/checks.py`) | Эффект вердикта | +|----------|-------------|-----------------------------|-----------------| +| `12-review.md` | `verdict:` | `check_reviewer_verdict` | `APPROVED` → дальше; `REQUEST_CHANGES` → откат на `development` | +| `13-test-report.md` | `result:` / `verdict:` / `status:` | `_parse_tests_verdict` | `PASS` → дальше; `FAIL`/`BLOCKED` → откат | +| `14-deploy-log.md` | `deploy_status:` | `_parse_deploy_status` | `SUCCESS` → `done`; `FAILED` → откат (БАГ-8) | +| `15-staging-log.md` | `staging_status:` | `_parse_staging_status` | `SUCCESS` → дальше; `FAILED` → откат (self-hosting; иначе N/A) | +| `17-security-report.md` | `security_status:` | `check_security_gate` | `PASS` → дальше; `FAIL` → откат | + +**Информационные доки** — гейтом НЕ парсятся (структура ничего не блокирует): +`00-business-request.md` (вход), `08-data-requirements.md`, `10-tech-risks.md`, +`16-post-deploy-log.md` (несёт `post_deploy_status:`, но это телеметрия петли уроков ORCH-8 / +наблюдаемость, не гейт). + +--- + +## 4. Конвенция ADR-naming + +### Per-work-item ADR (основное) + +- **Путь:** `docs/work-items//06-adr/` +- **Имя файла:** `ADR-NNN-.md` + - `NNN` — 3-значный, начинается с `001`; инкремент при нескольких ADR в одной задаче + (`ADR-001-…`, `ADR-002-…`). + - `` — kebab-case (нижний регистр, слова через дефис), отражает суть решения. +- **Стадия:** пишет **architect** на стадии `architecture`; гейтится `check_architecture_done` + (наличие каталога `06-adr/` ≥ 1 файла). + +### Сквозной (cross-cutting) ADR + +Решения, затрагивающие несколько компонентов/ролей или поведение всего конвейера, **дублируются** +в глобальный реестр: + +- **Путь:** `docs/architecture/adr/` +- **Имя файла:** `adr-NNNN-.md` (4-значная сквозная нумерация, последовательная по + всему репозиторию; на момент ORCH-075 реестр доходит до `adr-0019`). + +### Примеры из репозитория (реальные, проверенные) + +- `docs/work-items/ORCH-088/06-adr/ADR-001-serial-gate.md` +- `docs/work-items/ORCH-089/06-adr/ADR-001-auto-label-gates.md` +- `docs/work-items/ORCH-071/06-adr/ADR-001-merge-verify-gate.md` +- Сквозные: `docs/architecture/adr/adr-0017-serial-gate.md`, + `docs/architecture/adr/adr-0018-auto-label-gates.md`. + +--- + +## 5. Как пользоваться шаблонами + +1. Скопируй нужный скелет из [`docs/_templates/`](../_templates/) в + `docs/work-items//` под канонным именем (для ADR — `06-adr/ADR-001-.md`). +2. Заполни секции; **не удаляй** machine-key frontmatter у machine-verdict доков и **не меняй имя + ключа** (регистр чувствителен — иначе гейт упадёт ложно). +3. Сверяйся с манифестом (§2–§3): какой агент, на какой стадии, какой гейт читает документ. + +> Стандарт **описательный** (слой 1). Машинная проверка соответствия шаблонам/frontmatter — +> отдельная задача ORCH-52c; до неё соблюдение — на ответственности агента и reviewer'а +> (правило CLAUDE.md «обновлена ли документация»). diff --git a/docs/_templates/00-business-request.md b/docs/_templates/00-business-request.md new file mode 100644 index 0000000..dc6c00b --- /dev/null +++ b/docs/_templates/00-business-request.md @@ -0,0 +1,8 @@ +# Business Request: <краткий заголовок задачи> + +Work Item ID: ORCH-NNN + +## Description + +<Что хочет заказчик/Владелец своими словами: проблема, желаемый результат, контекст. +Допускается `TBD` на входе — analyst уточняет на стадии `analysis` и формализует в 01-brd.md.> diff --git a/docs/_templates/01-brd.md b/docs/_templates/01-brd.md new file mode 100644 index 0000000..f3f9ea9 --- /dev/null +++ b/docs/_templates/01-brd.md @@ -0,0 +1,34 @@ +# 01 — BRD (бизнес-требования): ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: analysis + +## 1. Бизнес-контекст и проблема +<Зачем задача, какую боль/риск закрывает. Установленные факты — не изобретать.> + +## 2. Объём (scope) + +### В объёме +- <что делаем> + +### Вне объёма +- <что явно НЕ делаем — чтобы исключить расползание> + +## 3. Заинтересованные стороны +<Кто заказчик, кого затрагивает, кто принимает результат.> + +## 4. Бизнес-требования (BR) +- **BR-1** — <требование, проверяемое> +- **BR-2** — … + +## 5. Нефункциональные требования (NFR) +- **NFR-1** — <надёжность / совместимость / обратимость / безопасность> +- **NFR-2** — … + +## 6. Допущения и ограничения +<Допущения, на которых стоит решение; внешние ограничения.> + +## 7. Критерии успеха +<Резюме; детальные PASS/FAIL — в 03-acceptance-criteria.md.> + +## 8. Риски +<Краткий перечень; детали — 10-tech-risks.md (заполняет архитектор).> diff --git a/docs/_templates/02-trz.md b/docs/_templates/02-trz.md new file mode 100644 index 0000000..973d842 --- /dev/null +++ b/docs/_templates/02-trz.md @@ -0,0 +1,30 @@ +# 02 — ТЗ (TRZ): ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: analysis + +> ТЗ описывает **конкретные изменения к реализации**, выведенные из BRD и фактического кода. +> Архитектурное обоснование/решения — задача архитектора (06-adr). + +## 1. Сводка изменения +<Что меняется, в одном-двух абзацах.> + +## 2. Задействованные модули / пути +| Путь | Действие | +|------|----------| +| `src/.py` | изменить / создать | + +## 3. Функциональные требования +### FR-1 — <название> +<Поведение, контракт, инварианты. Привязать к BR.> + +## 4. Изменения API +<Новые/изменённые эндпоинты; либо «Нет.».> + +## 5. Изменения схемы БД +<Таблицы/миграции/индексы; либо «Нет.».> + +## 6. Требования к новым/изменённым QG checks +<Изменения `QG_CHECKS` / `check_*`; либо «Нет.».> + +## 7. Совместимость / регресс +<Обратная совместимость, kill-switch, область раската, обратимость.> diff --git a/docs/_templates/03-acceptance-criteria.md b/docs/_templates/03-acceptance-criteria.md new file mode 100644 index 0000000..c576b25 --- /dev/null +++ b/docs/_templates/03-acceptance-criteria.md @@ -0,0 +1,31 @@ +# 03 — Критерии приёмки (Acceptance Criteria): ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: analysis + +Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** +(что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам +репозитория. + +--- + +## AC-1 — <краткий заголовок> + +**Условие:** <проверяемое условие> +- **PASS:** <что должно быть истинно> +- **FAIL:** <что считается провалом> + +--- + +## AC-2 — <краткий заголовок> + +**Условие:** <…> +- **PASS:** <…> +- **FAIL:** <…> + +--- + +## Сводная матрица AC ↔ FR/BR +| AC | Покрывает | +|----|-----------| +| AC-1 | BR-1 / FR-1 | +| AC-2 | BR-2 / FR-2 | diff --git a/docs/_templates/04-test-plan.yaml b/docs/_templates/04-test-plan.yaml new file mode 100644 index 0000000..80e9dfb --- /dev/null +++ b/docs/_templates/04-test-plan.yaml @@ -0,0 +1,20 @@ +work_item: ORCH-NNN +title: "<краткое название тест-плана>" +framework: pytest +scope: "<что покрывается тестами; что вне покрытия>" +notes: > + <Свободные заметки: окружение, особенности, что считается регрессом. + Полный регресс tests/ должен оставаться зелёным.> + +tests: + - id: TC-01 + type: unit # unit | integration + description: "<что проверяет тест>" + module: tests/test_.py + expected: PASS + + - id: TC-02 + type: integration + description: "<…>" + module: tests/test_.py + expected: PASS diff --git a/docs/_templates/06-adr-ADR-NNN-slug.md b/docs/_templates/06-adr-ADR-NNN-slug.md new file mode 100644 index 0000000..a4ab810 --- /dev/null +++ b/docs/_templates/06-adr-ADR-NNN-slug.md @@ -0,0 +1,43 @@ +# ADR-NNN: <Заголовок решения> + +> **Шаблон ADR.** Скопируй в `docs/work-items//06-adr/ADR-NNN-.md`. +> `NNN` начинается с `001`, инкремент при нескольких ADR в задаче. `` — нижний +> регистр, слова через дефис. Сквозное (cross-cutting) решение дополнительно дублируй в +> `docs/architecture/adr/adr-NNNN-.md` (4-значная глобальная нумерация). +> См. `docs/_standards/PIPELINE_DOCS.md` §4. + +Work Item: **ORCH-NNN** — <короткое описание> +Стадия: **architecture** +Сквозная регистрация: **`docs/architecture/adr/adr-NNNN-.md`** (если решение +кросс-каттинговое; иначе — «N/A, локальное решение задачи»). + +## Статус +Proposed + +## Контекст +<Какую проблему решаем; факты, сверенные с кодом (`src/…`); почему «как есть» не годится.> + +## Решение + +### Сводка +<Суть выбранного решения в одном-двух абзацах.> + +### D1 — <название аспекта решения> +<Конкретное решение по аспекту, инварианты, привязка к FR/AC.> + +### D2 — <название аспекта решения> +<…> + +## Альтернативы +- **<альтернатива>** — отвергнуто: <почему>. + +## Последствия +- **+** <положительный эффект> +- **−** <издержка / приятый компромисс + митигейшн> +- **Откат:** <как полностью откатить изменение> + +## Ссылки +- BRD: `docs/work-items/ORCH-NNN/01-brd.md` +- TRZ: `docs/work-items/ORCH-NNN/02-trz.md` +- Acceptance: `docs/work-items/ORCH-NNN/03-acceptance-criteria.md` +- Сверено по коду: `src/…` diff --git a/docs/_templates/07-infra-requirements.md b/docs/_templates/07-infra-requirements.md new file mode 100644 index 0000000..9967cb8 --- /dev/null +++ b/docs/_templates/07-infra-requirements.md @@ -0,0 +1,19 @@ +# 07 — Инфра-требования: ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: architecture + +> When-applicable. Если инфраструктура не затрагивается — оставить явные `N/A` по пунктам +> (файл создаётся для аудитопригодности, а не из-за изменения топологии). + +## I-1. Топология / окружения +<Контейнеры, порты, сеть, тома, хост; либо `N/A`.> + +## I-2. Переменные окружения / секреты +<Новые env-переменные, изменения `.env` / `.env.example`, секреты; либо `N/A`.> + +## I-3. Деплой / рестарт +<Требуется ли рестарт прод-контейнера; self-hosting инвариант (не ронять прод вне staging); +либо `N/A`.> + +## I-4. CI/CD +<Изменения `.gitea/workflows/`, новые тестовые шаги; либо «без изменений».> diff --git a/docs/_templates/08-data-requirements.md b/docs/_templates/08-data-requirements.md new file mode 100644 index 0000000..c4e68af --- /dev/null +++ b/docs/_templates/08-data-requirements.md @@ -0,0 +1,15 @@ +# 08 — Требования к данным: ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: architecture + +> When-applicable / информационный (гейтом не парсится). Если данные/схема не затрагиваются — +> оставить явные `N/A`. + +## Изменения схемы БД +<Новые/изменённые таблицы, индексы, миграции (`init_db`); либо `N/A`.> + +## Новые/изменённые сущности +<Поля, колонки, инварианты данных; либо «Нет.».> + +## Совместимость данных / миграции +<Аддитивность, идемпотентность миграций, restart-safe, влияние на общую прод-БД; либо `N/A`.> diff --git a/docs/_templates/10-tech-risks.md b/docs/_templates/10-tech-risks.md new file mode 100644 index 0000000..1c066d7 --- /dev/null +++ b/docs/_templates/10-tech-risks.md @@ -0,0 +1,16 @@ +# 10 — Технические риски: ORCH-NNN — <название> + +Work Item: **ORCH-NNN** · Repo: **** · Стадия: architecture + +> Информационный (гейтом не парсится). Перечисляет риски реализации и их митигейшн. + +## Реестр рисков + +| ID | Риск | Вер. | Влия. | Митигейшн | +|----|------|------|-------|-----------| +| TR-1 | <описание риска> | Низ./Сред./Выс. | Низ./Сред./Выс. | <как снижаем> | +| TR-2 | <…> | | | | + +## Сводный вывод +<Доминирующий класс рисков; нужна ли эскалация `arch:major-change` / возврат в анализ; +итоговая оценка остаточного риска для прод-конвейера (self-hosting).> diff --git a/docs/_templates/12-review.md b/docs/_templates/12-review.md new file mode 100644 index 0000000..4063608 --- /dev/null +++ b/docs/_templates/12-review.md @@ -0,0 +1,31 @@ +--- +type: review +work_item_id: ORCH-NNN +verdict: APPROVED # APPROVED | REQUEST_CHANGES (machine-key — читает check_reviewer_verdict) +version: 1 +--- + +# Review ORCH-NNN + +> Машинный вердикт читается ТОЛЬКО из `verdict:` во frontmatter (никогда из прозы). +> `APPROVED` → дальше по конвейеру; `REQUEST_CHANGES` → откат на `development`. + +## Summary +<Краткая оценка: реализовано ли по ТЗ/ADR, покрытие тестами, обновлена ли документация.> + +## Оси проверки +<Корректность, соответствие ADR/инвариантам, тесты, документация, совместимость/регресс.> + +## Findings + +### P0 — Blocker +- (нет) + +### P1 — Must fix +- (нет) + +### P2 — Should fix +- (нет) + +## Документация +<Обновлена ли документация (README/CLAUDE/CHANGELOG/архитектура) в том же PR. Нет → REQUEST_CHANGES.> diff --git a/docs/_templates/13-test-report.md b/docs/_templates/13-test-report.md new file mode 100644 index 0000000..fd853e9 --- /dev/null +++ b/docs/_templates/13-test-report.md @@ -0,0 +1,33 @@ +--- +type: test-report +work_item_id: ORCH-NNN +result: PASS # PASS | FAIL | BLOCKED (machine-key — читает _parse_tests_verdict) +--- + +# Test Report — ORCH-NNN + +> Машинный вердикт читается ТОЛЬКО из frontmatter. Канонический ключ — `result:`; равнорангово +> допускаются `verdict:` / `status:` (ORCH-047). Любой негативный токен (`FAIL`/`BLOCKED`) — +> авторитетен. + +## Окружение +- Python: <версия> +- pytest: <версия> +- Дата: YYYY-MM-DD +- Worktree: `feature/ORCH-NNN-` + +## Результаты + +### Полный регресс +<`pytest tests/ -q` — итог (N passed); прод-контейнер не трогается.> + +### Профильные сюиты +<Целевые тесты задачи.> + +### Сопоставление с тест-планом +| TC ID | Описание | Тест-функция | Результат | +|-------|----------|--------------|-----------| +| TC-01 | <…> | test_… | PASS | + +### Сопоставление с критериями приёмки + diff --git a/docs/_templates/14-deploy-log.md b/docs/_templates/14-deploy-log.md new file mode 100644 index 0000000..2d2d98e --- /dev/null +++ b/docs/_templates/14-deploy-log.md @@ -0,0 +1,14 @@ +--- +deploy_status: SUCCESS # SUCCESS | FAILED (machine-key — читает _parse_deploy_status) +work_item: ORCH-NNN +hook_exit_code: 0 +deployed_by: deploy-finalizer +--- + +# Deploy log — ORCH-NNN + +> Машинный вердикт читается ТОЛЬКО из `deploy_status:` во frontmatter. +> `SUCCESS` → `done`; `FAILED` → откат на `development` (БАГ-8). + +<Краткое описание деплоя: что выкачено, exit-code хука, кто/что зафиксировало вердикт +(детерминированный finalizer Фаза C, не LLM, для self-hosting).> diff --git a/docs/_templates/15-staging-log.md b/docs/_templates/15-staging-log.md new file mode 100644 index 0000000..34b197f --- /dev/null +++ b/docs/_templates/15-staging-log.md @@ -0,0 +1,20 @@ +--- +staging_status: SUCCESS # SUCCESS | FAILED (machine-key — читает _parse_staging_status) +timestamp: YYYY-MM-DDTHH:MM:SSZ +base_url: http://localhost:8501 +--- + +# Staging Gate Log + +> Машинный вердикт читается ТОЛЬКО из `staging_status:` во frontmatter. Реален для self-hosting +> (`orchestrator`); для прочих репо гейт — N/A (ORCH-35). `SUCCESS` → дальше; `FAILED` → откат. + +Staging test suite — итог (например: «All REAL pipeline checks passed»). Запуск канонически +внутри контейнера `orchestrator-staging` (8501). + +## Results +- **Block A (SMOKE)**: <…> +- **Block B (ACCESS)**: <…> +- **Block C (E2E)**: <…> + +REAL failed: . diff --git a/docs/_templates/16-post-deploy-log.md b/docs/_templates/16-post-deploy-log.md new file mode 100644 index 0000000..749f5af --- /dev/null +++ b/docs/_templates/16-post-deploy-log.md @@ -0,0 +1,21 @@ +--- +post_deploy_status: HEALTHY # HEALTHY | DEGRADED (информационный, гейтом НЕ парсится — телеметрия ORCH-021) +action_taken: NONE # NONE | ALERT_ONLY | ROLLBACK_OK | ROLLBACK_FAILED +work_item: ORCH-NNN +window_s: 900 +checks_total: 0 +checks_failed: 0 +--- + +# Post-deploy log — ORCH-NNN + +> Пост-`done` наблюдение прода (ORCH-021). НЕ ребро `STAGE_TRANSITIONS`, гейтом не парсится — +> frontmatter машиночитаем для петли уроков ORCH-8 / наблюдаемости. + +Окно наблюдения: s; опросов всего: , с провалом: . + +## Серия наблюдений +<Краткая серия сигналов health / доли 5xx; классификация HEALTHY/DEGRADED.> + +## Решение +<Реакция: для self-hosting всегда `ALERT_ONLY` (ручной approve, тик не откатывает прод).> diff --git a/docs/_templates/17-security-report.md b/docs/_templates/17-security-report.md new file mode 100644 index 0000000..61dcdce --- /dev/null +++ b/docs/_templates/17-security-report.md @@ -0,0 +1,26 @@ +--- +security_status: PASS # PASS | FAIL (machine-key — читает check_security_gate) +work_item: ORCH-NNN +secrets_found: 0 +deps_blocking: 0 +deps_warning: 0 +deps_audit_degraded: false +--- + +# Security Report — ORCH-NNN + +> Детерминированный security-гейт (ORCH-022) — под-гейт ребра `deploy-staging→deploy` (врезка в +> `advance_stage`, не строка `STAGE_TRANSITIONS`). Машинный вердикт читается ТОЛЬКО из +> `security_status:`. `PASS` → дальше; `FAIL` → откат. + +## Verdict + + +## Secrets + + +## Dependencies (blocking) + + +## Dependencies (warning) +<Не блокирующие предупреждения зависимостей.> diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 3d591a0..6153351 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -41,6 +41,18 @@ created → analysis → architecture → development → review → testing → **Канон гейтов:** машинные вердикты читаются ТОЛЬКО из YAML-frontmatter, никогда из прозы. Лог-файлы мержатся в `origin/main` отдельным PR; гейт читает из `origin/main`. +### Стандарт документов конвейера (ORCH-075, ORCH-52b) +Структура номерных документов work item (`00-business-request.md` … `17-security-report.md`), +карта «стадия → агент → документ → категория → гейт/механизм → frontmatter machine-key» и +конвенция ADR-naming зафиксированы как golden source в +[`docs/_standards/PIPELINE_DOCS.md`](../_standards/PIPELINE_DOCS.md); копируемые скелеты — в +[`docs/_templates/`](../_templates/). Манифест **документирует** поведение гейтов (источник истины +остаётся код: `src/stages.py`, `src/qg/checks.py`), честно различая machine-verdict доки +(`12/13/14/15/17` — несут читаемый гейтом ключ) и информационные (`00/08/10/16` — гейтом не +парсятся). Это слой 1 (описательный); машинная проверка соответствия — задача ORCH-52c. ADR: +[adr-0019](adr/adr-0019-pipeline-docs-standard.md), детально — +`docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.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_`/`ORCH_AGENT_EFFORT_` > `*_default` > CLI-дефолт (без флага)**. **Эффорт (ORCH-081):** ниже `*_default` добавлен непустой **per-role floor** — class-default поля `agent_effort_` из `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`. diff --git a/docs/architecture/adr/adr-0019-pipeline-docs-standard.md b/docs/architecture/adr/adr-0019-pipeline-docs-standard.md new file mode 100644 index 0000000..40fbf9c --- /dev/null +++ b/docs/architecture/adr/adr-0019-pipeline-docs-standard.md @@ -0,0 +1,49 @@ +# adr-0019: Стандарт документов пайплайна (docs/_standards + docs/_templates + ADR-naming) + +Статус: **proposed** · Дата: 2026-06-09 · Источник: **ORCH-075** (ORCH-52b, слой 1 эпика ORCH-52) +Детально: `docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md`. + +## Контекст +Агенты всех ролей пишут номерные доки work item (`00…17`) «по памяти»; каталогов +`docs/_standards/` и `docs/_templates/` нет. Следствия: разнобой структуры между задачами; риск +рассинхрона критичных frontmatter-ключей машинных доков (`verdict:` / `result:` / `deploy_status:` / +`staging_status:` / `security_status:`), которые читает гейт; отсутствует целостная карта «стадия → +агент → документ → гейт». Эпик ORCH-52 слоист: слой 1 (52b) фиксирует **договорённость**, машинная +проверка/валидатор — отдельный слой 52c. + +## Решение +**Документационный стандарт, docs-only, выведенный из фактического кода и эталонных доков:** + +1. `docs/_standards/PIPELINE_DOCS.md` — манифест-карта «стадия → документ → владелец-агент → + категория (`required`/`when-applicable`/`optional`) → гейт/механизм → frontmatter machine-key». + Манифест **документирует** поведение гейтов (источник истины остаётся `src/`), честно различает + machine-verdict доки (`12,13,14,15,17`) и информационные (`00,08,10,16`), и помечает под-гейты + ребра `deploy-staging→deploy` (security/merge/image-freshness) как врезки в `advance_stage`, а не + строки `STAGE_TRANSITIONS`. +2. `docs/_templates/*` — копируемые скелеты для каждого `required`/`when-applicable` дока; секции + выведены из эталонов (ORCH-088/073/089/071), новые не изобретаются; машинные доки несут точный + frontmatter-ключ из ground-truth. +3. **ADR-naming** канонизирован: `docs/work-items//06-adr/ADR-NNN-.md` (NNN с + `001`); кросс-каттинговые решения дублируются в этот глобальный реестр `adr-NNNN-.md`. + +Подключение — ссылки из `CLAUDE.md` и `docs/architecture/README.md` + запись в `CHANGELOG.md`. + +## Альтернативы +- Сразу валидатор на гейте — отвергнуто (ORCH-52c; нарушил бы docs-only/NFR-1, групповой риск). +- Манифест как источник истины гейтов — отвергнуто (дубль-истина «манифест ≠ код»). +- Шаблоны в `docs/work-items/_template/` — отвергнуто (риск для сканеров/гейтов наличия файлов). +- Ретро-фит истории доков — отвергнуто (вне scope, отдельный риск). + +## Последствия +- **+** Единый golden source структуры доков; меньше ложных падений гейтов из-за неверного + frontmatter-ключа; ADR-naming записан; база для ORCH-52c. +- **+ Нулевой рантайм-риск:** только `docs/**` + `CLAUDE.md` + `CHANGELOG.md`; `STAGE_TRANSITIONS` / + `QG_CHECKS` / `check_*` / `src/stage_engine.py` / схема БД — без изменений; полностью обратимо. +- **−** Манифест — снимок поведения гейтов, дрейфует до ORCH-52c (митигейшн: источник истины — код, + reviewer-правило, привязка к именам `check_*`); стандарт описательный, не принуждающий. + +## Связи +- Источник: ORCH-075 (`docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md`). +- Документирует (не меняет): adr-0003/0006/0008/0012/0013/0014/0016 (гейты и под-гейты ребра), + `STAGE_TRANSITIONS` (`src/stages.py`), `QG_CHECKS` (`src/qg/checks.py`). +- Downstream: ORCH-52c (frontmatter-валидатор / writer-контракт), ORCH-52d (правка промптов). diff --git a/docs/work-items/ORCH-075/00-business-request.md b/docs/work-items/ORCH-075/00-business-request.md new file mode 100644 index 0000000..a5cf346 --- /dev/null +++ b/docs/work-items/ORCH-075/00-business-request.md @@ -0,0 +1,7 @@ +# Business Request: ORCH-52b: стандарт документов (docs/_templates + манифест стадий + ADR-naming) + +Work Item ID: ORCH-075 + +## Description + +TBD diff --git a/docs/work-items/ORCH-075/01-brd.md b/docs/work-items/ORCH-075/01-brd.md new file mode 100644 index 0000000..019af35 --- /dev/null +++ b/docs/work-items/ORCH-075/01-brd.md @@ -0,0 +1,111 @@ +# 01 — BRD: ORCH-075 — ORCH-52b: стандарт документов (docs/_templates + манифест стадий + ADR-naming) + +Work Item: **ORCH-075** +Repo: **orchestrator** (self-hosting) +Стадия: analysis +Заказчик: Owner / команда агентов оркестратора +Тип: documentation-standard (слой 1 эпика ORCH-52) + +> Документ фиксирует **бизнес-требования** к созданию стандарта документов пайплайна. +> ORCH-52b — слой 1 («стандарт»): только документация (манифест + канонические шаблоны + +> конвенция ADR-naming). Любая принудительная проверка/валидатор/правка кода и промптов — +> вне scope (это ORCH-52c/52d). Источник истины для манифеста — фактические +> `STAGE_TRANSITIONS` / `QG_CHECKS` и реальные эталонные доки в репозитории, а не вымысел. + +--- + +## 1. Бизнес-контекст и проблема + +### 1.1. Текущее состояние (проверено в репо) +- Каталоги `docs/_templates/` и `docs/_standards/` **не существуют**. +- Агенты (`analyst` → `architect` → … → `deployer`) пишут номерные доки work item + (`00-business-request.md` … `17-security-report.md`) «с нуля по памяти». +- Конвенция ADR-naming `06-adr/ADR-NNN-.md` фактически уже сложилась в репо, + но **нигде не зафиксирована** как стандарт. + +### 1.2. Боль +- **Разнобой структуры** между задачами: набор и порядок секций одного и того же дока + плавает от work item к work item (видно при сравнении BRD/ТЗ разных задач). +- Машинные доки-вердикты (`12-review.md`, `13-test-report.md`, `14-deploy-log.md`, + `15-staging-log.md`, `17-security-report.md`) держат критичный frontmatter-ключ + (`verdict:` / `deploy_status:` / `staging_status:` / `security_status:`), читаемый + гейтом — но единого канонического скелета с этим ключом нет → риск рассинхрона. +- Нет единой карты «какая стадия / какой агент пишет какой документ и на каком гейте он + проверяется» — онбординг новых агентских ролей и аудит покрытия затруднён. + +### 1.3. Почему именно стандарт (а не сразу валидатор) +Эпик ORCH-52 разбит на слои, чтобы **сначала зафиксировать договорённость (golden source +документации)**, а уже потом, отдельной задачей (52c), навешивать машинную проверку +frontmatter/шаблонов на гейте. Стандарт без кода — обратимый, низкорисковый, не трогает +работающий прод-конвейер (self-hosting). Это снижает групповой риск. + +## 2. Объём (scope) + +### 2.1. В объёме (ORCH-52b) +1. **Манифест** `docs/_standards/PIPELINE_DOCS.md`: таблица «стадия → документ» с + владельцем-агентом, категорией (`required` / `when-applicable` / `optional`), стадией + написания и гейтом/механизмом проверки — **сверенная с фактическими `QG_CHECKS` и + `stage_engine`**. +2. **Канонические шаблоны** `docs/_templates/*` — скелеты (frontmatter при необходимости + + обязательные секции) для всех номерных доков из реального набора. +3. **Конвенция ADR-naming** — зафиксировать сложившийся формат `06-adr/ADR-NNN-.md` + (нумерация с `001`, где живёт, как формируется slug); раздел в манифесте/стандарте. +4. Ссылки на новый стандарт в `CLAUDE.md` и `docs/architecture/README.md`; запись в + `CHANGELOG.md`. + +### 2.2. Вне объёма (явно — это ORCH-52c / 52d) +- Frontmatter-валидатор в коде; writer-контракт; принудительная проверка наличия/структуры + шаблонов на Quality Gate. +- Любые изменения `QG_CHECKS` / `STAGE_TRANSITIONS` / `check_*` / `src/stage_engine.py` / + схемы БД. +- Правка системных промптов агентов (`.openclaw/agents/*`) — это слой 52d. +- Массовое приведение **уже существующих** доков прошлых задач к новому шаблону (ретро-фит). + +## 3. Заинтересованные стороны +| Роль | Интерес | +|------|---------| +| Owner | Единообразие и аудитопригодность документации проекта | +| Агенты analyst/architect | Готовый скелет → меньше расхождений, быстрее старт | +| Агенты reviewer/tester/deployer | Предсказуемый frontmatter машинных доков | +| ORCH-52c (downstream) | Стандарт = база для frontmatter-валидатора/writer-контракта | + +## 4. Бизнес-требования (BR) +| ID | Требование | +|----|------------| +| BR-1 | Создан `docs/_standards/PIPELINE_DOCS.md` — манифест, покрывающий **все** номерные доки реального набора (00,01,02,03,04,06,07,08,10,12,13,14,15,16,17) с владельцем-агентом и категорией. | +| BR-2 | Каждому `required` и `when-applicable` доку соответствует канонический шаблон в `docs/_templates/` (frontmatter при необходимости + обязательные секции). | +| BR-3 | Формат ADR-naming `06-adr/ADR-NNN-.md` зафиксирован в стандарте и совпадает с реальными ADR в репо. | +| BR-4 | Манифест и шаблоны **согласованы с фактическими эталонными доками** (ORCH-088/073/089/071): нет секций, которых никто не пишет, и наоборот; frontmatter-ключи машинных доков совпадают с тем, что реально парсят гейты. | +| BR-5 | Обновлены `CLAUDE.md` и `docs/architecture/README.md` со ссылкой на стандарт; добавлена запись в `CHANGELOG.md`. | +| BR-6 | Манифест отражает категорию проверки документа фактическим механизмом: какие доки несут machine-verdict frontmatter, читаемый гейтом, а какие информационные (не гейтятся). | + +## 5. Нефункциональные требования (NFR) +| ID | Требование | +|----|------------| +| NFR-1 | **Нулевой риск для прода:** изменения — только под `docs/` (+ `CLAUDE.md`/`CHANGELOG.md`). Ни строки кода/гейтов. | +| NFR-2 | **Достоверность:** все утверждения манифеста о стадии/агенте/гейте проверяемы по `src/stages.py` / `src/qg/checks.py` / `src/stage_engine.py`. | +| NFR-3 | **Не изобретать:** шаблоны выведены из существующих эталонов, не из фантазии; новые секции не вводятся. | +| NFR-4 | **Читаемость:** манифест — на русском, в стиле существующей документации проекта; таблицы машиночитаемо-аккуратные. | +| NFR-5 | **Обратимость:** удаление новых файлов полностью откатывает изменение без следов в поведении системы. | + +## 6. Допущения и ограничения +- Реальный набор номерных доков и их частота взяты из `docs/work-items/` (факты в описании + задачи); считаем его авторитетным на момент задачи. +- Эталонные («golden») задачи для извлечения скелетов — ORCH-088, ORCH-073, ORCH-089, ORCH-071. +- `09-review.md` — legacy fallback (канон — `12-review.md`); в манифест как канон **не** + вводится, при необходимости упоминается примечанием. +- Стадия `monitoring` для `16-post-deploy-log.md` — пост-`done` наблюдение (ORCH-021), не + ребро `STAGE_TRANSITIONS`; манифест это отражает явно. + +## 7. Критерии успеха +- Любой агент, открыв `docs/_standards/PIPELINE_DOCS.md`, понимает: какой документ он пишет + на своей стадии, в какой категории, с каким frontmatter и где он проверяется. +- Для каждого `required`/`when-applicable` дока существует шаблон, который можно скопировать + и заполнить без догадок о структуре. +- ADR-naming больше не «устная традиция», а записанная конвенция. +- Полный набор уточняющих PASS/FAIL — в `03-acceptance-criteria.md`. + +## 8. Риски +Технические риски и митигейшн ведёт архитектор в `10-tech-risks.md`. Ключевой бизнес-риск — +**рассинхрон стандарта с кодом** (манифест описал гейт, которого нет, или наоборот): митигируется +NFR-2 (сверка с `src/`) и AC-1/AC-4. diff --git a/docs/work-items/ORCH-075/02-trz.md b/docs/work-items/ORCH-075/02-trz.md new file mode 100644 index 0000000..263c31f --- /dev/null +++ b/docs/work-items/ORCH-075/02-trz.md @@ -0,0 +1,141 @@ +# 02 — ТЗ (TRZ): ORCH-075 — ORCH-52b: стандарт документов + +Work Item: **ORCH-075** · Repo: **orchestrator** · Стадия: analysis + +> ТЗ описывает **конкретные артефакты к созданию** (манифест + шаблоны + раздел ADR-naming) и +> их обязательное содержимое, выведенное из фактических `STAGE_TRANSITIONS`/`QG_CHECKS` и +> эталонных доков. Это **docs-only** изменение: исходный код, гейты, схема БД, промпты — +> НЕ затрагиваются (см. §7). Архитектурное обоснование/решения — задача архитектора (06-adr). + +## 1. Сводка изменения +Создать каталоги `docs/_standards/` и `docs/_templates/`, наполнить их манифестом +«стадия→документ», каноническими скелетами номерных доков и зафиксировать ADR-naming. +Обновить точки-ссылки (`CLAUDE.md`, `docs/architecture/README.md`, `CHANGELOG.md`). + +## 2. Задействованные модули / пути +| Путь | Действие | +|------|----------| +| `docs/_standards/PIPELINE_DOCS.md` | **создать** — манифест стадия→документ + раздел ADR-naming | +| `docs/_templates/00-business-request.md` | **создать** — шаблон | +| `docs/_templates/01-brd.md` | **создать** | +| `docs/_templates/02-trz.md` | **создать** | +| `docs/_templates/03-acceptance-criteria.md` | **создать** | +| `docs/_templates/04-test-plan.yaml` | **создать** | +| `docs/_templates/06-adr-ADR-NNN-slug.md` | **создать** — шаблон ADR (имя файла шаблона без коллизии с реальной нумерацией) | +| `docs/_templates/07-infra-requirements.md` | **создать** (when-applicable) | +| `docs/_templates/08-data-requirements.md` | **создать** (when-applicable) | +| `docs/_templates/10-tech-risks.md` | **создать** | +| `docs/_templates/12-review.md` | **создать** (frontmatter `verdict:`) | +| `docs/_templates/13-test-report.md` | **создать** (frontmatter `result:`) | +| `docs/_templates/14-deploy-log.md` | **создать** (frontmatter `deploy_status:`) | +| `docs/_templates/15-staging-log.md` | **создать** (frontmatter `staging_status:`) | +| `docs/_templates/16-post-deploy-log.md` | **создать** (frontmatter `post_deploy_status:`) | +| `docs/_templates/17-security-report.md` | **создать** (frontmatter `security_status:`) | +| `CLAUDE.md` | **изменить** — ссылка на стандарт в разделе «Артефакты задачи» / «Правила для агентов» | +| `docs/architecture/README.md` | **изменить** — ссылка на стандарт | +| `CHANGELOG.md` | **изменить** — запись в `## [Unreleased]` | + +> Точное имя файла-шаблона ADR оставлено на усмотрение разработчика/архитектора при условии, +> что **внутри** шаблона и в манифесте зафиксирован реальный целевой формат +> `06-adr/ADR-NNN-.md` (см. §3, FR-3). + +## 3. Функциональные требования + +### FR-1 — Манифест `docs/_standards/PIPELINE_DOCS.md` +Содержит таблицу-манифест, покрывающую **все** номерные доки реального набора. Для каждого — +колонки: `Документ`, `Владелец-агент`, `Категория`, `Стадия написания`, `Гейт/механизм +проверки`, `Frontmatter machine-key (если есть)`. Манифест ДОЛЖЕН соответствовать +ground-truth ниже (сверено по `src/`): + +| Документ | Владелец-агент | Категория | Стадия написания | Гейт / проверка | Machine-key | +|----------|----------------|-----------|------------------|-----------------|-------------| +| `00-business-request.md` | система (Plane webhook `_create_initial_docs`) / заказчик | required | `created` (инициализация) | не гейтится (вход) | — | +| `01-brd.md` | analyst | required | `analysis` | exit-гейт `analysis→architecture` = `check_analysis_approved` (Approved + полнота файлов); helper `check_analysis_complete` (наличие) | — | +| `02-trz.md` | analyst | required | `analysis` | то же | — | +| `03-acceptance-criteria.md` | analyst | required | `analysis` | то же | — | +| `04-test-plan.yaml` | analyst | required | `analysis` | то же | — | +| `06-adr/ADR-NNN-.md` | architect | required | `architecture` | `check_architecture_done` (наличие каталога/ADR) | — | +| `07-infra-requirements.md` | architect | when-applicable | `architecture` | `check_architecture_done` (учитывается при наличии) | — | +| `08-data-requirements.md` | architect | when-applicable | `architecture` | информационный (гейтом не парсится) | — | +| `10-tech-risks.md` | architect | required | `architecture` | информационный (гейтом не парсится) | — | +| `12-review.md` | reviewer | required | `review` | `check_reviewer_verdict` | `verdict:` (APPROVED\|REQUEST_CHANGES) | +| `13-test-report.md` | tester | required | `testing` | `check_tests_passed` | `result:`/`verdict:`/`status:` (PASS\|FAIL\|BLOCKED) | +| `14-deploy-log.md` | deployer / deploy-finalizer | required | `deploy` | `check_deploy_status` | `deploy_status:` (SUCCESS\|FAILED) | +| `15-staging-log.md` | deployer | required (self-hosting) | `deploy-staging` | `check_staging_status` (self-hosting; иначе N/A) | `staging_status:` (SUCCESS\|FAILED) | +| `16-post-deploy-log.md` | post-deploy-monitor | when-applicable | пост-`done` наблюдение (ORCH-021, не ребро `STAGE_TRANSITIONS`) | информационный (гейтом не парсится) | `post_deploy_status:` | +| `17-security-report.md` | security-гейт (детерминированный, ORCH-022) | when-applicable | под-гейт ребра `deploy-staging→deploy` | `check_security_gate` | `security_status:` (PASS\|FAIL) | + +Примечания манифеста (обязательны): +- Под-гейты ребра `deploy-staging→deploy` (`check_security_gate` → `check_branch_mergeable` → + `check_staging_image_fresh`) — **не** строки `STAGE_TRANSITIONS`, а врезки в `advance_stage`. +- `09-review.md` — legacy fallback; канон — `12-review.md` (упомянуть примечанием, в основную + таблицу как канон не вносить). +- Категория `when-applicable` = пишется при наличии соответствующего предмета (инфра/данные/ + security/post-deploy); её отсутствие — не нарушение. + +### FR-2 — Шаблоны `docs/_templates/*` +Каждый шаблон — копируемый скелет. Обязательные элементы по типам (выведено из эталонов +ORCH-088/073/089/071): + +- **Документы БЕЗ frontmatter** (`00`,`01`,`02`,`03`,`06-adr`,`07`,`08`,`10`): заголовок `#`, + строка метаданных `Work Item / Repo / Стадия`, и фиксированные `##`-секции (ниже §FR-2.1). +- **YAML-only**: `04-test-plan.yaml` — корневые ключи + список `tests:` (ниже §FR-2.2). +- **Документы С YAML-frontmatter** (`12`,`13`,`14`,`15`,`16`,`17`): блок `---…---` с + machine-key из таблицы FR-1 + body-секции. + +#### FR-2.1 Обязательные секции по документу (минимальный канон) +- `00-business-request.md`: `# Business Request: `; строка `Work Item ID:`; `## Description`. +- `01-brd.md`: `## 1. Бизнес-контекст и проблема`, `## 2. Объём (scope)` (с `### В объёме`/`### Вне объёма`), `## 3. Заинтересованные стороны`, `## 4. Бизнес-требования (BR)`, `## 5. Нефункциональные требования (NFR)`, `## 6. Допущения и ограничения`, `## 7. Критерии успеха`, `## 8. Риски`. +- `02-trz.md`: `## 1. Сводка изменения`, `## 2. Задействованные модули`, `## 3. Функциональные требования`, `## 4. Изменения API`, `## 5. Изменения схемы БД`, `## 6. Требования к QG checks`, `## 7. Совместимость / регресс`. +- `03-acceptance-criteria.md`: преамбула формата; повторяемый блок `## AC-N — ` с `**Условие:**`, `- **PASS:**`, `- **FAIL:**`; опц. `## Сводная матрица AC ↔ FR/BR`. +- `06-adr (шаблон)`: `# ADR-NNN: <title>`, метаданные (`Work Item`,`Стадия: architecture`,`Сквозная регистрация:`), `## Статус`, `## Контекст`, `## Решение` (с `### Сводка` и `### D1 — …`), `## Альтернативы`, `## Последствия`, `## Ссылки`. +- `07-infra-requirements.md`: `# 07 — Инфра-требования`, нумерованные `## I-N. <topic>`. +- `08-data-requirements.md`: `# 08 — Требования к данным`, секции по таблицам/колонкам/миграциям. +- `10-tech-risks.md`: `# 10 — Технические риски`, таблица `| ID | Риск | Вер. | Влия. | Митигейшн |`, `## Сводный вывод`. +- `12-review.md`: frontmatter `type: review` / `work_item_id:` / `verdict:` / `version:`; body `## Summary`, `## Оси проверки`, `## Findings` (`### P0`/`### P1`/`### P2`), `## Документация`. +- `13-test-report.md`: frontmatter `type: test-report` / `work_item_id:` / `result:`; body `## Окружение`, `## Результаты` (`### Полный регресс`, `### Профильные сюиты`, `### Сопоставление с тест-планом`, `### Сопоставление с критериями приёмки`). +- `14-deploy-log.md`: frontmatter `deploy_status:` / `work_item:` / `hook_exit_code:` / `deployed_by:`; body — краткое описание деплоя. +- `15-staging-log.md`: frontmatter `staging_status:` / `timestamp:` / `base_url:`; body — `# Staging Gate Log` + результаты проверок. +- `16-post-deploy-log.md`: frontmatter `post_deploy_status:` / `action_taken:` / `work_item:`; body — окно наблюдения/серия/решение. +- `17-security-report.md`: frontmatter `security_status:` / `work_item:`; body — secret-scan + dependency-audit результаты. + +#### FR-2.2 `04-test-plan.yaml` +Корень: `work_item:`, `title:`, `framework: pytest`, опц. `scope:`/`notes:`. Список `tests:` +с элементами `{ id: TC-NN, type: unit|integration, description, module: tests/…, expected: PASS }`. + +### FR-3 — Конвенция ADR-naming +Зафиксировать в `PIPELINE_DOCS.md` отдельным разделом: +- Путь: `docs/work-items/<plane-id>/06-adr/`. +- Имя: `ADR-NNN-<kebab-slug>.md`, `NNN` с `001`, инкремент при нескольких ADR в одной задаче. +- `slug` — kebab-case (нижний регистр, дефисы), отражает суть решения. +- Сквозные (cross-cutting) решения дублируются в `docs/architecture/adr/adr-NNNN-<slug>.md` + (4-значная глобальная нумерация) — это уже существующая конвенция, лишь зафиксировать. +- Примеры из репо: `ADR-001-serial-gate`, `ADR-001-auto-label-gates`, `ADR-001-merge-verify-gate`. + +### FR-4 — Точки-ссылки +- `CLAUDE.md`: в разделе «Артефакты задачи» и/или «Правила для агентов» добавить ссылку на + `docs/_standards/PIPELINE_DOCS.md` и `docs/_templates/` как golden source структуры доков. +- `docs/architecture/README.md`: добавить ссылку/абзац о стандарте документов. +- `CHANGELOG.md`: запись в `## [Unreleased]` (`docs:` тип). + +## 4. Изменения API +Нет. Эндпоинты не добавляются и не меняются. + +## 5. Изменения схемы БД +Нет. Таблицы/миграции не затрагиваются. + +## 6. Требования к новым/изменённым QG checks +Нет. `QG_CHECKS` и `check_*` **не трогаются** (это ORCH-52c). Манифест лишь **документирует** +текущее поведение гейтов. + +## 7. Совместимость / регресс +- Изменения только под `docs/` + `CLAUDE.md` + `CHANGELOG.md`. Поведение рантайма неизменно. +- Существующие доки прошлых задач не модифицируются (нет ретро-фита). +- `09-review.md` (legacy) сохраняется как fallback; манифест канонизирует `12-review.md`. +- Удаление новых файлов → полный откат без следов (NFR-5). + +## 8. Артефакты, создаваемые/обновляемые по pipeline +Создаются: `docs/_standards/PIPELINE_DOCS.md`, `docs/_templates/*` (15 шаблонов). +Обновляются: `CLAUDE.md`, `docs/architecture/README.md`, `CHANGELOG.md`. +Downstream-доки самой задачи ORCH-075 (`06-adr`, `10-tech-risks`, `12-review`, `13-test-report`, +`14-deploy-log`, `15-staging-log`) — по штатному конвейеру. diff --git a/docs/work-items/ORCH-075/03-acceptance-criteria.md b/docs/work-items/ORCH-075/03-acceptance-criteria.md new file mode 100644 index 0000000..a22543d --- /dev/null +++ b/docs/work-items/ORCH-075/03-acceptance-criteria.md @@ -0,0 +1,104 @@ +# 03 — Критерии приёмки (Acceptance Criteria): ORCH-075 — ORCH-52b: стандарт документов + +Work Item: **ORCH-075** · Repo: **orchestrator** · Стадия: analysis + +Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** +(что считается провалом). Скоп — только создание стандарта/шаблонов/манифеста (docs-only). + +> Критерии унаследованы из AC задачи и расширены проверяемыми условиями. Любой машинный/ручной +> reviewer проверяет их буквально по файлам репозитория. + +--- + +## AC-1 — Манифест создан и покрывает весь реальный набор + +**Условие:** существует `docs/_standards/PIPELINE_DOCS.md` с таблицей-манифестом. +- **PASS:** файл существует; манифест содержит строки для **всех** номерных доков реального + набора — `00, 01, 02, 03, 04, 06, 07, 08, 10, 12, 13, 14, 15, 16, 17`; для каждого указаны + владелец-агент (analyst/architect/developer/reviewer/tester/deployer/система) и категория + (`required` / `when-applicable` / `optional`). +- **FAIL:** файла нет; пропущен хотя бы один документ набора; у дока отсутствует владелец или + категория. + +--- + +## AC-2 — Шаблоны созданы для каждого required/when-applicable дока + +**Условие:** существует `docs/_templates/` с каноническими скелетами. +- **PASS:** для каждого `required` и `when-applicable` дока есть файл-шаблон; в шаблоне + присутствуют (а) frontmatter с machine-key там, где он требуется по FR-1 (`12`→`verdict:`, + `13`→`result:`, `14`→`deploy_status:`, `15`→`staging_status:`, `16`→`post_deploy_status:`, + `17`→`security_status:`), и (б) обязательные `##`-секции из ТЗ §FR-2.1. +- **FAIL:** отсутствует шаблон для какого-либо required/when-applicable дока; в шаблоне + машинного дока нет требуемого frontmatter-ключа; набор секций произвольный, не из ТЗ. + +--- + +## AC-3 — ADR-naming зафиксирован + +**Условие:** в стандарте есть раздел про ADR-naming. +- **PASS:** зафиксирован формат `06-adr/ADR-NNN-<kebab-slug>.md` (NNN с `001`), путь + (`docs/work-items/<plane-id>/06-adr/`), правило формирования slug (kebab-case) и связь со + сквозным реестром `docs/architecture/adr/adr-NNNN-<slug>.md`; приведён ≥1 реальный пример. +- **FAIL:** ADR-naming не описан, либо описанный формат не совпадает с реальными ADR в репо + (напр. указана нумерация не с `001`, неверный путь, неверный регистр slug). + +--- + +## AC-4 — Согласованность с фактическими эталонами + +**Условие:** манифест и шаблоны соответствуют реальным эталонным докам (ORCH-088/073/089/071) +и фактическому коду. +- **PASS:** в шаблонах нет секций, которых никто не пишет в эталонах; все секции эталонов, + входящие в общий канон, присутствуют; frontmatter-ключи машинных доков совпадают с тем, что + реально парсят `src/qg/checks.py` (`verdict:`/`result:`/`deploy_status:`/`staging_status:`/ + `security_status:`); привязка «документ→стадия→гейт» совпадает с `src/stages.py` + (`STAGE_TRANSITIONS`). +- **FAIL:** шаблон вводит выдуманную секцию; манифест приписывает доку неверную стадию/гейт/ + агента; frontmatter-ключ в шаблоне не тот, что читает гейт. + +--- + +## AC-5 — Ссылки и CHANGELOG обновлены + +**Условие:** точки-ссылки и журнал изменений отражают новый стандарт. +- **PASS:** `CLAUDE.md` и `docs/architecture/README.md` содержат ссылку на + `docs/_standards/PIPELINE_DOCS.md` (и/или `docs/_templates/`); в `CHANGELOG.md` добавлена + запись в `## [Unreleased]` типа `docs:`. +- **FAIL:** хотя бы одна из трёх точек не обновлена. + +--- + +## AC-6 — Код гейтов НЕ изменён + +**Условие:** изменение строго docs-only. +- **PASS:** `git diff` не содержит изменений в `src/qg/checks.py` (`QG_CHECKS`/`check_*`), + `src/stages.py` (`STAGE_TRANSITIONS`), `src/stage_engine.py`, схеме БД и любом коде гейтов; + затронуты только `docs/**`, `CLAUDE.md`, `CHANGELOG.md` (+ опционально новые файлы тестов). +- **FAIL:** изменён любой из перечисленных кодовых модулей/гейтов/схемы. + +--- + +## AC-7 — Манифест различает machine-verdict и информационные доки + +**Условие:** манифест честно отражает механизм проверки. +- **PASS:** документы, чей frontmatter читает гейт (`12,13,14,15,17`), помечены своим + machine-key и гейтом; информационные (`00,08,10,16`) явно помечены как не гейтящиеся; + под-гейты ребра `deploy-staging→deploy` (security/merge/image-freshness) отмечены как врезки + в `advance_stage`, а не строки `STAGE_TRANSITIONS`. +- **FAIL:** информационный док представлен как гейтящийся (или наоборот); под-гейты выданы за + стадии. + +--- + +## Сводная матрица AC ↔ BR + +| AC | Покрывает BR | +|----|--------------| +| AC-1 | BR-1 | +| AC-2 | BR-2 | +| AC-3 | BR-3 | +| AC-4 | BR-4, BR-6 | +| AC-5 | BR-5 | +| AC-6 | NFR-1, NFR-5 | +| AC-7 | BR-6, NFR-2 | diff --git a/docs/work-items/ORCH-075/04-test-plan.yaml b/docs/work-items/ORCH-075/04-test-plan.yaml new file mode 100644 index 0000000..fcc8c0a --- /dev/null +++ b/docs/work-items/ORCH-075/04-test-plan.yaml @@ -0,0 +1,136 @@ +work_item: ORCH-075 +title: "ORCH-52b — стандарт документов (docs/_standards + docs/_templates + ADR-naming)" +scope: "docs-only: проверяется НАЛИЧИЕ и СТРУКТУРА новых файлов-стандартов/шаблонов; код гейтов не трогается" +framework: pytest +notes: > + Изменение документационное. Тесты — лёгкие структурные проверки (existence + наличие + обязательных секций/frontmatter-ключей), новый файл tests/test_orch_52b_docs_standard.py. + Тесты НЕ меняют QG_CHECKS/STAGE_TRANSITIONS и не вводят новый гейт (это ORCH-52c). Полный + регресс tests/ должен остаться зелёным (отсутствие регресса от docs-изменения). + +tests: + - id: TC-01 + type: integration + description: "docs/_standards/PIPELINE_DOCS.md существует и непустой" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-02 + type: integration + description: "Манифест PIPELINE_DOCS.md упоминает все номерные доки набора: 00,01,02,03,04,06,07,08,10,12,13,14,15,16,17" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-03 + type: integration + description: "Манифест указывает владельца-агента для каждого дока (analyst/architect/reviewer/tester/deployer/система упомянуты)" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-04 + type: integration + description: "Манифест содержит категории required / when-applicable / optional" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-05 + type: integration + description: "Каталог docs/_templates/ существует и содержит шаблоны для всех required/when-applicable доков" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-06 + type: integration + description: "Шаблон 12-review содержит frontmatter-ключ verdict:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-07 + type: integration + description: "Шаблон 13-test-report содержит frontmatter-ключ result:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-08 + type: integration + description: "Шаблон 14-deploy-log содержит frontmatter-ключ deploy_status:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-09 + type: integration + description: "Шаблон 15-staging-log содержит frontmatter-ключ staging_status:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-10 + type: integration + description: "Шаблон 17-security-report содержит frontmatter-ключ security_status:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-11 + type: integration + description: "Шаблон 16-post-deploy-log содержит frontmatter-ключ post_deploy_status:" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-12 + type: integration + description: "Шаблон 01-brd содержит обязательные секции: Бизнес-контекст, Объём, Бизнес-требования, NFR" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-13 + type: integration + description: "Шаблон 02-trz содержит обязательные секции: Задействованные модули, Изменения API, Изменения схемы БД, QG checks" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-14 + type: integration + description: "Шаблон 03-acceptance-criteria содержит блок AC-N с метками PASS и FAIL" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-15 + type: integration + description: "Шаблон 04-test-plan.yaml — валидный YAML с ключами work_item и tests (список с id/type/description/module/expected)" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-16 + type: integration + description: "Раздел ADR-naming присутствует и фиксирует формат ADR-NNN-<slug>.md с нумерацией с 001 и kebab-slug" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-17 + type: integration + description: "ADR-naming в стандарте совпадает с реальными ADR в репо (напр. существует docs/work-items/ORCH-088/06-adr/ADR-001-*.md)" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-18 + type: integration + description: "CLAUDE.md содержит ссылку на docs/_standards/PIPELINE_DOCS.md" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-19 + type: integration + description: "docs/architecture/README.md содержит ссылку на стандарт документов" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-20 + type: integration + description: "CHANGELOG.md содержит запись об ORCH-52b/ORCH-075 в разделе Unreleased" + module: tests/test_orch_52b_docs_standard.py + expected: PASS + + - id: TC-21 + type: integration + description: "Регресс: полный прогон pytest tests/ зелёный (docs-изменение не ломает существующие тесты)" + module: tests/ + expected: PASS diff --git a/docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md b/docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md new file mode 100644 index 0000000..14c28c2 --- /dev/null +++ b/docs/work-items/ORCH-075/06-adr/ADR-001-pipeline-docs-standard.md @@ -0,0 +1,160 @@ +# ADR-001: Стандарт документов пайплайна (docs/_standards + docs/_templates + ADR-naming) + +Work Item: **ORCH-075** (ORCH-52b — слой 1 эпика ORCH-52) +Стадия: **architecture** +Сквозная регистрация: **`docs/architecture/adr/adr-0019-pipeline-docs-standard.md`** (решение +кросс-каттинговое — задаёт правила доко-письма для ВСЕХ агентских ролей). + +## Статус +Proposed + +## Контекст +Агенты конвейера (`analyst → architect → developer → reviewer → tester → deployer` + системные +акторы deploy-finalizer / post-deploy-monitor / security-гейт) пишут номерные документы work item +(`00-business-request.md` … `17-security-report.md`) «с нуля по памяти». Каталогов +`docs/_standards/` и `docs/_templates/` не существует (проверено в репо). Следствия: + +- **Разнобой структуры** одного и того же документа от задачи к задаче (набор/порядок секций + плавает) — затрудняет ревью и онбординг новых ролей. +- **Риск рассинхрона машинных вердиктов.** Доки `12-review.md` / `13-test-report.md` / + `14-deploy-log.md` / `15-staging-log.md` / `17-security-report.md` несут frontmatter-ключ, + который читает гейт (`verdict:` / `result:` / `deploy_status:` / `staging_status:` / + `security_status:`), но единого канонического скелета с этим ключом нет → агент может выдать + ключ не того имени/регистра и уронить гейт ложно. +- **Нет карты «стадия → агент → документ → гейт».** Какая роль пишет какой документ и где он + проверяется — нигде не зафиксировано целостно. + +Эпик ORCH-52 намеренно разбит на слои: **сначала зафиксировать договорённость** (golden source +структуры доков), и лишь потом, отдельной задачей (52c), навесить машинную проверку +frontmatter/шаблонов на гейте. Слой 1 (эта задача) — **только документация**: манифест, +канонические шаблоны, конвенция ADR-naming. Любой валидатор/правка кода/правка промптов — вне +scope. Ключевое архитектурное ограничение задачи (NFR-1): **ни строки кода/гейтов** — изменения +строго под `docs/**` (+ `CLAUDE.md` / `CHANGELOG.md`). + +Ground-truth для манифеста — **фактические** `STAGE_TRANSITIONS` (`src/stages.py`), `QG_CHECKS` / +`check_*` (`src/qg/checks.py`), `src/stage_engine.py` и реальные эталонные доки (ORCH-088/073/089/071), +а не вымысел. Сверка проведена на стадии architecture (см. §Решение D5). + +## Решение + +### Сводка +Создать **документационный стандарт** из трёх артефактов, выведенный из фактического кода и +эталонных доков, и подключить его ссылками из точек-онбординга. Никаких рантайм-изменений. + +- `docs/_standards/PIPELINE_DOCS.md` — манифест-карта «стадия → документ → агент → категория → + гейт/механизм → frontmatter machine-key» + раздел ADR-naming. +- `docs/_templates/*` — копируемые скелеты для каждого `required` / `when-applicable` дока. +- Ссылки из `CLAUDE.md` и `docs/architecture/README.md`; запись в `CHANGELOG.md`. + +### D1 — Местоположение и разделение «стандарт» vs «шаблон» +Два каталога с раздельной ответственностью: `docs/_standards/` — **описательный** golden source +(манифест, конвенции, человекочитаемая карта); `docs/_templates/` — **копируемые** скелеты для +заполнения. Префикс `_` выводит служебные каталоги наверх листинга и визуально отделяет их от +`docs/work-items/` / `docs/architecture/` / `docs/operations/`. Шаблоны — НЕ work item, не имеют +`<plane-id>`, не парсятся гейтами (живут вне `docs/work-items/`), поэтому не влияют на +`check_architecture_done` / `check_analysis_complete` и не попадают под ретро-фит. + +### D2 — Манифест как производная от кода, а не параллельный источник истины +`PIPELINE_DOCS.md` **документирует** текущее поведение гейтов, но НЕ становится их источником +истины (источник остаётся `src/`). Это устраняет класс «манифест разошёлся с кодом»: при будущем +изменении гейта (ORCH-52c+) правка кода первична, манифест — следом. Манифест честно различает: +- **machine-verdict доки** (`12,13,14,15,17`) — несут frontmatter-ключ, читаемый гейтом; в + манифесте помечены ключом и именем `check_*`; +- **информационные доки** (`00,08,10,16`) — гейтом не парсятся; помечены явно как не-гейтящиеся + (чтобы не возникало ложного ожидания, что их структура что-то блокирует). + +Под-гейты ребра `deploy-staging → deploy` (`check_security_gate` → `check_branch_mergeable` → +`check_staging_image_fresh`) в манифесте отмечаются как **врезки в `advance_stage`**, а НЕ строки +`STAGE_TRANSITIONS` — иначе карта соврёт о топологии машины стадий (AC-7). + +### D3 — Шаблоны выведены из эталонов, новые секции не изобретаются +Скелеты извлекаются из реальных «golden» задач (ORCH-088/073/089/071) и текущей задачи ORCH-075. +Инвариант (NFR-3): **в шаблоне нет секции, которой никто не пишет в эталонах**, и наоборот — общий +канон секций эталона присутствует. Минимальный обязательный набор секций по каждому документу +зафиксирован в TRZ §FR-2.1 и является контрактом приёмки (AC-2/AC-4). Документы с машинным +вердиктом несут в шаблоне точный frontmatter-ключ из ground-truth таблицы (D5), чтобы скопированный +скелет проходил гейт без догадок. + +### D4 — ADR-naming: канонизация сложившейся традиции, не новый формат +Зафиксировать **уже существующий** формат, не вводя нового: +- Путь: `docs/work-items/<plane-id>/06-adr/`. +- Имя: `ADR-NNN-<kebab-slug>.md`; `NNN` с `001`, инкремент при нескольких ADR в одной задаче. +- `slug` — kebab-case (нижний регистр, дефисы), отражает суть решения. +- Кросс-каттинговые решения **дублируются** в глобальном реестре + `docs/architecture/adr/adr-NNNN-<slug>.md` (4-значная сквозная нумерация) — это уже действующая + конвенция (подтверждено: реестр идёт до `adr-0018`), лишь записывается. +- Примеры из репо (проверены): `ADR-001-serial-gate`, `ADR-001-auto-label-gates`, + `ADR-001-merge-verify-gate`. + +Сам этот ADR следует конвенции и дублируется как `adr-0019` — стандарт демонстрирует себя. + +### D5 — Достоверность: сверка манифеста с `src/` на стадии architecture (NFR-2) +Перед фиксацией манифеста ground-truth сверен с кодом. Подтверждено: + +| Документ | Гейт / механизм | Machine-key | Подтверждено в | +|----------|-----------------|-------------|----------------| +| `01–04` | `check_analysis_approved` (exit `analysis→architecture`); helper `check_analysis_complete` (наличие `01/02/03/04`) | — | `stages.py`, `qg/checks.py:check_analysis_complete` | +| `06-adr/` | `check_architecture_done` (наличие каталога `06-adr/` ≥1 файл ИЛИ `07-infra-requirements.md`) | — | `qg/checks.py:check_architecture_done` | +| `12-review.md` | `check_reviewer_verdict` | `verdict:` | `qg/checks.py` | +| `13-test-report.md` | `check_tests_passed` | `result:`/`verdict:`/`status:` (три равноранговых, ORCH-047) | `qg/checks.py:_parse_tests_verdict` | +| `14-deploy-log.md` | `check_deploy_status` | `deploy_status:` | `qg/checks.py:_parse_deploy_status` | +| `15-staging-log.md` | `check_staging_status` (self-hosting; иначе N/A — ORCH-35) | `staging_status:` | `qg/checks.py:_parse_staging_status` | +| `17-security-report.md` | `check_security_gate` (под-гейт ребра `deploy-staging→deploy`) | `security_status:` | `qg/checks.py` | +| `16-post-deploy-log.md` | информационный (пост-`done` наблюдение ORCH-021, не ребро) | `post_deploy_status:` (не гейтится) | `stage_engine.run_post_deploy_monitor` | +| `00/08/10` | не гейтятся (вход / информационные) | — | — | + +`STAGE_TRANSITIONS` (проверено): `analysis→architecture→development→review→testing→deploy-staging +→deploy→done`; рёбра несут ровно `check_analysis_approved / check_architecture_done / check_ci_green +/ check_reviewer_verdict / check_tests_passed / check_staging_status / check_deploy_status`. +Под-гейты `security/merge/image-freshness` в `STAGE_TRANSITIONS` **отсутствуют** (врезки в +`advance_stage`) — подтверждает D2. + +### D6 — Разграничение ответственности стадий (что пишет архитектор vs разработчик) +Эта стадия (architecture) производит **только** ADR + tech-risks (+ N/A infra/data). Сами артефакты +стандарта (`PIPELINE_DOCS.md`, `docs/_templates/*`) и правки точек-ссылок +(`CLAUDE.md` / `docs/architecture/README.md` / `CHANGELOG.md`) создаёт стадия development по TRZ §2 — +чтобы не было двойного авторства и конфликтов. Архитектор фиксирует **контракт** (что и где должно +появиться, по каким инвариантам), разработчик его **реализует**. + +## Альтернативы +- **Один файл-стандарт без каталога шаблонов** — отвергнуто: шаблон должен быть копируемым + отдельным файлом (UX «скопировал и заполнил», AC-2), а не вырезкой из прозы манифеста. +- **Сразу валидатор frontmatter на гейте** — отвергнуто намеренно (это ORCH-52c): нарушило бы + NFR-1 (правка кода/гейтов) и подняло бы групповой self-hosting риск без предварительной фиксации + договорённости. Слой «стандарт» обязан предшествовать слою «проверка». +- **Манифест как источник истины для гейтов** — отвергнуто: породило бы дубль-истину и класс + «манифест ≠ код». Источник остаётся `src/`; манифест — производная (D2). +- **Положить шаблоны в `docs/work-items/_template/`** — отвергнуто: попадание под `docs/work-items/` + с `<plane-id>`-семантикой риск-фактор для гейтов наличия файлов и сканеров; служебный каталог + должен быть вне дерева work item (D1). +- **Ретро-фит существующих доков под новый шаблон** — отвергнуто (вне scope, BRD §2.2): массовая + правка истории — отдельный риск и шум; стандарт применяется к новым задачам вперёд. +- **Не заводить глобальный `adr-0019`** — отвергнуто: решение кросс-каттинговое (правила + доко-письма для всех ролей), а FR-3 сам канонизирует дублирование сквозных решений в глобальный + реестр — стандарт обязан следовать собственному правилу. + +## Последствия +- **+** Единая карта «стадия → агент → документ → гейт → machine-key»; копируемые скелеты → + меньше разнобоя и ложных падений гейтов из-за неверного frontmatter-ключа; ADR-naming перестаёт + быть устной традицией; готовая база для ORCH-52c (валидатор). +- **+ Нулевой рантайм-риск (NFR-1/NFR-5):** изменения только под `docs/**` + `CLAUDE.md` + + `CHANGELOG.md`. `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / `src/stage_engine.py` / схема БД — + **не трогаются**. Удаление новых файлов полностью откатывает изменение без следов в поведении + системы (обратимость). +- **− Дрейф во времени:** манифест — снимок поведения гейтов; при будущей правке гейта его нужно + обновлять вручную (до ORCH-52c, где появится проверка). Митигейшн: D2 (источник истины — код) + + reviewer-правило «обновлена ли документация» + явная привязка манифеста к именам `check_*`. +- **−** Стандарт описательный, не принуждающий: агент может его проигнорировать (форсинг — 52c). + Осознанно принято как цена слоистого подхода. +- **Откат:** удалить `docs/_standards/PIPELINE_DOCS.md`, `docs/_templates/*`, снять ссылки и запись + CHANGELOG — система ведёт себя в точности как до ORCH-075. + +## Ссылки +- BRD: `docs/work-items/ORCH-075/01-brd.md` +- TRZ: `docs/work-items/ORCH-075/02-trz.md` (ground-truth таблица FR-1, секции FR-2.1) +- Acceptance: `docs/work-items/ORCH-075/03-acceptance-criteria.md` +- Tech-risks: `docs/work-items/ORCH-075/10-tech-risks.md` +- Глобальный реестр: `docs/architecture/adr/adr-0019-pipeline-docs-standard.md` +- Эталоны скелетов: ORCH-088 / ORCH-073 / ORCH-089 / ORCH-071 (`docs/work-items/*/`) +- Сверено по коду: `src/stages.py` (`STAGE_TRANSITIONS`), `src/qg/checks.py` (`QG_CHECKS`, + `_parse_*`), `src/stage_engine.py`. diff --git a/docs/work-items/ORCH-075/07-infra-requirements.md b/docs/work-items/ORCH-075/07-infra-requirements.md new file mode 100644 index 0000000..872cca2 --- /dev/null +++ b/docs/work-items/ORCH-075/07-infra-requirements.md @@ -0,0 +1,25 @@ +# 07 — Инфра-требования: ORCH-075 (ORCH-52b — стандарт документов) + +Work Item: **ORCH-075** · Repo: **orchestrator** · Стадия: architecture + +## I-1. Топология / окружения +**N/A.** Изменение docs-only: создаются `docs/_standards/PIPELINE_DOCS.md`, `docs/_templates/*` и +правятся `CLAUDE.md` / `docs/architecture/README.md` / `CHANGELOG.md`. Контейнеры (`orchestrator` +8500, `orchestrator-staging` 8501), Docker Compose, сеть, тома, хост mva154 — **не затрагиваются**. + +## I-2. Переменные окружения / секреты +**N/A.** Новые env-переменные не вводятся; `.env` / `.env.staging` / `.env.example` не меняются; +секретов не добавляется. + +## I-3. Деплой / рестарт +**N/A.** Рантайм-поведение не меняется → прод-рестарт не требуется. Изменение проходит штатный +self-hosting путь (`deploy-staging` 8501 → `deploy` 8500) как обычный PR, но эффект деплоя — лишь +появление новых docs-файлов в образе; функциональной нагрузки на рестарт нет. Self-hosting инвариант +соблюдён: **не ронять / не рестартить прод вне staging-гейта** — здесь это и не нужно. + +## I-4. CI/CD +Без изменений в `.gitea/workflows/`. Добавляется один тестовый файл +`tests/test_orch_52b_docs_standard.py` (структурные проверки), исполняемый существующим pytest-шагом. + +> Вывод: инфраструктурных требований нет. Файл создан для аудитопригодности (явное N/A), а не из-за +> изменения топологии. diff --git a/docs/work-items/ORCH-075/08-data-requirements.md b/docs/work-items/ORCH-075/08-data-requirements.md new file mode 100644 index 0000000..b869793 --- /dev/null +++ b/docs/work-items/ORCH-075/08-data-requirements.md @@ -0,0 +1,28 @@ +# 08 — Требования к данным: ORCH-075 (ORCH-52b — стандарт документов) + +Work Item: **ORCH-075** · Repo: **orchestrator** · Стадия: architecture + +## Изменения схемы БД +**N/A.** Изменение docs-only. Таблицы SQLite (`jobs`, `tasks`, `job_deps`, `repo_freeze`, +`agent_runs`, `tracker_messages`, …), индексы, миграции (`init_db`) — **не затрагиваются**. + +## Новые/изменённые сущности +**Нет.** Манифест и шаблоны — статические Markdown/YAML-файлы под `docs/`, вне модели данных +рантайма. Гейты наличия файлов (`check_analysis_complete` / `check_architecture_done`) сканируют +только `docs/work-items/<plane-id>/` и служебные каталоги `docs/_standards/` / `docs/_templates/` не +видят (см. ADR-001 §D1, риск TR-6). + +## Frontmatter machine-keys (документируются, не вводятся) +Стандарт лишь **фиксирует** уже существующие машиночитаемые ключи, которые парсят гейты — это НЕ +новые поля данных и не изменение хранения: + +| Документ | Ключ | Парсер (`src/qg/checks.py`) | +|----------|------|-----------------------------| +| `12-review.md` | `verdict:` | `check_reviewer_verdict` | +| `13-test-report.md` | `result:` / `verdict:` / `status:` | `_parse_tests_verdict` | +| `14-deploy-log.md` | `deploy_status:` | `_parse_deploy_status` | +| `15-staging-log.md` | `staging_status:` | `_parse_staging_status` | +| `17-security-report.md` | `security_status:` | `check_security_gate` | +| `16-post-deploy-log.md` | `post_deploy_status:` | информационный (не гейтится) | + +> Вывод: требований к данным/схеме нет. Файл создан для аудитопригодности (явное N/A). diff --git a/docs/work-items/ORCH-075/10-tech-risks.md b/docs/work-items/ORCH-075/10-tech-risks.md new file mode 100644 index 0000000..05a1b00 --- /dev/null +++ b/docs/work-items/ORCH-075/10-tech-risks.md @@ -0,0 +1,28 @@ +# 10 — Технические риски: ORCH-075 (ORCH-52b — стандарт документов) + +Work Item: **ORCH-075** · Repo: **orchestrator** · Стадия: architecture + +> Изменение docs-only (NFR-1): только `docs/**` + `CLAUDE.md` + `CHANGELOG.md`. Рантайм-рисков +> деградации прода нет по построению. Основные риски — **достоверность** манифеста и **дрейф** +> стандарта относительно кода. + +## Реестр рисков + +| ID | Риск | Вер. | Влия. | Митигейшн | +|----|------|------|-------|-----------| +| TR-1 | **Рассинхрон манифеста с кодом** — манифест приписывает доку неверную стадию/гейт/агента или неверный frontmatter-ключ (напр. `12-review` → не `verdict:`). | Сред. | Сред. (вводит агентов в заблуждение, ложные ожидания) | NFR-2: ground-truth сверен с `src/stages.py` / `src/qg/checks.py` / `src/stage_engine.py` на стадии architecture (ADR-001 §D5, таблица сверки). AC-4 проверяет привязку буквально по файлам. Источник истины остаётся код (D2). | +| TR-2 | **Дрейф во времени** — будущая правка гейта (ORCH-52c+) не отражается в манифесте, т.к. форсинга нет. | Сред. | Низ. (до 52c — описательный документ) | D2 (источник истины — код, манифест производный); reviewer-правило «обновлена ли документация»; явная привязка строк манифеста к именам `check_*`; ORCH-52c добавит машинную проверку. | +| TR-3 | **Шаблон вводит выдуманную секцию** или, наоборот, упускает секцию общего канона эталонов. | Сред. | Низ. | NFR-3: скелеты выведены строго из эталонов ORCH-088/073/089/071 + ORCH-075; TRZ §FR-2.1 фиксирует минимальный обязательный набор секций; AC-2/AC-4 проверяют. | +| TR-4 | **Неверный machine-key в шаблоне машинного дока** — скопированный скелет уронит гейт ложно (напр. `deploy_status` написан `Deploy-Status`/иной регистр). | Низ. | Выс. (если бы дошло до прода — ложный откат БАГ-8) | Ключи в шаблонах берутся ДОСЛОВНО из `_parse_*` (`deploy_status`/`staging_status`/`security_status`/`verdict`/`result`); парсеры делают `.upper()` на значении, но имя ключа чувствительно — шаблон фиксирует точное имя. AC-2 проверяет наличие ключа. Гейты при этом **не трогаются** (docs-only). | +| TR-5 | **Коллизия имени файла-шаблона ADR** с реальной нумерацией (`06-adr/ADR-NNN-…`). | Низ. | Низ. | TRZ §2: имя шаблона ADR без `<plane-id>`-контекста и вне `docs/work-items/` (напр. `docs/_templates/06-adr-ADR-NNN-slug.md`); внутри фиксируется реальный целевой путь/формат. | +| TR-6 | **Шаблоны парсятся гейтами наличия файлов** (`check_architecture_done` / `check_analysis_complete` ловят `docs/_templates/*`). | Оч.низ. | Сред. | D1: служебные каталоги `docs/_standards/` / `docs/_templates/` лежат ВНЕ `docs/work-items/<plane-id>/`; гейты сканируют только путь work item → шаблоны структурно невидимы гейтам. | +| TR-7 | **Регресс существующих тестов** от docs-изменения. | Оч.низ. | Сред. | Изменения не трогают `src/`; новый тест `tests/test_orch_52b_docs_standard.py` — только структурные проверки наличия/секций; TC-21 требует зелёного полного `pytest tests/`. | +| TR-8 | **CHANGELOG-конфликт при merge** (`## [Unreleased]` правят параллельные задачи). | Низ. | Низ. | Корневой `.gitattributes` `CHANGELOG.md merge=union` (ORCH-073 FR-4) авто-сливает append-правки без конфликта. | + +## Сводный вывод +Риск для прод-конвейера (self-hosting) — **отсутствует по построению**: изменение docs-only, +полностью обратимо (NFR-5), `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / схема БД не затрагиваются +(AC-6). Доминирующий класс рисков — **достоверность и дрейф** манифеста (TR-1/TR-2); закрыт сверкой +с `src/` на стадии architecture (ADR-001 §D5) и принципом «источник истины — код, манифест — +производная». Эскалация `arch:major-change` не требуется (нет новой стадии/QG/компонента/смены БД). +Возврат в анализ не требуется — ТЗ удовлетворяется без нарушения принципов архитектуры. diff --git a/docs/work-items/ORCH-075/12-review.md b/docs/work-items/ORCH-075/12-review.md new file mode 100644 index 0000000..bb020fb --- /dev/null +++ b/docs/work-items/ORCH-075/12-review.md @@ -0,0 +1,71 @@ +--- +type: review +work_item_id: ORCH-075 +verdict: APPROVED +version: 1 +--- + +# Review ORCH-075 — ORCH-52b: стандарт документов конвейера + +## Summary +Docs-only задача: создан golden source структуры номерных документов (`docs/_standards/PIPELINE_DOCS.md`), +15 копируемых шаблонов (`docs/_templates/*`), зафиксирована конвенция ADR-naming, заведён сквозной +ADR `adr-0019`, обновлены точки-ссылки (CLAUDE.md, architecture/README.md, CHANGELOG.md). +Манифест и шаблоны **сверены с фактическим кодом** — соответствие подтверждено. Все 7 критериев +приёмки выполнены. P0/P1/P2 findings нет → **APPROVED**. + +## Оси проверки + +### 1. Соответствие ТЗ (02-trz.md) +- FR-1 (манифест) — таблица покрывает весь реальный набор `00/01/02/03/04/06/07/08/10/12/13/14/15/16/17`, + колонки владелец/категория/стадия/гейт/machine-key присутствуют. ✓ +- FR-2 (шаблоны) — все 15 шаблонов созданы; секции совпадают с FR-2.1 (спот-чек 01-brd, 02-trz, + 06-adr, 04-test-plan). ✓ +- FR-3 (ADR-naming) — §4 фиксирует путь, `ADR-NNN-<kebab-slug>`, связь с глобальным реестром, примеры. ✓ +- FR-4 (точки-ссылки) — CLAUDE.md (раздел «Артефакты задачи» + правило 2), README §«Стандарт + документов конвейера», CHANGELOG `## [Unreleased]` (`docs`-тип). ✓ + +### 2. Соответствие ADR (06-adr/ADR-001 + adr-0019) +- D2 «манифест документирует, источник истины — код» отражён в самом манифесте (блок «Статус истины»). ✓ +- D5 ground-truth сверка соответствует тому, что реально читает код (проверено независимо). ✓ +- Стандарт следует собственной конвенции (заведён `adr-0019`). ✓ + +### 3. Качество кода (docs-only) — сверка с `src/` +Независимо подтверждено по источнику истины: +- `STAGE_TRANSITIONS` (`src/stages.py`) — рёбра и exit-гейты совпадают с манифестом 1:1. +- Frontmatter-ключи совпадают с парсерами: `verdict:`→`check_reviewer_verdict`; `result:`/`verdict:`/ + `status:`→`_parse_tests_verdict`; `deploy_status:`→`_parse_deploy_status`; `staging_status:`→ + `_parse_staging_status`; `security_status:`→`check_security_gate`/`security_gate.py`. +- `check_analysis_complete` (01/02/03/04) и `check_architecture_done` (06-adr ≥1 файл ИЛИ 07-infra) — + формулировки манифеста точны. +- Под-гейты ребра `deploy-staging→deploy` корректно помечены как врезки в `advance_stage`, не строки + `STAGE_TRANSITIONS` (AC-7). +- AC-6: `git diff` по `src/` пуст — код/гейты/схема БД не тронуты. + +### 4. Качество тестов +`tests/test_orch_52b_docs_standard.py` — 20 содержательных структурных тестов (наличие манифеста, +покрытие всех доков, владельцы/категории, frontmatter-ключи каждого машинного шаблона, ADR-naming +против реального репо, валидность YAML тест-плана, точки-ссылки, CHANGELOG). Прогон: **20 passed**. + +## Findings + +### P0 — Blocker +- нет + +### P1 — Must fix +- нет + +### P2 — Should fix +- нет + +### P3 — Nice-to-have +- [ ] В `06-adr/ADR-001` §D4 формулировка «реестр идёт до `adr-0018`» описывает состояние ДО добавления + текущего `adr-0019` (что верно), тогда как `PIPELINE_DOCS.md` §4 говорит «доходит до `adr-0019`». + Несоответствие безвредно (разные срезы времени), правка не требуется. + +## Документация +Это docs-only задача — документация **является** деливерейблом. `src/` не изменён, поэтому правило +CLAUDE.md «изменил src → обнови доку» неприменимо в блокирующем смысле. Сама документация проверена на +достоверность против кода (`src/stages.py`, `src/qg/checks.py`, `src/security_gate.py`) и эталонных +доков — расхождений нет. Точки-онбординга (CLAUDE.md, architecture/README.md) и CHANGELOG обновлены. +Статус документации: **полностью обновлена и верифицирована**. diff --git a/docs/work-items/ORCH-075/13-test-report.md b/docs/work-items/ORCH-075/13-test-report.md new file mode 100644 index 0000000..49744e0 --- /dev/null +++ b/docs/work-items/ORCH-075/13-test-report.md @@ -0,0 +1,85 @@ +--- +type: test-report +work_item_id: ORCH-075 +result: PASS +--- + +# Test Report — ORCH-075 (ORCH-52b: стандарт документов конвейера) + +## Окружение +- Python: 3.12.13 +- pytest: 8.3.3 +- Дата: 2026-06-09 +- Ветка: `feature/ORCH-075-orch-52b-docs-templates-adr-na` +- Prod health (`http://localhost:8500/health`): `{"status":"ok","service":"orchestrator"}` +- Review verdict (12-review.md): **APPROVED** (предусловие выполнено) + +## Smoke-тест API (read-only, прод не трогался) +| Endpoint | Результат | +|----------|-----------| +| `GET /health` | `{"status":"ok","service":"orchestrator"}` — OK | +| `GET /status` | OK — активная задача ORCH-075 (id 68) на стадии `testing` | +| `GET /queue` | OK — counts {running:1, done:871, failed:4}, breaker `closed`, reconcile/reaper enabled | + +## Результаты + +### Полный регресс +`python -m pytest tests/ -q` → **1177 passed, 1 warning in 38.08s** (warning — Pydantic V2 deprecation в `src/config.py`, не относится к задаче). Регресса от docs-изменения нет. + +### Профильная сюита +`python -m pytest tests/test_orch_52b_docs_standard.py -v` → **20 passed in 0.39s**. + +### Сопоставление с тест-планом (04-test-plan.yaml) + +| TC ID | Описание | Результат | +|-------|----------|-----------| +| TC-01 | PIPELINE_DOCS.md существует и непустой | PASS | +| TC-02 | Манифест упоминает все номерные доки (00..17) | PASS | +| TC-03 | Манифест указывает владельца-агента для каждого дока | PASS | +| TC-04 | Манифест содержит категории required/when-applicable/optional | PASS | +| TC-05 | docs/_templates/ содержит шаблоны всех required/when-applicable доков | PASS | +| TC-06 | Шаблон 12-review содержит `verdict:` | PASS | +| TC-07 | Шаблон 13-test-report содержит `result:` | PASS | +| TC-08 | Шаблон 14-deploy-log содержит `deploy_status:` | PASS | +| TC-09 | Шаблон 15-staging-log содержит `staging_status:` | PASS | +| TC-10 | Шаблон 17-security-report содержит `security_status:` | PASS | +| TC-11 | Шаблон 16-post-deploy-log содержит `post_deploy_status:` | PASS | +| TC-12 | Шаблон 01-brd содержит обязательные секции | PASS | +| TC-13 | Шаблон 02-trz содержит обязательные секции | PASS | +| TC-14 | Шаблон 03-acceptance-criteria содержит блок AC-N с PASS/FAIL | PASS | +| TC-15 | Шаблон 04-test-plan.yaml — валидный YAML с work_item/tests | PASS | +| TC-16 | Раздел ADR-naming фиксирует формат ADR-NNN-<slug>.md (с 001, kebab) | PASS | +| TC-17 | ADR-naming совпадает с реальными ADR в репо | PASS | +| TC-18 | CLAUDE.md ссылается на docs/_standards/PIPELINE_DOCS.md | PASS | +| TC-19 | docs/architecture/README.md ссылается на стандарт | PASS | +| TC-20 | CHANGELOG.md содержит запись ORCH-52b/ORCH-075 в Unreleased | PASS | +| TC-21 | Регресс: полный прогон pytest tests/ зелёный | PASS | + +### Сопоставление с критериями приёмки (03-acceptance-criteria.md) + +| AC | Критерий | Результат | +|----|----------|-----------| +| AC-1 | Манифест создан, покрывает весь набор + владелец/категория | PASS (TC-01..04) | +| AC-2 | Шаблоны для каждого required/when-applicable + frontmatter-ключи + секции | PASS (TC-05..14) | +| AC-3 | ADR-naming зафиксирован | PASS (TC-16) | +| AC-4 | Согласованность с эталонами и кодом | PASS (TC-15,17; reviewer сверил с src/) | +| AC-5 | Ссылки + CHANGELOG обновлены | PASS (TC-18..20) | +| AC-6 | Код гейтов НЕ изменён (docs-only) | PASS — `git diff origin/main...HEAD -- src/` пуст; затронуты только `docs/**`, `CLAUDE.md`, `CHANGELOG.md`, `tests/test_orch_52b_docs_standard.py` | +| AC-7 | Манифест различает machine-verdict и информационные доки | PASS (reviewer подтвердил врезки `advance_stage` и разметку гейтов) | + +## Вывод pytest +``` +........................................................................ [ 97%] +......................... [100%] +=============================== warnings summary =============================== +src/config.py:5: PydanticDeprecatedSince20: ... +1177 passed, 1 warning in 38.08s +``` +``` +tests/test_orch_52b_docs_standard.py — 20 passed, 1 warning in 0.39s +``` + +## Итог +**PASS** — полный регресс зелёный (1177 passed), профильная сюита зелёная (20 passed), +smoke API OK, изменение строго docs-only (AC-6 подтверждён: `src/` не тронут). +Задача готова к стадии `deploy-staging`. diff --git a/docs/work-items/ORCH-075/14-deploy-log.md b/docs/work-items/ORCH-075/14-deploy-log.md new file mode 100644 index 0000000..52c494f --- /dev/null +++ b/docs/work-items/ORCH-075/14-deploy-log.md @@ -0,0 +1,12 @@ +--- +deploy_status: SUCCESS +work_item: ORCH-075 +hook_exit_code: 0 +deployed_by: deploy-finalizer +--- + +# Deploy log — ORCH-036 executable self-deploy + +Прод-деплой завершён хост-хуком с exit-code `0` -> `deploy_status: SUCCESS`. + +Вердикт зафиксирован детерминированным finalizer'ом (Фаза C), не LLM. diff --git a/tests/test_orch_52b_docs_standard.py b/tests/test_orch_52b_docs_standard.py new file mode 100644 index 0000000..2e62ef5 --- /dev/null +++ b/tests/test_orch_52b_docs_standard.py @@ -0,0 +1,214 @@ +"""ORCH-075 (ORCH-52b) — структурные проверки стандарта документов конвейера. + +Docs-only задача: проверяется НАЛИЧИЕ и СТРУКТУРА новых файлов-стандартов/шаблонов +(`docs/_standards/PIPELINE_DOCS.md`, `docs/_templates/*`) и обновление точек-ссылок +(`CLAUDE.md`, `docs/architecture/README.md`, `CHANGELOG.md`). Тесты НЕ меняют +`QG_CHECKS`/`STAGE_TRANSITIONS` и не вводят новый гейт (это ORCH-52c). + +Покрытие тест-плана 04-test-plan.yaml: TC-01…TC-20 (TC-21 — полный регресс `pytest tests/`). +""" + +from pathlib import Path + +import yaml + +REPO_ROOT = Path(__file__).resolve().parents[1] +STANDARDS = REPO_ROOT / "docs" / "_standards" +TEMPLATES = REPO_ROOT / "docs" / "_templates" +MANIFEST = STANDARDS / "PIPELINE_DOCS.md" + +# Все номерные доки реального набора (TRZ §FR-1, AC-1). +NUMBERED_DOCS = ["00", "01", "02", "03", "04", "06", "07", "08", "10", + "12", "13", "14", "15", "16", "17"] + +# Шаблоны required/when-applicable доков (TRZ §2, AC-2). +TEMPLATE_FILES = [ + "00-business-request.md", + "01-brd.md", + "02-trz.md", + "03-acceptance-criteria.md", + "04-test-plan.yaml", + "06-adr-ADR-NNN-slug.md", + "07-infra-requirements.md", + "08-data-requirements.md", + "10-tech-risks.md", + "12-review.md", + "13-test-report.md", + "14-deploy-log.md", + "15-staging-log.md", + "16-post-deploy-log.md", + "17-security-report.md", +] + + +def _read(path: Path) -> str: + return path.read_text(encoding="utf-8") + + +# --- TC-01 ----------------------------------------------------------------- +def test_tc01_manifest_exists_and_nonempty(): + """docs/_standards/PIPELINE_DOCS.md существует и непустой.""" + assert MANIFEST.is_file(), f"манифест не найден: {MANIFEST}" + assert len(_read(MANIFEST).strip()) > 0, "манифест пустой" + + +# --- TC-02 ----------------------------------------------------------------- +def test_tc02_manifest_mentions_all_numbered_docs(): + """Манифест упоминает все номерные доки набора.""" + content = _read(MANIFEST) + missing = [] + for num in NUMBERED_DOCS: + # Документ упоминается как `NN-...` или `NN-adr` — ищем по префиксу `NN-`. + if f"{num}-" not in content: + missing.append(num) + assert not missing, f"в манифесте не упомянуты доки: {missing}" + + +# --- TC-03 ----------------------------------------------------------------- +def test_tc03_manifest_lists_owner_agents(): + """Манифест указывает владельцев-агентов конвейера (TC-03: analyst/architect/ + reviewer/tester/deployer/система). `developer` не владеет номерным доком — пишет код+PR.""" + content = _read(MANIFEST).lower() + for agent in ["analyst", "architect", "reviewer", "tester", "deployer"]: + assert agent in content, f"в манифесте нет владельца-агента: {agent}" + assert "систем" in content, "в манифесте нет системного владельца (Plane webhook)" + + +# --- TC-04 ----------------------------------------------------------------- +def test_tc04_manifest_has_categories(): + """Манифест содержит категории required / when-applicable / optional.""" + content = _read(MANIFEST) + for category in ["required", "when-applicable", "optional"]: + assert category in content, f"в манифесте нет категории: {category}" + + +# --- TC-05 ----------------------------------------------------------------- +def test_tc05_templates_dir_has_all_templates(): + """docs/_templates/ существует и содержит шаблоны для всех required/when-applicable доков.""" + assert TEMPLATES.is_dir(), f"каталог шаблонов не найден: {TEMPLATES}" + missing = [name for name in TEMPLATE_FILES if not (TEMPLATES / name).is_file()] + assert not missing, f"отсутствуют шаблоны: {missing}" + + +# --- TC-06..TC-11 — frontmatter machine-keys ------------------------------- +def _assert_frontmatter_key(template_name: str, key: str): + content = _read(TEMPLATES / template_name) + assert content.lstrip().startswith("---"), f"{template_name}: нет YAML-frontmatter" + head = content.split("---", 2) + assert len(head) >= 3, f"{template_name}: frontmatter не закрыт" + assert f"{key}:" in head[1], f"{template_name}: нет machine-key `{key}:` во frontmatter" + + +def test_tc06_review_template_has_verdict(): + """Шаблон 12-review содержит frontmatter-ключ verdict:.""" + _assert_frontmatter_key("12-review.md", "verdict") + + +def test_tc07_test_report_template_has_result(): + """Шаблон 13-test-report содержит frontmatter-ключ result:.""" + _assert_frontmatter_key("13-test-report.md", "result") + + +def test_tc08_deploy_log_template_has_deploy_status(): + """Шаблон 14-deploy-log содержит frontmatter-ключ deploy_status:.""" + _assert_frontmatter_key("14-deploy-log.md", "deploy_status") + + +def test_tc09_staging_log_template_has_staging_status(): + """Шаблон 15-staging-log содержит frontmatter-ключ staging_status:.""" + _assert_frontmatter_key("15-staging-log.md", "staging_status") + + +def test_tc10_security_report_template_has_security_status(): + """Шаблон 17-security-report содержит frontmatter-ключ security_status:.""" + _assert_frontmatter_key("17-security-report.md", "security_status") + + +def test_tc11_post_deploy_template_has_post_deploy_status(): + """Шаблон 16-post-deploy-log содержит frontmatter-ключ post_deploy_status:.""" + _assert_frontmatter_key("16-post-deploy-log.md", "post_deploy_status") + + +# --- TC-12 ----------------------------------------------------------------- +def test_tc12_brd_template_has_mandatory_sections(): + """Шаблон 01-brd содержит обязательные секции (TRZ §FR-2.1).""" + content = _read(TEMPLATES / "01-brd.md") + for section in ["Бизнес-контекст", "Объём", "Бизнес-требования", "Нефункциональные требования"]: + assert section in content, f"01-brd: нет секции `{section}`" + + +# --- TC-13 ----------------------------------------------------------------- +def test_tc13_trz_template_has_mandatory_sections(): + """Шаблон 02-trz содержит обязательные секции (TRZ §FR-2.1).""" + content = _read(TEMPLATES / "02-trz.md") + for section in ["Задействованные модули", "Изменения API", "Изменения схемы БД", + "QG checks"]: + assert section in content, f"02-trz: нет секции `{section}`" + + +# --- TC-14 ----------------------------------------------------------------- +def test_tc14_ac_template_has_pass_fail_block(): + """Шаблон 03-acceptance-criteria содержит блок AC-N с метками PASS и FAIL.""" + content = _read(TEMPLATES / "03-acceptance-criteria.md") + assert "AC-1" in content, "03-ac: нет блока AC-N" + assert "**PASS:**" in content, "03-ac: нет метки PASS" + assert "**FAIL:**" in content, "03-ac: нет метки FAIL" + + +# --- TC-15 ----------------------------------------------------------------- +def test_tc15_test_plan_template_is_valid_yaml(): + """Шаблон 04-test-plan.yaml — валидный YAML с work_item и списком tests.""" + data = yaml.safe_load(_read(TEMPLATES / "04-test-plan.yaml")) + assert isinstance(data, dict), "04-test-plan: корень не словарь" + assert "work_item" in data, "04-test-plan: нет ключа work_item" + assert isinstance(data.get("tests"), list) and data["tests"], "04-test-plan: tests не список" + first = data["tests"][0] + for key in ["id", "type", "description", "module", "expected"]: + assert key in first, f"04-test-plan: в элементе tests нет ключа `{key}`" + + +# --- TC-16 ----------------------------------------------------------------- +def test_tc16_adr_naming_section_present(): + """Раздел ADR-naming фиксирует формат ADR-NNN-<slug>.md с нумерацией с 001 и kebab-slug.""" + content = _read(MANIFEST) + assert "ADR-NNN-" in content, "нет формата ADR-NNN-<slug>.md" + assert "06-adr" in content, "нет пути 06-adr/" + assert "001" in content, "не зафиксирована нумерация с 001" + assert "kebab" in content.lower(), "нет правила kebab-case для slug" + + +# --- TC-17 ----------------------------------------------------------------- +def test_tc17_adr_naming_matches_real_repo(): + """ADR-naming совпадает с реальными ADR в репо (пример из манифеста существует).""" + # Манифест приводит ORCH-088 как пример; реальный файл должен существовать. + adr_dir = REPO_ROOT / "docs" / "work-items" / "ORCH-088" / "06-adr" + real = list(adr_dir.glob("ADR-001-*.md")) + assert real, f"реальный ADR-001-*.md не найден в {adr_dir}" + # И глобальный реестр следует 4-значной конвенции. + global_adr = REPO_ROOT / "docs" / "architecture" / "adr" + assert list(global_adr.glob("adr-0019-*.md")), "глобальный adr-0019-*.md не найден" + + +# --- TC-18 ----------------------------------------------------------------- +def test_tc18_claude_md_links_standard(): + """CLAUDE.md содержит ссылку на docs/_standards/PIPELINE_DOCS.md.""" + content = _read(REPO_ROOT / "CLAUDE.md") + assert "docs/_standards/PIPELINE_DOCS.md" in content + + +# --- TC-19 ----------------------------------------------------------------- +def test_tc19_architecture_readme_links_standard(): + """docs/architecture/README.md содержит ссылку на стандарт документов.""" + content = _read(REPO_ROOT / "docs" / "architecture" / "README.md") + assert "PIPELINE_DOCS.md" in content + + +# --- TC-20 ----------------------------------------------------------------- +def test_tc20_changelog_mentions_task(): + """CHANGELOG.md содержит запись об ORCH-52b/ORCH-075 в разделе Unreleased.""" + content = _read(REPO_ROOT / "CHANGELOG.md") + unreleased = content.split("## [Unreleased]", 1) + assert len(unreleased) == 2, "нет раздела ## [Unreleased]" + # Берём срез до следующего релизного заголовка, если он есть. + body = unreleased[1].split("\n## ", 1)[0] + assert "ORCH-075" in body or "ORCH-52b" in body, "в Unreleased нет записи ORCH-075/ORCH-52b"