172 lines
18 KiB
Markdown
172 lines
18 KiB
Markdown
---
|
||
work_item: ORCH-120
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-17
|
||
model_used: claude-opus-4-8
|
||
escalate: full-cycle
|
||
---
|
||
|
||
# 01 — BRD (бизнес-требования): ORCH-120 — Открытые вопросы аналитика должны переводить задачу в Needs Input
|
||
|
||
Work Item: **ORCH-120** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
> ⚠️ **Эскалация в полный цикл (`escalate: full-cycle`).** Это формально баг (метка `BUG:` в
|
||
> заголовке), но фикс требует архитектурных решений (правило приоритета веток в
|
||
> `_handle_analysis_approved_flow`, интеграция с осью «пауза» ORCH-124, семантика устаревания
|
||
> `01-questions.md`, стандартизация нового pipeline-артефакта) — нужен ADR. Поэтому выпущен
|
||
> **полный** analysis-пакет (01/02/03/04), а не облегчённый bug-shaped. Оператор снимает багфикс-трек
|
||
> командой `POST /bug-fast-track/escalate?work_item=ORCH-120`, после чего задача идёт через стадию
|
||
> `architecture` (ADR-001 D5 ORCH-019). Открытые проектные вопросы для архитектора — §6 (DQ-1…DQ-4).
|
||
|
||
## 1. Бизнес-контекст и проблема
|
||
|
||
При запуске конвейера аналитик (`analyst`) получает бизнес-запрос и **обязан** выпустить 4 файла
|
||
(`01-brd` / `02-trz` / `03-acceptance-criteria` / `04-test-plan.yaml`), иначе exit-гейт стадии
|
||
`analysis` не пройдёт. Если бизнес-запрос неоднозначен или неполон (классический пример — тело
|
||
запроса `Description: TBD`), у аналитика **нет рабочего канала** запросить уточнения у заказчика: он
|
||
вынужден **домысливать** требования и всё равно сдать 4 файла. Сфабрикованный пакет уходит в
|
||
`In Review` / `architecture` — то есть весь конвейер строит решение поверх выдуманных требований.
|
||
|
||
**Парадокс:** механизм «вопросы → Needs Input» в движке **уже есть, но мёртв**. Код
|
||
`src/stage_engine.py::_handle_analysis_approved_flow` (стр. 769–786) читает файл
|
||
`docs/work-items/<wid>/01-questions.md` и при его наличии вызывает `set_issue_needs_input(...)` +
|
||
комментарий в Plane + Telegram. Однако:
|
||
|
||
1. **Контракт не доведён до аналитика.** Промпт `.openclaw/agents/analyst.md` **нигде** не упоминает
|
||
`01-questions.md`: ни в `<deliverables>`, ни в `<task>`. Скелета `docs/_templates/01-questions.md`
|
||
нет, в манифесте `docs/_standards/PIPELINE_DOCS.md` артефакт не описан. Аналитик физически не
|
||
знает, что у него есть канал «задать блокирующий вопрос», поэтому домысливает.
|
||
2. **Ошибка приоритета веток.** В `_handle_analysis_approved_flow` ветка `files_ok` (все 4 файла на
|
||
месте — `check_analysis_complete`) проверяется **первой** и делает `return` (стр. 711–767). Ветка
|
||
`01-questions.md` (стр. 769) достижима, только если 4 файла НЕ полны. Значит, если аналитик сдал и
|
||
неполный/заглушечный пакет, и `01-questions.md` — движок уйдёт в `In Review`, проигнорировав
|
||
блокирующие вопросы. «Есть вопросы» должно иметь приоритет над «файлы на месте».
|
||
3. **Needs-Input блокирует serial-gate репо.** Задача в Needs Input остаётся в стадии `analysis`
|
||
(Plane-статус — слой B индикации, ORCH-066, **не** меняет `tasks.stage`) и при этом
|
||
`paused_at IS NULL`. По правилу serial-gate (ORCH-088) такая «активная» задача держит FIFO репо
|
||
закрытым: пока заказчик не ответит (часы/дни), ни одна следующая задача `orchestrator` не войдёт в
|
||
`analysis`. ORCH-124 ввёл ортогональную ось «пауза» (`tasks.paused_at` + `POST /serial-gate/pause|
|
||
resume`) ровно для случая «приостановлено, но не блокирует» — Needs-Input обязан её использовать.
|
||
4. **Нет гигиены устаревшего `01-questions.md`.** После ответа заказчика `handle_status_start`
|
||
перезапускает аналитика (`src/webhooks/plane.py:317–381`). Если перезапущенный аналитик теперь
|
||
выпускает полный валидный пакет, старый `01-questions.md` остаётся в ветке. Без правила
|
||
«устаревания» он либо игнорируется (если `files_ok` побеждает), либо вечно перезапускает Needs
|
||
Input (если вопросы получат приоритет). Нужно явное правило supersede.
|
||
|
||
Корень — **разрыв контракта между промптом аналитика и движком** плюс **3 смежных дефекта потока**
|
||
(приоритет, блокировка очереди, устаревание). ORCH-120 закрывает их как единый «правильный поток
|
||
Needs Input».
|
||
|
||
**Связь с предшественниками (контекст резюма из бэклога):** задача разморожена после корневых
|
||
фиксов **ORCH-124** (ось «пауза без блокировки» — необходимый фундамент для требования BR-3) и
|
||
**ORCH-126** (queued-job не застревает со stale `run_id`/`pid` — гарантирует, что перезапущенный
|
||
после ответа аналитик-job реально заберётся из очереди). Оба — предусловия, а не объём ORCH-120.
|
||
|
||
## 2. Объём (scope)
|
||
|
||
### В объёме
|
||
- **Контракт промпта аналитика:** `.openclaw/agents/analyst.md` явно документирует канал
|
||
«блокирующие открытые вопросы → пиши `01-questions.md`, НЕ фабрикуй 4 deliverables», с форматом и
|
||
правилом поведения на перезапуске (прочитать ответы, снять устаревшие вопросы).
|
||
- **Канон артефакта:** скелет `docs/_templates/01-questions.md` + строка в манифесте
|
||
`docs/_standards/PIPELINE_DOCS.md` (артефакт-сигнал Needs Input; **не** machine-verdict-док, гейтом
|
||
не парсится).
|
||
- **Приоритет веток в движке:** в `_handle_analysis_approved_flow` блокирующие открытые вопросы
|
||
получают корректный приоритет → задача с вопросами надёжно достигает Needs Input.
|
||
- **Неблокирование serial-gate:** переход в Needs Input не держит FIFO репо закрытым неопределённо
|
||
долго (интеграция с осью «пауза» ORCH-124).
|
||
- **Гигиена устаревания:** перезапущенный аналитик, выпустивший полный валидный пакет без свежих
|
||
вопросов, приводит к `In Review`, а не к повторному Needs Input.
|
||
- **Корректность resume-петли:** ответ заказчика → перезапуск аналитика → снятие паузы (unpark), job
|
||
забирается из очереди.
|
||
- **Обязательный регресс-тест** (красный до фикса, зелёный после) + анти-дрейф структурные тесты.
|
||
|
||
### Вне объёма
|
||
- **Расширение владения Needs Input на других агентов.** ORCH-066 BR-10 фиксирует: Needs Input —
|
||
только у аналитика. Механизм не расширяется на architect/developer/reviewer/tester/deployer.
|
||
- **Новые QG-проверки и новые рёбра `STAGE_TRANSITIONS`.** Поток вопросов — pre-gate-ветка движка,
|
||
не Quality Gate. `check_analysis_complete`/`check_analysis_approved` — байт-в-байт.
|
||
- **Изменение семантики самого гейта `analysis`** (4 файла по-прежнему обязательны для прохождения
|
||
exit-гейта `analysis → architecture`).
|
||
- **Авто-ответ на вопросы / LLM-триаж ответов заказчика.** Ответы читает человек/аналитик, а не
|
||
отдельный автомат.
|
||
- **Машинерия багфикс-трека (ORCH-019)** и любые изменения вне аналитической стадии.
|
||
|
||
## 3. Заинтересованные стороны
|
||
- **Заказчик / оператор (Слава)** — получает осмысленный запрос уточнений вместо выдуманных
|
||
требований; отвечает в Plane и возвращает задачу в работу.
|
||
- **Конвейер `orchestrator` (self-hosting)** — перестаёт строить решения поверх домыслов; serial-gate
|
||
репо не клинит на задаче, ждущей человека.
|
||
- **Аналитик-агент** — получает легитимный канал «не знаю — спрошу» вместо принуждения к фабрикации.
|
||
- **Другие проекты на общем инстансе (enduro-trails)** — не затронуты (нулевая регрессия при
|
||
отсутствии `01-questions.md` и вне self-hosting-области).
|
||
|
||
## 4. Бизнес-требования (BR)
|
||
- **BR-1** — Аналитик, столкнувшийся с **блокирующей** неоднозначностью бизнес-запроса, ОБЯЗАН иметь
|
||
документированный канал запроса уточнений (`01-questions.md`) и НЕ должен фабриковать 4 deliverables
|
||
«лишь бы пройти гейт». Промпт `.openclaw/agents/analyst.md` описывает этот канал.
|
||
- **BR-2** — Наличие блокирующих открытых вопросов переводит задачу в Plane-статус **Needs Input** и
|
||
**останавливает** продвижение по конвейеру (не `In Review`, не `architecture`), даже если на диске
|
||
присутствуют частичные/заглушечные deliverables. Приоритет «вопросы» > «файлы на месте».
|
||
- **BR-3** — Задача в Needs Input **не блокирует** per-repo serial-gate FIFO неопределённо долго:
|
||
следующая задача `orchestrator` может войти в `analysis`, пока первая ждёт ответа человека.
|
||
- **BR-4** — После ответа заказчика (возврат issue в рабочий статус) аналитик перезапускается, читает
|
||
ответы и выпускает пакет. Если пакет полон и валиден и свежих блокирующих вопросов нет → задача
|
||
переходит в `In Review` (устаревший `01-questions.md` не должен повторно ронять её в Needs Input).
|
||
- **BR-5** — Поведение **обратимо и выборочно**: при отсутствии `01-questions.md` и выключенных
|
||
под-флагах поток Needs Input/паузы — байт-в-байт как до ORCH-120 (нулевая регрессия для enduro и
|
||
для штатной задачи без вопросов).
|
||
- **BR-6** — `01-questions.md` стандартизирован как pipeline-артефакт (скелет в `docs/_templates/` +
|
||
строка манифеста `PIPELINE_DOCS.md`): он сигнальный, **не** machine-verdict (гейтом не парсится).
|
||
|
||
## 5. Нефункциональные требования (NFR)
|
||
- **NFR-1 (never-raise / fail-safe)** — Любая ошибка новой логики (чтение файла, park-вызов,
|
||
определение приоритета) НЕ роняет `advance_stage`/launcher и деградирует к безопасному прежнему
|
||
поведению (как существующие leaf'ы `serial_gate`/`labels`/`cancel`).
|
||
- **NFR-2 (обратная совместимость)** — Стадии, кроме `analysis`, и Needs-Input-владение (ORCH-066) —
|
||
не трогаются. `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключи / семантика
|
||
exit-гейта `analysis` — байт-в-байт.
|
||
- **NFR-3 (инварианты serial-gate)** — Интеграция с паузой не регрессирует ORCH-088 (анти-stale-base:
|
||
отложенный срез ветки) и ORCH-124 (терминал `{done,cancelled}` и оси `task_deps`/`freeze` —
|
||
не читают `paused_at`; пауза их не обходит).
|
||
- **NFR-4 (self-hosting-безопасность)** — Поток только меняет Plane-статус/паузу/комментарий и читает
|
||
worktree: не деплоит, не рестартит прод-контейнер, не пушит в `main`, не трогает detached-процессы.
|
||
- **NFR-5 (наблюдаемость)** — Переход в Needs Input и park/unpark логируются структурно; состояние
|
||
паузы видно в блоке `serial_gate` `GET /queue` (ORCH-124 уже отдаёт `paused`).
|
||
|
||
## 6. Допущения и ограничения
|
||
- **Допущение:** механизм чтения `01-questions.md` и `set_issue_needs_input` рабочие — задача в
|
||
основном **активирует и достраивает** существующий путь, а не строит его с нуля.
|
||
- **Допущение:** промпт `cat`-ается из worktree в момент запуска (ORCH-077 loading-model) → новый
|
||
контракт аналитика вступает в силу на следующем worktree от `main` без прод-рестарта.
|
||
- **Ограничение:** Plane-статус **Needs Input** должен существовать на доске проекта (ключ
|
||
`needs_input` уже в `plane_sync._DEFAULT_STATES`) — инфра-предусловие выполнено для ORCH.
|
||
- **Открытые проектные вопросы для архитектора (решить в `06-adr/`, НЕ в analysis):**
|
||
- **DQ-1** — Парковать задачу при Needs Input **автоматически** (`db.set_task_paused` в момент
|
||
перехода) или оставить park **операторским** (`POST /serial-gate/pause`)? Trade-off:
|
||
авто-park снимает риск стопора очереди (BR-3), но связывает индикацию (слой B) с осью планировщика.
|
||
- **DQ-2** — Механизм устаревания `01-questions.md` (BR-4): удалять файл при выпуске полного пакета /
|
||
приоритет по «вопросы свежее deliverables» (mtime/commit) / явный маркер «answered». Любой выбор
|
||
обязан быть детерминированным и не зависеть от сетевого Plane.
|
||
- **DQ-3** — Точное правило приоритета в `_handle_analysis_approved_flow`: проверять
|
||
`01-questions.md` ДО `files_ok`, либо ввести предикат «вопросы активны» с учётом DQ-2.
|
||
- **DQ-4** — Коллизия номера `01-questions.md` с `01-brd.md`. Движок читает именно `01-questions.md`
|
||
(`stage_engine.py:771`) — менять путь = код-изменение; стандарт документирует фактический путь.
|
||
- **Ограничение по флагам:** новое поведение (приоритет вопросов / авто-park) — под kill-switch с
|
||
безопасным дефолтом, чтобы откат был байт-в-байт (BR-5).
|
||
|
||
## 7. Критерии успеха
|
||
Аналитик при блокирующей неоднозначности пишет `01-questions.md`, задача надёжно переходит в Needs
|
||
Input, **не** блокирует serial-gate репо, после ответа заказчика возобновляется и выпускает корректный
|
||
пакет; при отсутствии вопросов — поведение прежнее. Детальные PASS/FAIL — `03-acceptance-criteria.md`.
|
||
|
||
## 8. Риски
|
||
- Связывание индикации (Plane-статус) с осью планировщика (пауза) при авто-park (DQ-1) — риск
|
||
непреднамеренного park; смягчение — kill-switch + явный лог.
|
||
- Устаревший `01-questions.md` зацикливает Needs Input (DQ-2) — смягчение детерминированным
|
||
supersede-правилом + регресс-тест BR-4.
|
||
- Регресс serial-gate (ORCH-088/124) при неаккуратной интеграции паузы — смягчение тестами NFR-3.
|
||
Детали и оценка — `10-tech-risks.md` (заполняет архитектор).
|