Files
orchestrator/docs/work-items/ORCH-119/01-brd.md
claude-bot 5646552f02
All checks were successful
CI / test (push) Successful in 1m10s
analyst(ET): auto-commit from analyst run_id=783
2026-06-17 14:01:48 +03:00

13 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-119 analysis analyst ready-for-review 2026-06-17 claude-opus-4-8

01 — BRD / Bug-report: ORCH-119 — 00-business-request.md всегда TBD, теряется source-backed контекст запроса

Work Item: ORCH-119 · Repo: orchestrator · Стадия: analysis · Трек: Bug (укороченный маршрут, пропуск стадии architecture)

🐞 Багфикс-трек (ORCH-019). Облегчённый пакет (bug-report + обязательный регресс-тест), но все 4 файла analysis (гейт check_analysis_complete не меняется). Экономия — в пропуске стадии architecture, не в числе файлов.

Эскалация в full-cycle рассмотрена и отклонена. Дефект — контейнерный data-flow + рендеринг, чинится точным зеркалированием уже существующего прецедента tasks.title (персист при создании задачи → чтение в _materialize_deferred_branch). Нет нового компонента, нового QG, политического решения или визуального артефакта → ADR/макет не требуется. Если разработчик в ходе фикса упрётся в архитектурное решение (напр. иной механизм персиста, влияющий на схему/контракты) — снять трек: POST /bug-fast-track/escalate?work_item=ORCH-119 и пометить здесь escalate: full-cycle.


1. Бизнес-контекст и проблема

Симптом (наблюдаемое)

Для каждой созданной задачи файл docs/work-items/<id>/00-business-request.md генерируется с телом раздела «Description» равным буквальному TBD. Реальный текст запроса (описание Plane-issue, обогащённое из Plane API) не попадает в персистентный артефакт. Пример — сам этот work item:

# Business Request: BUG: 00-business-request.md is always TBD, losing source-backed request context
Work Item ID: ORCH-119
## Description
TBD

Последствие (бизнес-боль)

