fix(analysis): activate analyst open-questions -> Needs Input flow (ORCH-120)
All checks were successful
CI / test (push) Successful in 1m14s
CI / test (pull_request) Successful in 1m11s

Activates and completes the previously dead "analyst asks BLOCKING questions ->
01-questions.md -> Needs Input" path. Four coordinated changes, additive, under
kill-switch, self-hosting scope, never-raise; STAGE_TRANSITIONS / QG_CHECKS /
check_* / machine-verdict keys / DB schema are byte-for-byte UNCHANGED (the flow
is a pre-gate engine branch, NOT a Quality Gate; 01-questions.md is a SIGNAL
artifact, NOT a machine-verdict).

- D1 contract + canon: analyst.md documents the 01-questions.md channel (blocking
  questions -> Needs Input, do NOT fabricate deliverables) + resume behaviour; new
  skeleton docs/_templates/01-questions.md; PIPELINE_DOCS.md manifest row + 01-
  prefix note.
- D2 freshness-supersede (DQ-2): pure offline mtime predicate questions_active in
  the new leaf src/analyst_questions.py (a full FRESH package supersedes a stale
  untouched 01-questions.md -> no Needs-Input loop, AC-6).
- D3 priority: questions take priority over "files ready" in
  _handle_analysis_approved_flow (_decide_analysis_outcome + _emit_analysis_*);
  off/out-of-scope runs the ORIGINAL byte-for-byte order (AC-9).
- D4 auto-park: set_task_paused on Needs Input via the ORCH-124 pause axis so the
  repo serial-gate FIFO is not wedged while waiting for a human (AC-4); D5 resume +
  unpark (clear_task_paused) in handle_status_start (analysis branch).

Flags (config.py, safe defaults): analyst_questions_gate_enabled /
analyst_questions_gate_repos (empty -> self-hosting only) /
analyst_needs_input_autopause_enabled.

Tests: test_orch120_analyst_needs_input.py (TC-01 regress + TC-02/03/06/09/10),
test_orch120_serial_gate_needs_input.py (TC-04), test_orch120_resume_unpark.py
(TC-05), test_orch120_questions_artifact_canon.py (TC-08), assert in
test_agent_prompts_canon.py (TC-07). Full suite green (2205 passed).

Refs: ORCH-120

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 13:15:27 +03:00
parent 1fcbe06df5
commit d6b495f156
15 changed files with 1082 additions and 70 deletions

View File

@@ -47,6 +47,7 @@ check_tests_passed → check_staging_status → check_deploy_status`.
|----------|----------------|-----------|------------------|--------------------------|-------------------------|
| `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`) | — |
| `01-questions.md` | analyst | when-applicable | `analysis` | **сигнальный** (гейтом НЕ парсится); механизм — ветка Needs Input в `_handle_analysis_approved_flow` (ORCH-120, adr-0053): активные блокирующие вопросы → `set_issue_needs_input` (приоритет над «файлы готовы») | — (не machine-verdict) |
| `02-trz.md` | analyst | required | `analysis` | то же | — |
| `03-acceptance-criteria.md` | analyst | required | `analysis` | то же | — |
| `04-test-plan.yaml` | analyst | required | `analysis` | то же | — |
@@ -72,6 +73,10 @@ check_tests_passed → check_staging_status → check_deploy_status`.
- **Категория `when-applicable`** = документ пишется при наличии соответствующего предмета
(инфра / данные / security / post-deploy). Его отсутствие — не нарушение приёмки.
- **`05-…` / `09-…` / `11-…`** — зарезервированные/legacy номера, в текущем каноне не используются.
- **Префикс `01-` (DQ-4 ORCH-120)** — общий для артефактов стадии `analysis` владельца `analyst`:
`01-brd.md` — обязательный deliverable (гейтится `check_analysis_complete`), `01-questions.md`
**сигнальный** when-applicable артефакт того же владельца/стадии. Коллизии нет: файлы разноимённые,
`check_analysis_complete` проверяет ровно `01-brd.md`/`02`/`03`/`04` (`01-questions.md` им не парсится).
---

43
docs/_templates/01-questions.md vendored Normal file
View File

