From 13739c0b47a4d3ed270de8d00ecefd5154ad08c4 Mon Sep 17 00:00:00 2001 From: claude-bot Date: Wed, 10 Jun 2026 03:17:22 +0300 Subject: [PATCH] analyst(ET): auto-commit from analyst run_id=557 --- docs/work-items/ORCH-019/01-brd.md | 178 +++++++++++++++ docs/work-items/ORCH-019/02-trz.md | 207 ++++++++++++++++++ .../ORCH-019/03-acceptance-criteria.md | 139 ++++++++++++ docs/work-items/ORCH-019/04-test-plan.yaml | 111 ++++++++++ 4 files changed, 635 insertions(+) create mode 100644 docs/work-items/ORCH-019/01-brd.md create mode 100644 docs/work-items/ORCH-019/02-trz.md create mode 100644 docs/work-items/ORCH-019/03-acceptance-criteria.md create mode 100644 docs/work-items/ORCH-019/04-test-plan.yaml diff --git a/docs/work-items/ORCH-019/01-brd.md b/docs/work-items/ORCH-019/01-brd.md new file mode 100644 index 0000000..9e3f1b2 --- /dev/null +++ b/docs/work-items/ORCH-019/01-brd.md @@ -0,0 +1,178 @@ +--- +work_item: ORCH-019 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-10 +model_used: claude-opus-4-8 +--- + +# 01 — BRD (бизнес-требования): ORCH-019 — Режим багфиксинга (упрощённый/дешёвый трек для багов) + +Work Item: **ORCH-019** · Repo: **orchestrator** (self-hosting) · Стадия: analysis +Заказчик: Слава · Тип: фича (новый режим конвейера, опциональный, под флагом) + +> ⚠️ **Принцип, заданный Владельцем (нерушимый):** упрощаем **аналитику**, но **НЕ ослабляем +> качество**. Гейты CI / review / tester verdict / deploy verdict **остаются**. Горький урок +> ET-8 / BUG-TESTS-SUBSTRING: срезанная *проверка* = недоделка на проде. «Дешевле ≠ +> бесконтрольнее». Этот принцип — корневой инвариант всей задачи (см. NFR-1, BR-6). + +--- + +## 1. Бизнес-контекст и проблема + +### 1.1. Цель +Дать оркестратору **отдельный удешевлённый трек для багфиксов**. Сейчас любой баг (пример: +зашёл на карту enduro-trails, увидел дефект, завёл задачу) идёт по **полному** конвейеру +`analysis → architecture → development → review → testing → deploy-staging → deploy`. Для мелкой +правки полный цикл **избыточен**: лишние стадии (полный BRD/TRZ/AC + архитектурный ADR) тратят +токены и время, не добавляя ценности на однострочном фиксе. + +### 1.2. Установленные факты (проверено по коду, не изобретать) +- **Точка входа задачи в конвейер:** `src/webhooks/plane.py::start_pipeline` создаёт task-row + с **жёстко зашитой** начальной стадией `"analysis"` (`create_task_atomic(..., "analysis", ...)`) + и режет ветку (`_create_gitea_branch`). Это единственная точка, где задаётся точка входа. +- **Маршрутизация стадий полностью управляется** `src/stages.py::STAGE_TRANSITIONS` через + `get_next_stage` — `advance_stage` (`src/stage_engine.py`) не содержит «зашитого» порядка стадий, + он спрашивает `get_next_stage`. → Изменение точки входа / маршрута локализуемо, машину стадий + ломать не нужно. +- **Метка задачи уже читается из Plane** аппаратом ORCH-089: `src/labels.py::has_label` + + `plane_sync.fetch_issue_labels` / `get_project_labels` (TTL-кэш, нормализация имени, never-raise, + fail-safe → False). Источник истины — Plane API, **не** payload вебхука (`type`/`priority` в + payload отсутствуют). Это готовый, проверенный шаблон классификации задачи. +- **Все Quality Gate'ы читают вердикт из артефактов**, а не из стадии входа: `check_ci_green`, + `check_reviewer_verdict` (`12-review.md`), `check_tests_passed` (`13-test-report.md`), + `check_staging_status`, `check_deploy_status`, под-гейты security/merge/coverage/image-freshness. + Они **не зависят** от того, прошла ли задача `analysis`/`architecture`, → их можно сохранить + нетронутыми при срезанном «входе». +- **Coverage-гейт (ORCH-027)** уже структурно ловит «код без тестов» на ребре + `deploy-staging → deploy` — союзник принципа «баг фиксируется тестом». +- **Прецедент стоимости:** UI z-index баг ET-9/ET-014 прошёл **полный** цикл ~35 мин — типичный + кандидат на удешевление. + +### 1.3. Связки и разграничение +- **ORCH-13 (роутинг моделей):** «дешёвая модель на багфиксе» (Вариант 4 постановки) — + **вне объёма** ORCH-019, отдельная задача; ORCH-019 лишь оставляет точку композиции + (флаг bug-track наблюдаем, по нему ORCH-13 позже может выбрать модель). См. §2.2. +- **ORCH-088 (serial gate) / ORCH-089 (auto-label):** ORCH-019 **сосуществует** с ними и + переиспользует их аппарат (label-чтение, per-repo flag, claim-gate); не конфликтует. +- **ORCH-12 / ORCH-14 (UX) / ET-9 (визуальные баги):** часть багов визуальные и может требовать + мини-макета — для таких случаев предусмотрен механизм **эскалации обратно в полный цикл** + (BR-5), а не слепое удешевление. +- **ORCH-8 (петля уроков):** баг, найденный на проде, — сигнал петли уроков; ORCH-019 этого не + меняет (post-deploy-телеметрия ORCH-021 сохраняется). + +--- + +## 2. Объём (scope) + +### 2.1. В объёме +- **BR-1 — Классификация «баг».** Задача распознаётся как баг по **метке Plane** (рекоменд. имя + `Bug`), читаемой аппаратом ORCH-089. Операторская, детерминированная, обратимая разметка. +- **BR-2 — Упрощённый трек.** Багфикс-задача идёт по **укороченному** пути: пропускается + **тяжёлая аналитика и стадия `architecture`** (полный BRD/TRZ/AC/ADR не требуются); вместо них — + **минимальный набор артефактов** (короткий bug-report + обязательный план регресс-теста). +- **BR-3 — Гейты качества сохраняются ПОЛНОСТЬЮ.** CI (`check_ci_green`), review + (`check_reviewer_verdict`), testing (`check_tests_passed`), staging/deploy-вердикты и под-гейты + (security/merge/coverage/image-freshness) исполняются **без изменений** на багфикс-треке. +- **BR-4 — Обязательный регресс-тест.** Багфикс **обязан** зафиксировать дефект тестом (тест, + падающий до фикса и зелёный после) — главный предохранитель от рецидива (урок ET-8). +- **BR-5 — Эскалация в полный цикл.** Если баг оказался сложным/архитектурным или визуальным + (нужен макет), он **возвращается** в полный цикл; багфикс-трек не «застревает» на сложном. +- **BR-6 — Безопасность по умолчанию (fail-safe → полный цикл).** Любая неоднозначность/ошибка + чтения метки/выключенный флаг → задача идёт **полным** циклом (никогда не «теряет» стадии молча). +- **BR-7 — Наблюдаемость стоимости.** Виден факт «задача на багфикс-треке» и метрика экономии + (стадии/agent-runs/токены/время) относительно полного цикла. + +### 2.2. Вне объёма (явно не делать) +- **Роутинг моделей (ORCH-13 / Вариант 4):** выбор дешёвой модели на багфиксе — отдельная задача. +- **Авто-триаж сложности аналитиком (полный Вариант 3):** автоматическая classification + `trivial/small/complex` LLM-аналитиком — будущее развитие; v1 опирается на явную метку оператора + + ручную/мини-эскалацию (BR-5), не на ML-классификатор. +- **Изменение `STAGE_TRANSITIONS` (новые стадии), реестра `QG_CHECKS`, семантики любого `check_*`, + вердикт-ключей** (`verdict:`/`result:`/`deploy_status:`/`staging_status:`/`security_status:`/ + `coverage_status:`). +- **Параллелизм багфиксов**, изменение `max_concurrency`, merge-очередь. +- **Полный отказ от стадии `analysis`** (вариант «hotfix → сразу development») как дефолт — см. + §6 (требуется минимальный аналитический проход ради регресс-теста и трассируемости). Чистый + hotfix без аналитики оставлен как возможная опция архитектора, но не дефолт. + +--- + +## 3. Заинтересованные стороны +- **Владелец/оператор (Слава):** ставит метку `Bug`, получает быстрый дешёвый фикс, эскалирует + сложный баг, читает метрику экономии. +- **Self-hosting прод (`orchestrator`) и enduro-trails:** общий инстанс/БД/очередь — режим обязан + быть аддитивным, под флагом, per-repo, с нулевой регрессией при выключении (FR-условие). +- **Агенты конвейера (analyst/developer/reviewer/tester):** работают по тем же контрактам; на + багфикс-треке analyst выдаёт облегчённый пакет, остальные — как обычно. + +--- + +## 4. Бизнес-требования (BR) — сводная таблица + +| ID | Требование | Связь | +|----|------------|-------| +| BR-1 | Задача распознаётся как баг по метке Plane (`Bug`), читаемой через аппарат ORCH-089 (`labels.has_label` + `plane_sync.fetch_issue_labels`). Источник истины — Plane API, не payload. | FR-1, AC-1 | +| BR-2 | Багфикс-задача пропускает тяжёлую аналитику и стадию `architecture`; маршрут `analysis(lite) → development → review → testing → deploy-staging → deploy`. Полный BRD/TRZ/AC/ADR не обязателен. | FR-2, AC-2 | +| BR-3 | Все Quality Gate'ы (CI/review/tester/staging/deploy + под-гейты security/merge/coverage/image-freshness) исполняются на багфикс-треке **без изменений**. | FR-3, AC-3 | +| BR-4 | Багфикс обязан содержать **регресс-тест** (падает до фикса, зелён после); отсутствие нового/изменённого теста на исправление — повод для REQUEST_CHANGES reviewer'ом. | FR-3/FR-4, AC-4 | +| BR-5 | Существует механизм **эскалации** багфикса в полный цикл (сложный/архитектурный/визуальный баг) — задача возвращается на полную аналитику/архитектуру. | FR-5, AC-5 | +| BR-6 | **Fail-safe:** при выключенном флаге, ошибке/неоднозначности чтения метки, неприменимом репо — задача идёт **полным** циклом (никогда не теряет стадии молча). never-raise. | FR-6, AC-6 | +| BR-7 | Факт багфикс-трека и метрика экономии (пропущенные стадии / Σ agent-runs / токены / время vs полный цикл) наблюдаемы (`GET /queue` блок + лог/Telegram-карточка). | FR-7, AC-7 | +| BR-8 | Поведение управляется kill-switch'ом и областью репо (как ORCH-35/43/58/88/89): выключение флага → строго прежнее поведение (нулевая регрессия для enduro и для orchestrator). | NFR-2, AC-6 | + +--- + +## 5. Нефункциональные требования (NFR) + +| ID | Требование | +|----|------------| +| NFR-1 | **Качество не ослабляется (корневой инвариант).** Срезается только *аналитика/архитектура*; ни один Quality Gate, exit-код deploy-хука, под-гейт безопасности/покрытия — не ослаблен и не пропущен. | +| NFR-2 | **Нулевая регрессия / аддитивность.** При `bug_fast_track_enabled=False` или неприменимом репо путь старта и маршрут идентичны текущим. `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/вердикт-ключи/схема БД — не меняются (допустима лишь аддитивная идемпотентная миграция, если архитектор сочтёт нужным помечать тип задачи в БД). | +| NFR-3 | **never-raise / fail-safe.** Любая ошибка классификации/маршрутизации → деградация на полный цикл, не падение вебхука/конвейера (по образцу `labels.py`/`serial_gate.py`). | +| NFR-4 | **Offline-устойчивость горячего пути.** Классификация может ходить в Plane API только в момент `start_pipeline` (как ORCH-089), но **не** в горячем `claim_next_job` (иначе встанет очередь всех проектов). | +| NFR-5 | **Per-repo область.** Режим включается по CSV-области репо; orchestrator и enduro управляются независимо. | +| NFR-6 | **Self-hosting безопасность.** Механизм не рестартит/не роняет прод-контейнер, не пушит/force-push в `main`. | +| NFR-7 | **Композируемость.** Корректно сосуществует с serial-gate (ORCH-088), auto-label (ORCH-089), coverage-gate (ORCH-027), merge-gate (ORCH-043). | + +--- + +## 6. Допущения и ограничения +- **Минимальный аналитический проход сохраняется** (а не «hotfix → сразу dev»): ради (а) + фиксации регресс-теста как контракта приёмки (BR-4), (б) трассируемости (минимальный bug-report). + Полный отказ от `analysis` для багов оставлен архитектору как опция, но дефолт — мини-анализ. + Обоснование: урок ET-8 — именно отсутствие явного теста-фиксатора привело к «недоделка в Done». +- **Классификация v1 — явная метка оператора**, не LLM-авто-триаж (Вариант 3 в полном объёме — + будущее). Метка `Bug` должна существовать в Plane-проекте; её отсутствие = fail-safe полный цикл. +- **Эскалация v1** — допускает как минимум ручной путь (снять метку `Bug` / вернуть стадию) и/или + решение мини-аналитика «баг сложный → не фаст-трекать». Конкретный механизм — архитектору. +- **Стоимость измеряется относительно**: метрика «во сколько раз дешевле» считается по факту из + существующей телеметрии `agent_runs` (стадии/токены/время), без новой тяжёлой инфраструктуры. + +--- + +## 7. Критерии успеха (резюме; детали — `03-acceptance-criteria.md`) +- AC-1 — задача с меткой `Bug` распознаётся и помечается как багфикс-трек. +- AC-2 — багфикс-задача проходит конвейер, пропустив стадию `architecture` (и тяжёлый BRD/TRZ/AC). +- AC-3 — все Quality Gate'ы исполнены на багфикс-треке (CI/review/tester/staging/deploy + под-гейты). +- AC-4 — багфикс содержит регресс-тест; его отсутствие даёт REQUEST_CHANGES. +- AC-5 — сложный/визуальный баг эскалируется в полный цикл. +- AC-6 — при выключенном флаге / ошибке / неприменимом репо — поведение строго прежнее (полный цикл). +- AC-7 — факт багфикс-трека и метрика экономии наблюдаемы. + +--- + +## 8. Риски (детали — `10-tech-risks.md`, заполняет архитектор) +- R-1: **Срезали лишнее.** Ошибочный пропуск гейта качества → недоделка на проде (ET-8). Митигатор — + NFR-1: режется только аналитика/архитектура, гейты структурно нетронуты + тест AC-3. +- R-2: **Сложный баг под меткой `Bug`** уходит на фаст-трек и упирается в отсутствие архитектуры → + нужна эскалация (BR-5) и/или решение мини-аналитика. +- R-3: **Регресс-тест не написан** (developer «забыл») → рецидив бага. Митигатор — BR-4 + reviewer-ось + + союзник coverage-gate (ORCH-027). +- R-4: **Fail-safe инвертирован** (ошибка → молча срезали стадии) → недоделка. Митигатор — NFR-3 + fail-safe строго в сторону полного цикла + тест AC-6. +- R-5: **Конфликт с serial-gate/auto-label** при изменённой точке входа. Митигатор — NFR-7 + + интеграционный тест композиции. + + diff --git a/docs/work-items/ORCH-019/02-trz.md b/docs/work-items/ORCH-019/02-trz.md new file mode 100644 index 0000000..d2d0891 --- /dev/null +++ b/docs/work-items/ORCH-019/02-trz.md @@ -0,0 +1,207 @@ +--- +work_item: ORCH-019 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-10 +model_used: claude-opus-4-8 +--- + +# 02 — ТЗ (TRZ): ORCH-019 — Режим багфиксинга (упрощённый/дешёвый трек для багов) + +Work Item: **ORCH-019** · Repo: **orchestrator** · Стадия: analysis + +> ТЗ описывает **что** должно измениться и **где** (модули/контракты/артефакты), выведенное из BRD +> и фактического кода. **Как** (точная схема: где именно ветвить маршрут, хранить ли тип задачи в +> БД, отдельный leaf-модуль или расширение `labels.py`) — решает архитектор в `06-adr/`. ТЗ +> фиксирует требования и границы, архитектурное решение не предлагает. + +> ⚠️ **Корневой инвариант (NFR-1 BRD):** срезается ТОЛЬКО аналитика/архитектура. Любой Quality Gate, +> exit-код deploy-хука, под-гейт безопасности/покрытия — байт-в-байт прежние. + +--- + +## 1. Сводка изменения +Ввести **опциональный багфикс-трек**: задача, помеченная в Plane меткой `Bug`, проходит конвейер по +**укороченному маршруту** — пропускается стадия `architecture` и тяжёлая аналитика (полный +BRD/TRZ/AC/ADR заменяются минимальным bug-report + обязательным планом регресс-теста). Все +Quality Gate'ы (CI/review/tester/staging/deploy + под-гейты security/merge/coverage/image-freshness) +исполняются **без изменений**. Распознавание бага и маршрут — аддитивно, под kill-switch, с областью +репо, never-raise, fail-safe → полный цикл. `STAGE_TRANSITIONS` и реестр `QG_CHECKS` структурно не +меняются. + +--- + +## 2. Задействованные модули / пути + +| Путь | Роль в задаче | Характер изменения | +|------|---------------|--------------------| +| `src/labels.py` | аппарат чтения метки Plane (ORCH-089: `has_label`, `*_applies`) | переиспользовать; **добавить** `is_bug_task(work_item_id, project_id) -> bool` + `bug_fast_track_applies(repo) -> bool` (по образцу `auto_approve_applies`), либо вынести в новый leaf `src/bug_fast_track.py` (never-raise) — выбор архитектора | +| `src/plane_sync.py` | `fetch_issue_labels` / `get_project_labels` / `_normalize_label` | **без изменений** — переиспользуются для чтения метки `Bug` (источник истины — Plane API) | +| `src/webhooks/plane.py` | `start_pipeline` (создаёт task-row со стадией `"analysis"`, режет ветку `_create_gitea_branch`), `handle_status_start`, `handle_issue_updated` | **ключевая врезка:** перед `create_task_atomic(...)` определить тип задачи и (при багфикс-треке) пометить задачу багом / задать укороченный маршрут. Внешний контракт вебхука Plane не меняется | +| `src/stages.py` | `STAGE_TRANSITIONS`, `get_next_stage` | **структура `STAGE_TRANSITIONS` не меняется** (новых стадий нет). Требование: маршрут багфикса = `analysis → development` (пропуск `architecture`). Механизм (условный `get_next_stage` по типу задачи / bug-mode-флаг на task) — архитектору | +| `src/stage_engine.py` | `advance_stage`, `_run_qg`, `_handle_analysis_approved_flow`, откаты | `advance_stage` уже маршрутизирует через `get_next_stage` (не зашивает порядок) → при условной маршрутизации правка точечная. Гейты диспетчеризуются как раньше | +| `src/db.py` | `create_task_atomic(plane_id, work_item_id, repo, branch, stage, title)`, схема `tasks`, `claim_next_job` | если архитектор решит хранить «тип=bug» в БД — **аддитивная идемпотентная** колонка (`_ensure_column`, напр. `tasks.track TEXT DEFAULT 'full'`); горячий `claim_next_job` **не** должен ходить в сеть (NFR-4) | +| `src/config.py` | флаги фичи | новые: `bug_fast_track_enabled`, `bug_fast_track_label`, `bug_fast_track_repos` (CSV) + helper `applies(repo)` по образцу `auto_label_*` / `serial_gate_*` | +| `src/qg/checks.py` | реестр `QG_CHECKS` и `check_*` | **без изменений** (инвариант NFR-1) | +| `src/serial_gate.py`, `src/coverage_gate.py`, `src/merge_gate.py` | композиция | **без изменений**; проверить совместимость (NFR-7) интеграционным тестом | +| `src/main.py` | `GET /queue` | **аддитивный** read-only блок `bug_fast_track` (флаг/область/счётчики/метрика экономии) | +| `src/notifications.py` | live-карточка | опционально — отметка «🐞 багфикс-трек» в карточке (never-raise) | +| `.openclaw/agents/analyst.md` | промпт мини-аналитика | при багфикс-треке выдавать **облегчённый** пакет (bug-report + регресс-тест-план), не полный BRD/TRZ/AC. Канон промптов 52d не нарушать | +| `.openclaw/agents/reviewer.md` | ось контроля | добавить ось «багфикс без регресс-теста → REQUEST_CHANGES» (BR-4) — нормативно-описательно, не машинный гейт | + +--- + +## 3. Функциональные требования + +### FR-1 — Классификация задачи как «баг» (BR-1) +- Багфикс-трек активируется, если issue несёт метку Plane с именем `bug_fast_track_label` + (дефолт `Bug`), прочитанную через `labels.has_label(work_item_id, label, project_id)` (ORCH-089: + `fetch_issue_labels` + `get_project_labels`, нормализация `_normalize_label`, TTL-кэш). +- **Источник истины — Plane API**, не payload вебхука (поле `type` в payload отсутствует). +- Чтение метки допускается **только** в `start_pipeline` (момент старта, сетевой вызов приемлем, + как ORCH-089) — **не** в горячем `claim_next_job` (NFR-4). +- `applies(repo)` (локальный, без сети) проверяется **первым**; `has_label` (сеть) — только при + `applies==True` → при выключенном флаге нулевой сетевой оверхед (образец ORCH-089). + +### FR-2 — Укороченный маршрут (BR-2) +- Для багфикс-задачи маршрут конвейера: `analysis(lite) → development → review → testing → + deploy-staging → deploy → done`, т.е. **пропускается стадия `architecture`** (и её exit-гейт + `check_architecture_done` / требование `06-adr/`). +- `STAGE_TRANSITIONS` **не изменяется структурно**. Требуемый инвариант результата: при выходе + багфикс-задачи из `analysis` следующая стадия = `development` (а не `architecture`); для + не-багфикс задач — прежняя `architecture`. Конкретный механизм (условный `get_next_stage(stage, + task)` / bug-mode-флаг на task / точка входа сразу в `development`) — решение архитектора. +- Тяжёлая аналитика облегчается: на багфикс-треке обязательны лишь `01-brd.md` (короткий + bug-report: симптом, шаги воспроизведения, локализация, причина) и `04-test-plan.yaml` (план + регресс-теста). Полные `02-trz.md`/`03-acceptance-criteria.md` и `06-adr/` — **не обязательны**. + (Совместимость с `check_analysis_complete`, требующим `01/02/03/04` — см. FR-6.) + +### FR-3 — Гейты качества сохраняются полностью (BR-3, корневой инвариант) +- На багфикс-треке исполняются **без изменений**: `check_ci_green` (development→review), + `check_reviewer_verdict` (review→testing, `12-review.md`), `check_tests_passed` (testing→ + deploy-staging, `13-test-report.md`), `check_staging_status`, `check_deploy_status`, под-гейты + ребра `deploy-staging→deploy` (security ORCH-022 → merge ORCH-043 → coverage ORCH-027 → + image-freshness ORCH-058) и merge-verify ребра `deploy→done` (ORCH-071/073). +- Ни один `check_*`, его сигнатура, вердикт-ключ или порядок под-гейтов **не меняется**. + +### FR-4 — Обязательный регресс-тест (BR-4) +- Багфикс **обязан** содержать новый/изменённый тест, воспроизводящий дефект (красный до фикса, + зелёный после). Требование закрепляется: (а) в `04-test-plan.yaml` багфикса как обязательный TC; + (б) reviewer-осью (`.openclaw/agents/reviewer.md`): «исправление кода без теста-фиксатора → + finding ≥P1 / REQUEST_CHANGES»; (в) усиливается coverage-гейтом ORCH-027 (структурно ловит «код + без тестов»). Это требование, не новый машинный гейт. + +### FR-5 — Эскалация в полный цикл (BR-5) +- Багфикс-задача должна иметь путь возврата в полный цикл, если баг оказался сложным/архитектурным + или визуальным (нужен макет — связка ORCH-12/14, прецедент ET-9). Минимум v1: ручная эскалация + (оператор снимает метку `Bug` / переводит стадию) **и/или** решение мини-аналитика «баг сложный → + не фаст-трекать» (тогда задача идёт штатным маршрутом с `architecture`). Конкретный механизм и + его автоматизация — архитектору; v1 не обязан включать LLM-авто-триаж сложности. + +### FR-6 — Fail-safe → полный цикл (BR-6, NFR-3) +- При `bug_fast_track_enabled=False`, неприменимом репо, ошибке/таймауте/неоднозначности чтения + метки (`has_label` → False / `None`-labels), отсутствии метки `Bug` в проекте — задача идёт + **полным** циклом (точка входа `analysis`, маршрут с `architecture`). never-raise: ошибка логики + не роняет `start_pipeline`/вебхук. +- **Совместимость с `check_analysis_complete`** (требует наличие `01/02/03/04`): при облегчённом + пакете багфикса гейт не должен ложно блокировать. Варианты (архитектору): мини-аналитик всё равно + эмитит заглушки `02/03` ИЛИ гейт `check_analysis_approved` на багфикс-треке учитывает облегчённый + набор. Требование: **не ослабить** проверку для не-баг задач и **не заблокировать ложно** баг. + +### FR-7 — Наблюдаемость стоимости (BR-7) +- Факт «задача на багфикс-треке» и метрика экономии видны: (а) аддитивный блок `bug_fast_track` в + `GET /queue` (флаг/область + счётчик задач на треке + агрегат сэкономленных стадий/agent-runs); + (б) лог-строка на решение о маршруте; (в) опц. отметка в Telegram-карточке. Метрика «во сколько + дешевле» считается из существующей телеметрии `agent_runs` (Σ токены/время багфикс-трека vs + средний полный цикл) — без новой тяжёлой инфраструктуры. + +--- + +## 4. Изменения API + +### 4.1. Новые публичные endpoint'ы +- **Не требуются обязательно.** (Эскалация и классификация идут через Plane-метки/статусы, не через + новый HTTP-эндпоинт. Если архитектор вводит админ-эндпоинт принудительной (де)классификации — + описать в ADR и обновить таблицу API в README.) + +### 4.2. Изменяемые endpoint'ы +- `GET /queue` — **аддитивно** добавляется блок `bug_fast_track` (read-only, never-raise) по образцу + блоков `serial_gate` / `auto_labels` / `coverage`: `enabled`, `repos`, `label`, перечень/счётчик + задач на багфикс-треке, агрегатная метрика экономии. Существующие ключи `GET /queue` не меняются. + +### 4.3. Webhook-обработчики +- `start_pipeline` (`webhooks/plane.py`): добавляется ветвление «issue имеет метку `Bug` и + `applies(repo)` → багфикс-трек (пометить задачу / задать укороченный вход-маршрут)». Внешний + контракт вебхука Plane не меняется. + +--- + +## 5. Изменения схемы БД +> Только **аддитивные, идемпотентные** миграции (общая прод-БД; enduro не трогать). + +- **Опционально (выбор архитектора):** если тип задачи нужно знать после старта (для маршрутизации + в `advance_stage`/`get_next_stage` и для метрики), ввести аддитивную колонку + `tasks.track TEXT DEFAULT 'full'` (значения `full` | `bug`) через `_ensure_column` (паттерн + `tasks.cancelled_at` ORCH-090). Тогда горячий `claim_next_job` читает тип из БД, **не** из сети + (NFR-4). Альтернатива без колонки (вывести тип повторным чтением метки) допустима, но повторный + сетевой вызов в горячем пути запрещён (NFR-4) → колонка предпочтительнее. +- **Существующие** `tasks`-контракт (прочие колонки), `jobs`, `job_deps`, `agent_runs`, + `coverage_baseline`, `repo_freeze` — **без изменений**. + +--- + +## 6. Требования к новым/изменённым QG checks +- **Новых QG-проверок не вводить; ни один `check_*` не менять семантически** (NFR-1). Маршрутизация + багфикса — свойство планировщика/точки входа, **не** Quality Gate. +- Единственная допустимая тонкая правка — обеспечить, чтобы exit-гейт стадии `analysis` + (`check_analysis_approved` / helper `check_analysis_complete`) **не блокировал ложно** облегчённый + багфикс-пакет, **не ослабляя** проверку для полного цикла (FR-6). Если для этого требуется правка + `check_*` — она должна сохранить вердикт-семантику для не-баг задач байт-в-байт. + +--- + +## 7. Совместимость / регресс +- **Kill-switch** `bug_fast_track_enabled` (env `ORCH_BUG_FAST_TRACK_ENABLED`); `False` → точка входа + и маршрут строго прежние (`analysis → architecture → …`), нулевая регрессия (NFR-2). +- **Область репо** `bug_fast_track_repos` (CSV; пусто → рекомендуется self-hosting + явно + разрешённые проекты, где есть метка `Bug` — решение об области по умолчанию фиксирует архитектор). +- **`applies(repo)` первым** (локально, без сети) → выключенный флаг = нулевой сетевой оверхед, + enduro не затронут. +- **Композиция (NFR-7):** не конфликтует с serial-gate (ORCH-088: багфикс-задача — обычная задача + репо, учитывается в serial-очереди), auto-label (ORCH-089: `autoApprove`/`autoDeploy` работают и + на багфикс-треке), coverage-gate (ORCH-027: союзник BR-4), merge-gate (ORCH-043). +- **never-raise / fail-safe** (NFR-3): ошибка классификации/маршрута → полный цикл, не падение. +- **Self-hosting** (NFR-6): механизм не рестартит/не роняет прод, не пушит/force-push в `main`. +- **Маркеры трассировки** (CLAUDE.md §9): новые инварианты помечаются `ORCH-019`; правка + маркированного кода (ORCH-088/089/027) — со сверкой их `06-adr/`. + +--- + +## 8. Артефакты pipeline (создать/обновить в ТОМ ЖЕ PR) +- `docs/work-items/ORCH-019/06-adr/ADR-001-.md` — решение (механизм маршрута, хранение типа, + совместимость с `check_analysis_complete`, область по умолчанию, механизм эскалации). +- `docs/architecture/README.md` — новый раздел «Багфикс-трек (ORCH-019)» + блок `bug_fast_track` в + описании `GET /queue`; при новой колонке — раздел «База данных». +- `CLAUDE.md` — краткий абзац о багфикс-режиме (правила для агентов / конвейер). +- `CHANGELOG.md` — запись `feat:`. +- `.openclaw/agents/analyst.md` / `reviewer.md` — облегчённый пакет багфикса + reviewer-ось + регресс-теста (канон 52d не нарушать). +- При новой колонке — `docs/work-items/ORCH-019/08-data-requirements.md` (заполняет архитектор). + +--- + +## 9. Открытые вопросы для архитектора (не блокируют анализ) +- OQ-1: Механизм пропуска `architecture` — условный `get_next_stage(stage, task)`, bug-mode-флаг на + task, или прямой вход багфикса сразу в `development` с сохранённым мини-bug-report? (Влияет на + §3 `stages.py`/`stage_engine.py` и на `check_analysis_complete`.) +- OQ-2: Хранить ли тип задачи в БД (`tasks.track`) vs выводить из метки. Рекоменд. — колонка + (NFR-4 запрещает сеть в горячем claim). +- OQ-3: Сохранять ли мини-стадию `analysis(lite)` (рекоменд., ради регресс-теста и трассируемости) + или допустить чистый hotfix `→ development` (вне дефолта). См. BRD §6. +- OQ-4: Механизм эскалации (BR-5) — только ручной (снять метку/сменить стадию) или авто-сигнал + мини-аналитика «баг сложный → полный цикл». +- OQ-5: Область по умолчанию (пустой CSV) — self-hosting only vs все репо с меткой `Bug`. +- OQ-6: Совместимость с `check_analysis_approved`/`check_analysis_complete` на облегчённом пакете + (FR-6) — заглушки `02/03` vs условный учёт гейтом. + diff --git a/docs/work-items/ORCH-019/03-acceptance-criteria.md b/docs/work-items/ORCH-019/03-acceptance-criteria.md new file mode 100644 index 0000000..4f85b2a --- /dev/null +++ b/docs/work-items/ORCH-019/03-acceptance-criteria.md @@ -0,0 +1,139 @@ +--- +work_item: ORCH-019 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-10 +model_used: claude-opus-4-8 +--- + +# 03 — Критерии приёмки (Acceptance Criteria): ORCH-019 — Режим багфиксинга + +Work Item: **ORCH-019** · Repo: **orchestrator** · Стадия: analysis + +Формат: каждый критерий имеет **PASS** (что должно быть истинно для приёмки) и **FAIL** (что +считается провалом). Reviewer/tester проверяют их буквально по файлам репозитория и тестам. + +> ⚠️ Корневой инвариант (см. AC-3/AC-8): срезается только аналитика/архитектура; ни один Quality +> Gate не ослаблен. Это главное условие приёмки — нарушение = безусловный FAIL всей задачи. + +--- + +## AC-1 — Классификация задачи по метке `Bug` + +**Условие:** issue с меткой Plane `bug_fast_track_label` (дефолт `Bug`) при включённом флаге и +применимом репо распознаётся как багфикс-задача. +- **PASS:** при `bug_fast_track_enabled=True` и `applies(repo)==True` для issue с меткой `Bug` + `is_bug_task(...)` возвращает `True` (через `labels.has_label` → `plane_sync.fetch_issue_labels`); + задача стартует на багфикс-треке. Источник метки — Plane API, не payload вебхука. +- **FAIL:** метка `Bug` игнорируется; ИЛИ тип читается из payload вебхука; ИЛИ задача без метки + `Bug` ошибочно попадает на багфикс-трек. + +--- + +## AC-2 — Укороченный маршрут: пропуск стадии `architecture` + +**Условие:** багфикс-задача проходит конвейер, минуя стадию `architecture`. +- **PASS:** для багфикс-задачи переход из `analysis` ведёт в `development` (а не `architecture`); + стадия `architecture` и её требование `06-adr/` для багфикса не исполняются; задача доходит до + `done`. Маршрут не-баг задачи остаётся `analysis → architecture → development → …`. +- **FAIL:** багфикс-задача всё равно проходит `architecture`; ИЛИ не-баг задача начинает пропускать + `architecture`; ИЛИ `STAGE_TRANSITIONS` изменён структурно (новые/удалённые стадии). + +--- + +## AC-3 — Все Quality Gate'ы исполнены на багфикс-треке (корневой инвариант) + +**Условие:** на багфикс-треке исполняются все гейты качества без изменений. +- **PASS:** для багфикс-задачи отрабатывают `check_ci_green`, `check_reviewer_verdict` + (`12-review.md`), `check_tests_passed` (`13-test-report.md`), `check_staging_status`, + `check_deploy_status` и под-гейты ребра `deploy-staging→deploy` (security → merge → coverage → + image-freshness) и merge-verify ребра `deploy→done`. Реестр `QG_CHECKS`, сигнатуры `check_*`, + вердикт-ключи (`verdict:`/`result:`/`deploy_status:`/`staging_status:`/`security_status:`/ + `coverage_status:`) и порядок под-гейтов — байт-в-байт прежние. +- **FAIL:** хоть один гейт качества пропущен/ослаблен/изменён на багфикс-треке; ИЛИ изменён состав + `QG_CHECKS` / имя или регистр любого вердикт-ключа / порядок под-гейтов. + +--- + +## AC-4 — Обязательный регресс-тест + +**Условие:** багфикс фиксирует дефект тестом. +- **PASS:** PR багфикса содержит новый/изменённый тест, воспроизводящий исправляемый дефект + (красный на коде до фикса, зелёный после); требование закреплено в `04-test-plan.yaml` багфикса + и в reviewer-оси (`.openclaw/agents/reviewer.md`: фикс без теста → finding ≥P1 / REQUEST_CHANGES). +- **FAIL:** багфикс мержится без теста-фиксатора; ИЛИ reviewer-ось отсутствует/не срабатывает; ИЛИ + тест присутствует, но не падает на исходном (нефиксированном) коде. + +--- + +## AC-5 — Эскалация сложного бага в полный цикл + +**Условие:** сложный/архитектурный/визуальный баг возвращается в полный цикл. +- **PASS:** существует и документирован путь эскалации (минимум ручной: снятие метки `Bug` / + перевод стадии, и/или решение мини-аналитика «баг сложный → не фаст-трекать»); после эскалации + задача проходит штатный маршрут с `architecture`. +- **FAIL:** механизма эскалации нет; ИЛИ багфикс-задача необратимо застревает без `architecture`, + когда баг требует архитектурного решения/макета. + +--- + +## AC-6 — Fail-safe → полный цикл (нулевая регрессия) + +**Условие:** при выключении/ошибке/неприменимости — строго прежнее поведение (полный цикл). +- **PASS:** при `bug_fast_track_enabled=False`, неприменимом репо, ошибке/таймауте/неоднозначности + чтения метки, отсутствии метки `Bug` — задача стартует на `analysis` и идёт маршрутом с + `architecture` (как до ORCH-019). Логика never-raise: ошибка не роняет `start_pipeline`/вебхук. + При выключенном флаге путь старта и маршрут идентичны текущим (диффом по поведению — нулевые). +- **FAIL:** ошибка/неоднозначность приводит к молчаливому пропуску стадий; ИЛИ исключение из + логики классификации роняет вебхук/конвейер; ИЛИ при выключенном флаге поведение отличается от + прежнего. + +--- + +## AC-7 — Наблюдаемость трека и метрика стоимости + +**Условие:** факт багфикс-трека и экономия наблюдаемы. +- **PASS:** `GET /queue` содержит аддитивный read-only блок `bug_fast_track` (флаг/область/метка + + счётчик задач на треке + агрегатная метрика экономии стадий/agent-runs/токенов/времени); + решение о маршруте логируется; существующие ключи `GET /queue` не изменены. +- **FAIL:** трек/метрика ненаблюдаемы; ИЛИ блок ломает существующий контракт `GET /queue`; ИЛИ + ошибка построения блока роняет эндпоинт (нарушен never-raise). + +--- + +## AC-8 — Аддитивность и self-hosting безопасность + +**Условие:** изменение аддитивно и безопасно для общего прод-инстанса. +- **PASS:** миграции БД (если есть) аддитивны и идемпотентны (`_ensure_column`/`CREATE TABLE IF NOT + EXISTS`); enduro при выключенном/неприменимом флаге не затронут; механизм не рестартит/не роняет + прод-контейнер, не пушит/force-push в `main`. Полный регресс `tests/` зелёный. +- **FAIL:** ломающая миграция/изменение существующих контрактов; ИЛИ затронут enduro при выключенном + флаге; ИЛИ механизм трогает прод-контейнер/`main`; ИЛИ красный `tests/`. + +--- + +## AC-9 — Композиция с существующими гейтами + +**Условие:** багфикс-трек корректно сосуществует с ORCH-088/089/027/043. +- **PASS:** багфикс-задача корректно учитывается serial-gate (ORCH-088) как обычная задача репо; + `autoApprove`/`autoDeploy` (ORCH-089) работают на багфикс-треке; coverage-gate (ORCH-027) и + merge-gate (ORCH-043) исполняются штатно. Интеграционный тест композиции зелёный. +- **FAIL:** изменённая точка входа ломает serial-очередь/auto-label/merge/coverage; ИЛИ багфикс- + задача обходит serial-gate. + +--- + +## Сводная матрица AC ↔ BR/FR +| AC | Покрывает | +|----|-----------| +| AC-1 | BR-1 / FR-1 | +| AC-2 | BR-2 / FR-2 | +| AC-3 | BR-3 / FR-3 / NFR-1 | +| AC-4 | BR-4 / FR-4 | +| AC-5 | BR-5 / FR-5 | +| AC-6 | BR-6 / FR-6 / NFR-2 / NFR-3 | +| AC-7 | BR-7 / FR-7 | +| AC-8 | BR-8 / NFR-2 / NFR-6 | +| AC-9 | NFR-7 | + diff --git a/docs/work-items/ORCH-019/04-test-plan.yaml b/docs/work-items/ORCH-019/04-test-plan.yaml new file mode 100644 index 0000000..8546352 --- /dev/null +++ b/docs/work-items/ORCH-019/04-test-plan.yaml @@ -0,0 +1,111 @@ +work_item: ORCH-019 +stage: analysis +author_agent: analyst +status: ready-for-review +created_at: 2026-06-10 +model_used: claude-opus-4-8 +title: "Багфикс-трек: классификация по метке, укороченный маршрут, сохранность гейтов, fail-safe" +framework: pytest +scope: > + Покрывает: классификацию задачи как бага по метке Plane (ORCH-089-аппарат), маршрутизацию + багфикса в обход стадии architecture, сохранность ВСЕХ Quality Gate'ов, обязательность + регресс-теста, эскалацию в полный цикл, fail-safe → полный цикл, наблюдаемость/метрику, + аддитивность и композицию с serial-gate/auto-label/coverage. Вне покрытия: реальный + Plane/Gitea I/O (мокается), роутинг моделей ORCH-13, LLM-авто-триаж сложности. +notes: > + Сетевые вызовы Plane (fetch_issue_labels/get_project_labels) мокаются. Полный регресс tests/ + должен оставаться зелёным. Тесты на сохранность гейтов проверяют НЕИЗМЕННОСТЬ QG_CHECKS/check_*/ + вердикт-ключей — это анти-регресс корневого инварианта (NFR-1). Финальные имена модулей/функций + (labels.py vs новый bug_fast_track.py; tasks.track колонка) фиксирует архитектор — TC привязаны + к поведению, имена путей уточняются на стадии разработки. + +tests: + - id: TC-01 + type: unit + description: "is_bug_task() возвращает True для issue с меткой 'Bug' (has_label True); метка читается из Plane API, не из payload." + module: tests/test_bug_fast_track.py + expected: PASS + + - id: TC-02 + type: unit + description: "is_bug_task() возвращает False при отсутствии метки, неоднозначной метке или labels=None (fail-safe)." + module: tests/test_bug_fast_track.py + expected: PASS + + - id: TC-03 + type: unit + description: "bug_fast_track_applies(repo): первым проверяется локальная область (enabled + CSV repos) до любого сетевого вызова; выключенный флаг → False без обращения к has_label." + module: tests/test_bug_fast_track.py + expected: PASS + + - id: TC-04 + type: unit + description: "never-raise: исключение в fetch_issue_labels/get_project_labels не пробрасывается — is_bug_task деградирует в False (полный цикл)." + module: tests/test_bug_fast_track.py + expected: PASS + + - id: TC-05 + type: unit + description: "Маршрут багфикса: для bug-задачи следующая стадия после analysis = development (architecture пропущена); для не-баг задачи = architecture." + module: tests/test_bug_fast_track_routing.py + expected: PASS + + - id: TC-06 + type: unit + description: "STAGE_TRANSITIONS структурно не изменён: набор стадий и рёбер байт-в-байт прежний (анти-регресс)." + module: tests/test_bug_fast_track_routing.py + expected: PASS + + - id: TC-07 + type: unit + description: "Реестр QG_CHECKS и сигнатуры check_* не изменены багфикс-треком; вердикт-ключи (verdict/result/deploy_status/staging_status/security_status/coverage_status) сохранены по имени и регистру." + module: tests/test_bug_fast_track_gates.py + expected: PASS + + - id: TC-08 + type: integration + description: "E2E багфикс-трек: bug-задача проходит development→review→testing→deploy-staging→deploy с исполнением всех гейтов (check_ci_green/reviewer_verdict/tests_passed/staging/deploy + под-гейты security/merge/coverage/image-freshness), минуя architecture." + module: tests/test_bug_fast_track_e2e.py + expected: PASS + + - id: TC-09 + type: integration + description: "start_pipeline: issue с меткой Bug (флаг вкл, репо применим) создаёт задачу на багфикс-треке; issue без метки — на полном цикле (точка входа analysis + маршрут с architecture)." + module: tests/test_bug_fast_track_e2e.py + expected: PASS + + - id: TC-10 + type: integration + description: "Fail-safe: при bug_fast_track_enabled=False путь старта и маршрут идентичны прежним (нулевая регрессия) — задача с меткой Bug идёт полным циклом." + module: tests/test_bug_fast_track_e2e.py + expected: PASS + + - id: TC-11 + type: integration + description: "Эскалация: после снятия метки Bug / решения 'баг сложный' задача проходит штатный маршрут с architecture (возврат в полный цикл)." + module: tests/test_bug_fast_track_escalation.py + expected: PASS + + - id: TC-12 + type: unit + description: "check_analysis_approved/check_analysis_complete не блокирует ложно облегчённый багфикс-пакет, но сохраняет прежнюю проверку для не-баг задач (требование FR-6)." + module: tests/test_bug_fast_track_gates.py + expected: PASS + + - id: TC-13 + type: integration + description: "GET /queue содержит аддитивный read-only блок bug_fast_track (enabled/repos/label/счётчик/метрика); существующие ключи неизменны; ошибка построения блока не роняет эндпоинт." + module: tests/test_queue_endpoint.py + expected: PASS + + - id: TC-14 + type: integration + description: "Композиция: багфикс-задача учитывается serial-gate (ORCH-088) как обычная задача репо и не обходит его; autoApprove/autoDeploy (ORCH-089) применимы на багфикс-треке." + module: tests/test_bug_fast_track_composition.py + expected: PASS + + - id: TC-15 + type: unit + description: "Миграция (если введена колонка tasks.track) аддитивна и идемпотентна: повторный init_db/_ensure_column не падает; дефолт 'full' для существующих строк." + module: tests/test_db_migrations.py + expected: PASS