analyst(ET): auto-commit from analyst run_id=783
All checks were successful
CI / test (push) Successful in 1m10s
All checks were successful
CI / test (push) Successful in 1m10s
This commit is contained in:
151
docs/work-items/ORCH-119/01-brd.md
Normal file
151
docs/work-items/ORCH-119/01-brd.md
Normal file
@@ -0,0 +1,151 @@
|
||||
---
|
||||
work_item: ORCH-119
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-17
|
||||
model_used: 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) **хардкодит** тело:
|
||||
```python
|
||||
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,
|
||||
~539–551) → зовёт `_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` (строки ~514–538), который вызывает то же
|
||||
`_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).
|
||||
86
docs/work-items/ORCH-119/02-trz.md
Normal file
86
docs/work-items/ORCH-119/02-trz.md
Normal file
@@ -0,0 +1,86 @@
|
||||
---
|
||||
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).
|
||||
109
docs/work-items/ORCH-119/03-acceptance-criteria.md
Normal file
109
docs/work-items/ORCH-119/03-acceptance-criteria.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
work_item: ORCH-119
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-17
|
||||
model_used: claude-opus-4-8
|
||||
---
|
||||
|
||||
# 03 — Критерии приёмки: ORCH-119 — source-backed `00-business-request.md`
|
||||
|
||||
Work Item: **ORCH-119** · Repo: **orchestrator** · Стадия: analysis · Трек: **Bug**
|
||||
|
||||
Формат: каждый критерий — **PASS** (что должно быть истинно для приёмки) и **FAIL** (что считается
|
||||
провалом). Reviewer/тесты проверяют буквально по файлам репозитория.
|
||||
|
||||
---
|
||||
|
||||
## AC-1 — Реальное описание в артефакте вместо `TBD`
|
||||
|
||||
**Условие:** при создании задачи с непустым описанием раздел «Description» файла
|
||||
`00-business-request.md` содержит фактический текст запроса.
|
||||
- **PASS:** тело раздела «Description» равно переданному `description` (plain-text); подстрока с
|
||||
реальным текстом присутствует; литерал `TBD` как ВСЁ тело раздела отсутствует.
|
||||
- **FAIL:** раздел «Description» = `TBD` (или иной плейсхолдер) при наличии непустого описания на входе.
|
||||
|
||||
---
|
||||
|
||||
## AC-2 — Прямой путь создания (путь A)
|
||||
|
||||
**Условие:** когда `serial_gate` не применим, `start_pipeline` передаёт `description` в
|
||||
`_create_initial_docs`.
|
||||
- **PASS:** артефакт, созданный прямым путём, содержит реальное описание (см. AC-1).
|
||||
- **FAIL:** на прямом пути `description` не доходит до артефакта (остаётся `TBD`).
|
||||
|
||||
---
|
||||
|
||||
## AC-3 — Отложенный путь / self-hosting (путь B, критичный)
|
||||
|
||||
**Условие:** когда `serial_gate_applies(repo)` (напр. `orchestrator`), описание персистится при
|
||||
создании задачи и рендерится при материализации ветки на момент claim
|
||||
(`launcher._materialize_deferred_branch`).
|
||||
- **PASS:** артефакт, материализованный отложенным путём, содержит реальное описание; описание
|
||||
durable-доступно из строки `tasks` (не теряется между созданием задачи и claim).
|
||||
- **FAIL:** на отложенном пути описание утрачено → артефакт = `TBD`; либо описание нигде не
|
||||
персистится до момента claim.
|
||||
|
||||
---
|
||||
|
||||
## AC-4 — Безопасный fallback при пустом описании
|
||||
|
||||
**Условие:** описание отсутствует/пустое/нечитаемо.
|
||||
- **PASS:** артефакт создаётся с явным безопасным fallback-маркером (не «голый» `TBD`-баг), создание
|
||||
задачи не падает.
|
||||
- **FAIL:** создание задачи падает/бросает исключение, либо тихо теряет контекст без маркера.
|
||||
|
||||
---
|
||||
|
||||
## AC-5 — Никаких изменений гейтов / схемы сверх аддитивной колонки
|
||||
|
||||
**Условие:** правка не трогает машинерию конвейера.
|
||||
- **PASS:** `STAGE_TRANSITIONS`, реестр `QG_CHECKS`, имена/семантика `check_*`, machine-verdict-ключи
|
||||
— байт-в-байт прежние; единственное изменение схемы — аддитивная `tasks.description` (или
|
||||
эквивалент без сетевого вызова в claim); базовый `CREATE TABLE tasks` не тронут.
|
||||
- **FAIL:** изменены гейты/переходы/вердикт-ключи; неаддитивная миграция; сетевой вызов добавлен в
|
||||
`claim_next_job`.
|
||||
|
||||
---
|
||||
|
||||
## AC-6 — Идемпотентность и обратная совместимость
|
||||
|
||||
**Условие:** повторная материализация и существующие задачи.
|
||||
- **PASS:** повторный вызов (`_create_initial_docs`, Gitea 422) — no-op, не перезаписывает тело;
|
||||
`_ensure_column` идемпотентен (no-op при существующей колонке); enduro-trails и прочие репо не
|
||||
затронуты негативно.
|
||||
- **FAIL:** повторная материализация затирает/дублирует артефакт; миграция падает на боевой БД;
|
||||
регресс для других репо.
|
||||
|
||||
---
|
||||
|
||||
## AC-7 — Обязательный регресс-тест (red→green) и зелёный полный прогон
|
||||
|
||||
**Условие:** дефект зафиксирован тестом.
|
||||
- **PASS:** `tests/test_orch119_business_request.py::TC-01` падает на коде ДО фикса (доказывает баг) и
|
||||
проходит ПОСЛЕ; полный `pytest tests/ -q` зелёный.
|
||||
- **FAIL:** регресс-теста нет, либо он зелёный и до фикса (ничего не доказывает), либо полный прогон
|
||||
красный.
|
||||
|
||||
---
|
||||
|
||||
## AC-8 — Сопровождение
|
||||
|
||||
**Условие:** документация/история обновлены в том же PR.
|
||||
- **PASS:** `CHANGELOG.md` содержит запись о фиксе ORCH-119.
|
||||
- **FAIL:** изменён функционал без обновления `CHANGELOG.md`.
|
||||
|
||||
---
|
||||
|
||||
## Сводная матрица AC ↔ FR/BR
|
||||
| AC | Покрывает |
|
||||
|----|-----------|
|
||||
| AC-1 | BR-1 / FR-1 |
|
||||
| AC-2 | BR-2 / FR-2 |
|
||||
| AC-3 | BR-2 / FR-3 / NFR-3 |
|
||||
| AC-4 | BR-3 / FR-4 / NFR-1 |
|
||||
| AC-5 | BR-4 / NFR-4 |
|
||||
| AC-6 | NFR-1 / FR-4 |
|
||||
| AC-7 | BR-1..BR-3 (доказательство) |
|
||||
| AC-8 | правило сопровождения |
|
||||
64
docs/work-items/ORCH-119/04-test-plan.yaml
Normal file
64
docs/work-items/ORCH-119/04-test-plan.yaml
Normal file
@@ -0,0 +1,64 @@
|
||||
work_item: ORCH-119
|
||||
stage: analysis
|
||||
author_agent: analyst
|
||||
status: ready-for-review
|
||||
created_at: 2026-06-17
|
||||
model_used: claude-opus-4-8
|
||||
title: "Source-backed генерация 00-business-request.md (фикс хардкода TBD)"
|
||||
framework: pytest
|
||||
scope: >
|
||||
Покрывается: рендер фактического description в 00-business-request.md вместо литерала TBD на обоих
|
||||
путях создания (прямой A и отложенный срез ветки B / self-hosting ORCH-088), durable-персист
|
||||
description (зеркало tasks.title), безопасный fallback при пустом описании, аддитивность схемы и
|
||||
обратная совместимость. ВНЕ покрытия: реальные сетевые вызовы Gitea/Plane (мокаются), ретро-генерация
|
||||
артефактов для уже существующих задач.
|
||||
notes: >
|
||||
TC-01 — ОБЯЗАТЕЛЬНЫЙ регресс-тест: красный на коде ДО фикса (доказывает баг хардкода TBD), зелёный
|
||||
ПОСЛЕ. Сетевые вызовы (_create_gitea_branch / _create_initial_docs httpx, Plane API) мокаются —
|
||||
тесты без сети/прода. Рекомендуется тестировать чистый рендер-хелпер (_render_business_request) на
|
||||
уровне unit, а пути A/B — на уровне integration с моками httpx и временной SQLite-БД. Полный регресс
|
||||
pytest tests/ -q должен оставаться зелёным. Перед правкой отложенного среза ветки свериться с
|
||||
docs/work-items/ORCH-088/06-adr/ (анти-stale-base инвариант, TRACEABILITY).
|
||||
|
||||
tests:
|
||||
- id: TC-01
|
||||
type: unit
|
||||
description: "ОБЯЗАТЕЛЬНЫЙ РЕГРЕСС. Рендер 00-business-request.md при непустом description содержит фактический текст запроса в разделе 'Description' и НЕ равен литералу TBD. Красный до фикса (хардкод TBD), зелёный после."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-02
|
||||
type: unit
|
||||
description: "Fallback: при пустом/whitespace/None description рендер даёт явный безопасный маркер (напр. 'описание отсутствует в источнике'), функция не бросает исключение."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-03
|
||||
type: integration
|
||||
description: "Путь B (отложенный, self-hosting): description персистнут при создании задачи и доступен из строки tasks; launcher._materialize_deferred_branch рендерит реальное описание в артефакт (мок httpx; description не теряется между созданием и claim)."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-04
|
||||
type: integration
|
||||
description: "Путь A (прямой, serial_gate не применим): start_pipeline передаёт description в _create_initial_docs; артефакт содержит реальное описание (мок httpx, перехват записанного content)."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-05
|
||||
type: integration
|
||||
description: "Обратная совместимость схемы: init_db на пустой БД и на БД со старой таблицей tasks (без колонки description) проходит; _ensure_column идемпотентен (повторный init_db — no-op); создание задачи не падает."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-06
|
||||
type: unit
|
||||
description: "Целостность данных: многострочное описание со спецсимволами markdown рендерится без обрезки/искажения; идемпотентность — повторная материализация (Gitea 422) не перезаписывает уже записанное тело."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
|
||||
- id: TC-07
|
||||
type: unit
|
||||
description: "Анти-регресс гейтов: STAGE_TRANSITIONS / реестр QG_CHECKS / имена check_* импортируются без изменений (00-business-request.md остаётся информационным, не гейтится)."
|
||||
module: tests/test_orch119_business_request.py
|
||||
expected: PASS
|
||||
Reference in New Issue
Block a user