@@ -0,0 +1,43 @@
---
work_item: ORCH-NNN
stage: analysis
author_agent: analyst
status: needs-input
created_at: <YYYY-MM-DD>
model_used: <resolve ORCH-41>
---
# 01 — Открытые вопросы (Open Questions): ORCH-NNN — <название>
Work Item: **ORCH-NNN** · Repo: **<repo>** · Стадия: analysis
> **Сигнальный** when-applicable артефакт (ORCH-120, adr-0053). Пишется аналитиком через **Write
> tool** ТОЛЬКО при **блокирующей** неоднозначности бизнес-запроса, когда выпустить корректные 4
> deliverables нельзя без ответа заказчика. Наличие этого файла с **активными** вопросами уводит
> задачу в **Needs Input** (приоритет над «файлы готовы»). **Не** machine-verdict: гейтом
> (`check_analysis_complete`/`check_analysis_approved`) НЕ парсится — это сигнал движку
> (`_handle_analysis_approved_flow`).
>
> ⚠️ Если блокирующих вопросов НЕТ — **не создавай** этот файл; выпускай полный пакет (`01-brd.md`/
> `02-trz.md`/`03-acceptance-criteria.md`/`04-test-plan.yaml`). Не фабрикуй требования ради сдачи 4
> файлов.
## 1. Контекст
<Что именно в бизнес-запросе (`00-business-request.md`) блокирует выпуск корректного пакета. Какие
факты установлены, а какие — нет. На какой код `src/` это влияет.>
## 2. Блокирующие вопросы
> Каждый вопрос — конкретный, отвечаемый, с вариантами (где уместно) и указанием, почему ответ
> блокирует анализ. Нумеруй (Q-1, Q-2, …).
- **Q-1** — <вопрос>
- Вариант A: <…> (последствие)
- Вариант B: <…> (последствие)
- Почему блокирует: <без ответа нельзя выпустить BR/TRZ, т.к. …>
- **Q-2** — …
## 3. Что разблокирует анализ
<Какие ответы переводят задачу из Needs Input обратно в работу: после ответов заказчика в Plane
аналитик перезапускается (resume), читает свежие комментарии и выпускает полный пакет. Если часть
вопросов снята, а часть осталась — **перепиши** этот файл (оставь только актуальные блокеры), иначе
выпусти 4 deliverables (свежий пакет supersedeит этот файл по mtime, DQ-2).>

View File

@@ -650,7 +650,7 @@ ORCH-027 вводит детерминированный (без LLM) **гейт
`docs/work-items/ORCH-088/08-data-requirements.md`,
`docs/work-items/ORCH-124/06-adr/ADR-001-serial-gate-pause-without-blocking.md`.
### Открытые вопросы аналитика → Needs Input (ORCH-120 — design, [adr-0053](adr/adr-0053-analyst-open-questions-needs-input-flow.md))
### Открытые вопросы аналитика → Needs Input (ORCH-120 — реализовано, [adr-0053](adr/adr-0053-analyst-open-questions-needs-input-flow.md))
При неоднозначном бизнес-запросе у аналитика не было рабочего канала уточнения — он **фабриковал**
требования, чтобы сдать обязательные 4 файла. Механизм «вопросы → Needs Input» в
`_handle_analysis_approved_flow` (`src/stage_engine.py`) существовал, но был **мёртв** (контракт не в
@@ -663,7 +663,10 @@ self-hosting, never-raise; `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-ver
`01-questions.md`, НЕ фабриковать deliverables»; `01-questions.md` стандартизирован как
`when-applicable` сигнальный артефакт (скелет `docs/_templates/` + строка `PIPELINE_DOCS.md`).
- **Приоритет «вопросы активны» > «файлы готовы»** в `_handle_analysis_approved_flow` (DQ-3) →
блокирующие вопросы достигают Needs Input даже при частичных/сфабрикованных deliverables.
блокирующие вопросы достигают Needs Input даже при частичных/сфабрикованных deliverables. Чистая
логика решения — leaf `src/analyst_questions.py` (`questions_gate_applies`/`autopause_applies`/
`questions_active`, never-raise); side-effects (`set_issue_needs_input`/коммент/Telegram/park) —
в `stage_engine` (`_decide_analysis_outcome`/`_emit_analysis_*`).
- **Авто-park (DQ-1)** через ось «пауза» ORCH-124 (`db.set_task_paused` при Needs Input) → задача
исключается из «активного» предиката serial-gate, FIFO репо не клинит, пока ждём человека;
**resume + unpark** в `handle_status_start` (analysis-ветка, `clear_task_paused`).