Files

208 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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-<slug>.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 условный учёт гейтом.
</content>