00-business-request.mdточка входа конвейера и источник для analyst (вход стадии analysis, см. PIPELINE_DOCS.md §2). Когда тело всегда TBD:

  • source-backed контекст запроса теряется из durable-артефакта репозитория (остаётся только эфемерно в task_content analyst-job'а и в Plane);
  • последующее чтение work item «глазами» (reviewer, человек, ретроспектива, петля уроков) видит пустой бизнес-запрос — невозможно сверить, ту ли задачу решал конвейер;
  • на self-hosting (orchestrator) задача почти всегда идёт отложенным срезом ветки (serial gate, ORCH-088), где контекст теряется безвозвратно (см. §3, причина B).

Причина симптома (установленный факт, по коду)

src/webhooks/plane.py::_create_initial_docs (строка ~925) хардкодит тело:

content = f"# Business Request: {name}\n\nWork Item ID: {work_item_id}\n\n## Description\n\nTBD\n"

Функция принимает только (repo, branch, work_item_id, name)description ей не передаётся, хотя у вызывающего start_pipeline оно есть в области видимости и уже используется для analyst-job (task_desc, строка ~725: Description:\n{description}). То есть данные есть, но в артефакт не доходят.

Локализация (куда смотреть разработчику) — два пути создания

Путь A — прямой (serial_gate не применим к репо): start_pipeline (src/webhooks/plane.py) имеет description (строки ~518; обогащается из Plane API, ~539551) → зовёт _create_initial_docs(repo, branch, work_item_id, name) (строка ~710) без description. Достаточно дотянуть аргумент.

Путь B — отложенный (критичный для self-hosting) (serial_gate_applies(repo) → для orchestrator): start_pipeline не создаёт ветку/доки (ORCH-088, анти-stale-base); срез релоцирован в src/agents/launcher.py::_materialize_deferred_branch (строки ~514538), который вызывает то же _create_initial_docs, располагая только title из строки tasks (description нигде не персистится). Установленный факт схемы: таблица tasks не имеет колонки description; title персистится через _ensure_column (src/db.py:125) и читается в _spawn/_materialize_deferred_branch именно так. ⇒ Чтобы путь B рендерил описание, description надо сохранить durable при создании задачи (зеркало tasks.title).

Предусловие истинности данных (установленный факт)

QG-0 (_qg0_errors, src/webhooks/plane.py:490) отклоняет создание при description короче 20 символов (строка ~500). ⇒ любая задача, дошедшая до _create_initial_docs, гарантированно имеет непустое осмысленное описание — терять его тем более недопустимо. Защитный fallback на случай пустого описания всё равно предусмотреть (NFR-2).

2. Объём (scope)

В объёме

  • Рендер фактического description (предпочтительно description_stripped, plain-text) в раздел «Description» файла 00-business-request.md — на обоих путях (A прямой, B отложенный).
  • Durable-персист description при создании задачи (зеркало tasks.title), чтобы путь B имел доступ к нему на момент claim.
  • Защитный fallback при отсутствии/пустом описании (без падения).
  • Обязательный регресс-тест (красный до фикса, зелёный после).

Вне объёма

  • Изменение STAGE_TRANSITIONS / QG_CHECKS / check_* / machine-verdict-ключей / семантики гейтов.
  • Изменение поведения serial-gate / отложенного среза ветки ORCH-088 (только дополнить данными, не менять момент/условие среза).
  • Ретро-генерация 00-business-request.md для уже существующих задач (только новые создания).
  • Переформатирование/обогащение структуры самого 00-business-request.md сверх вставки описания (заголовки/название источника остаются как есть).
  • Любая запись в Plane (артефакт пишется только в Gitea-ветку, как сейчас).

3. Заинтересованные стороны

  • Заказчик/оператор — получает читаемый durable бизнес-запрос вместо TBD.
  • Агент analyst и reviewer — могут сверять решённое с запросом по репозиторию.
  • Петля уроков / ретроспектива (ORCH-098) — корректный контекст в артефакте.
  • Приёмку результата выполняет конвейер (reviewer + Quality Gates), не аналитик.

4. Бизнес-требования (BR)

  • BR-1 — Раздел «Description» в 00-business-request.md содержит фактический текст запроса (из Plane-issue, как он используется для analyst-job'а), а не литерал TBD, для вновь создаваемых задач.
  • BR-2 — Поведение одинаково на обоих путях создания: прямом (A) и отложенном срезе ветки (B, self-hosting/serial-gate). Путь B — приоритетный сценарий (доминирует на orchestrator).
  • BR-3 — При отсутствующем/пустом описании артефакт создаётся с явным безопасным fallback- маркером (напр. «описание отсутствует в источнике»), без падения создания задачи.
  • BR-4 — Сохранён состав/имена артефактов: создаётся ровно 00-business-request.md по тому же пути; downstream-конвейер (analyst и далее) не затронут.

5. Нефункциональные требования (NFR)

  • NFR-1 (обратная совместимость / never-break) — изменение аддитивно: создание задачи никогда не должно падать из-за нового рендера/персиста. Любая ошибка обогащения → деградация на безопасное значение (fallback-маркер), а не отказ создания. Идемпотентность _create_initial_docs (422 = уже существует → no-op) сохранена.
  • NFR-2 (целостность данных) — описание рендерится как есть (plain-text description_stripped), без обрезки/искажения; многострочный текст сохраняется. 00-business-request.md — информационный док (гейтом не парсится), поэтому markdown-спецсимволы в описании безопасны для гейтов.
  • NFR-3 (инварианты ORCH-088) — момент и условие отложенного среза ветки не меняются; описание лишь дополнительно переносится через durable-хранилище (зеркало tasks.title), анти-stale-base логика цела.
  • NFR-4 (self-hosting-безопасность) — фикс не деплоит/не рестартит прод, не трогает main, не добавляет сетевых вызовов в горячий claim_next_job.

6. Допущения и ограничения

  • description/description_stripped доступны в start_pipeline и достаточны как источник (уже используются для analyst-job). Plane-обогащение (ORCH «name_missing/desc_missing» блок) остаётся единственным источником описания — новых сетевых обращений не вводим.
  • QG-0 гарантирует ≥20 символов описания для прошедших задач (см. §1) — нормальный путь всегда имеет реальный текст.
  • Персист описания следует установленному прецеденту tasks.title (аддитивная колонка через _ensure_column); это не новое архитектурное решение.

7. Критерии успеха

Новые задачи получают 00-business-request.md с реальным описанием на обоих путях; обязательный регресс-тест красный до фикса и зелёный после; полный pytest tests/ -q зелёный. Детальные PASS/FAIL — 03-acceptance-criteria.md.

8. Риски

  • Путь B забыт (чинят только прямой путь A) → на self-hosting баг остаётся. Митигируется обязательным integration-тестом пути B (TC-03).
  • Регресс схемы/создания задачи при добавлении персиста → митигируется аддитивным _ensure_column и тестом обратной совместимости (TC-05). Детальные тех-риски архитектором не выпускаются (bug-track).