87 lines
8.2 KiB
Markdown
87 lines
8.2 KiB
Markdown
---
|
||
work_item: ORCH-119
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-17
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 02 — ТЗ (TRZ): ORCH-119 — source-backed генерация `00-business-request.md`
|
||
|
||
Work Item: **ORCH-119** · Repo: **orchestrator** · Стадия: analysis · Трек: **Bug**
|
||
|
||
> Bug-track: стадия `architecture` пропускается, поэтому ТЗ конкретизирует затрагиваемые модули и
|
||
> требование к данным. ТЗ описывает **что должно измениться и где**; точная форма реализации (имена
|
||
> символов, сигнатуры) — за разработчиком, в рамках указанного прецедента `tasks.title`.
|
||
|
||
## 1. Сводка изменения
|
||
Source-backed `description` (текст запроса из Plane-issue) должен попадать в раздел «Description»
|
||
файла `00-business-request.md` вместо хардкода `TBD`. Для этого: (1) `description` рендерится в тело
|
||
артефакта; (2) `description` **персистится при создании задачи** (зеркало `tasks.title`), чтобы
|
||
отложенный путь среза ветки (ORCH-088, доминирует на self-hosting) имел к нему доступ на момент claim.
|
||
Изменение аддитивно, never-break, fail-safe.
|
||
|
||
## 2. Задействованные модули / пути
|
||
| Путь | Действие |
|
||
|------|----------|
|
||
| `src/webhooks/plane.py` | изменить — `_create_initial_docs`: принять `description`, рендерить его в тело вместо `TBD`; рекомендуется выделить чистый рендер-хелпер (напр. `_render_business_request(work_item_id, name, description) -> str`) для unit-тестируемости без сети |
|
||
| `src/webhooks/plane.py` | изменить — `start_pipeline`: (а) прямой путь — передать `description` в `_create_initial_docs` (строка ~710); (б) персистить `description` при создании задачи (рядом со стампом `title`) |
|
||
| `src/agents/launcher.py` | изменить — `_materialize_deferred_branch`: прочитать персистнутое `description` из строки `tasks` и передать в `_create_initial_docs` (зеркало того, как уже читается/используется `title`) |
|
||
| `src/db.py` | изменить — аддитивная колонка `tasks.description` через `_ensure_column` (паттерн `tasks.title`, строка ~125); хелпер чтения/записи при необходимости; **не менять** базовый `CREATE TABLE tasks` |
|
||
| `tests/test_orch119_business_request.py` | создать — регресс + edge-кейсы (см. `04-test-plan.yaml`) |
|
||
| `CHANGELOG.md` | изменить — запись о фиксе (правило сопровождения) |
|
||
|
||
## 3. Функциональные требования
|
||
|
||
### FR-1 — Рендер описания в артефакт (BR-1)
|
||
Тело раздела «Description» в `00-business-request.md` = фактический `description` (предпочтительно
|
||
`description_stripped`, plain-text), без обрезки/искажения, многострочный текст сохраняется. Заголовок
|
||
(`# Business Request: {name}`) и `Work Item ID` — без изменений.
|
||
|
||
### FR-2 — Прямой путь (BR-2, путь A)
|
||
`start_pipeline` при `serial_gate` НЕ применим → передаёт `description` в `_create_initial_docs`;
|
||
артефакт создаётся с реальным описанием в одном вызове.
|
||
|
||
### FR-3 — Отложенный путь / персист (BR-2, путь B — критичный)
|
||
`description` персистится durable при создании задачи (зеркало `tasks.title`).
|
||
`_materialize_deferred_branch` читает его из строки `tasks` и передаёт в `_create_initial_docs`, так
|
||
что артефакт, материализованный на момент claim analyst-job, содержит реальное описание. Момент/условие
|
||
отложенного среза (ORCH-088) **не меняются** — только источник данных дополняется (NFR-3).
|
||
|
||
### FR-4 — Fallback и устойчивость (BR-3, NFR-1)
|
||
Пустое/отсутствующее/нечитаемое `description` → явный безопасный маркер (напр.
|
||
`_(описание отсутствует в источнике)_`), **без падения** создания задачи. Любая ошибка рендера/чтения
|
||
персиста → деградация на fallback-маркер, не отказ. Идемпотентность сохранена: повторная
|
||
материализация (Gitea 422 = файл уже существует) → no-op, ранее записанное тело не перезаписывается.
|
||
|
||
## 4. Изменения API
|
||
Нет. Эндпоинты не добавляются и не меняются. Запись артефакта остаётся в Gitea-ветку через
|
||
существующий `contents` API; в Plane ничего не пишется.
|
||
|
||
## 5. Изменения схемы БД
|
||
Аддитивная колонка **`tasks.description TEXT`** через `_ensure_column` (идемпотентный ALTER, no-op на
|
||
существующей таблице — safe на боевой БД), строго по прецеденту `tasks.title`. Базовый
|
||
`CREATE TABLE tasks` не трогается. Индексы не требуются. Для уже существующих задач колонка `NULL`
|
||
(ретро-генерация — вне объёма).
|
||
|
||
> Допустимая эквивалентная реализация (на усмотрение разработчика): переиспользовать уже доступный
|
||
> в `_spawn`/`_materialize_deferred_branch` источник данных, если он durable до момента claim. Если
|
||
> такой надёжно нет — канон именно колонка `tasks.description` (как `tasks.title`). Решение не должно
|
||
> вводить сетевой вызов в горячий путь claim (NFR-4).
|
||
|
||
## 6. Требования к новым/изменённым QG checks
|
||
Нет. `00-business-request.md` — информационный документ (гейтом не парсится, `PIPELINE_DOCS.md` §2–§3).
|
||
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключи — байт-в-байт не трогаются.
|
||
|
||
## 7. Совместимость / регресс
|
||
- **Обратная совместимость:** аддитивная колонка + аддитивный аргумент с дефолтом; существующие задачи
|
||
и enduro-trails не затронуты (для них тоже просто рендерится их описание — улучшение, не регресс).
|
||
- **Kill-switch:** отдельный флаг не требуется — изменение это исправление дефекта (улучшение
|
||
«всегда»), не рискованная фича; безопасность обеспечивается fail-safe fallback и never-break-контрактом.
|
||
- **Обратимость:** revert PR полностью возвращает прежнее поведение (колонка остаётся, инертна).
|
||
- **Self-hosting:** не деплоит/не рестартит прод, не трогает `main`, без новых сетевых вызовов в
|
||
`claim_next_job` (NFR-4). Анти-stale-base инвариант ORCH-088 цел (NFR-3) — перед правкой
|
||
`_materialize_deferred_branch`/отложенного среза свериться с `docs/work-items/ORCH-088/06-adr/`
|
||
(TRACEABILITY).
|