reviewer(ET): auto-commit from reviewer run_id=788
This commit is contained in:
@@ -8,74 +8,88 @@ created_at: 2026-06-17
|
||||
model_used: claude-opus-4-8
|
||||
type: review
|
||||
work_item_id: ORCH-119
|
||||
version: 1
|
||||
version: 2
|
||||
---
|
||||
|
||||
# Review ORCH-119 — source-backed `00-business-request.md` вместо хардкода `TBD`
|
||||
|
||||
## Summary
|
||||
|
||||
Чистый, узко-скоупленный багфикс. Раздел «Description» файла `00-business-request.md`
|
||||
теперь несёт **фактический текст запроса** из Plane-issue вместо литерала `TBD` — на
|
||||
**обоих** путях создания (прямой A + отложенный срез ветки B, ORCH-088, доминирует на
|
||||
self-hosting). Реализация **точно зеркалирует** прецедент `tasks.title`, как и предписал
|
||||
ADR-001: аддитивная колонка `tasks.description` через `_ensure_column`, записываемая
|
||||
**внутри того же атомарного INSERT** `create_task_atomic` (race-safe vs ORCH-053),
|
||||
читаемая в `_spawn` → `_materialize_deferred_branch` на момент claim (без сети в горячем
|
||||
пути, NFR-4). Тело рендерится чистым unit-тестируемым хелпером `_render_business_request`
|
||||
с fail-safe fallback-маркером.
|
||||
Чистый, узко-скоупленный багфикс (Bug-трек). Раздел «Description» файла
|
||||
`00-business-request.md` теперь несёт **фактический текст запроса** из Plane-issue вместо
|
||||
литерала `TBD` — на **обоих** путях создания (прямой A + отложенный срез ветки B, ORCH-088,
|
||||
доминирует на self-hosting). Реализация **точно зеркалирует** прецедент `tasks.title`, как и
|
||||
предписал ADR-001: аддитивная колонка `tasks.description` через `_ensure_column`, записываемая
|
||||
**внутри того же атомарного INSERT** `create_task_atomic` (race-safe vs ORCH-053), читаемая в
|
||||
`_spawn` → `_materialize_deferred_branch` на момент claim (без сети в горячем пути, NFR-4).
|
||||
Тело рендерится чистым unit-тестируемым хелпером `_render_business_request` с fail-safe
|
||||
fallback-маркером.
|
||||
|
||||
Изменение конвейерной машинерии — ноль: ORCH-119-коммит (`4390851`) трогает только
|
||||
`src/db.py`, `src/webhooks/plane.py`, `src/agents/launcher.py`, `CHANGELOG.md` и 2 тест-файла.
|
||||
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict-ключи / базовый
|
||||
`CREATE TABLE tasks` — байт-в-байт. Инварианты ORCH-088 (анти-stale-base) и ORCH-053
|
||||
(атомарный анти-dup-claim) сохранены (правки маркированных блоков аддитивны, с дефолтами;
|
||||
семантика `(row, created)` и момент/условие среза не меняются — трассировка соблюдена).
|
||||
**Это повторный review (v2).** v1 выдал APPROVED с единственным P2: полный прогон был красным
|
||||
из-за **вне-скоупного flake чужой смерженной задачи** `test_orch123_staging_runner_exec.py::test_r2_…`
|
||||
(переиспользовал смерженный в `main` id `ORCH-123`; staging-гейт через `origin/main`-fallback
|
||||
находил реальный `staging_status: SUCCESS`-лог ORCH-123 и делал намеренно-красный гейт зелёным,
|
||||
вызывая `advance`). Developer закрыл это **тест-гермеичностью** (commit `26d6f31`: пин `repos_dir`
|
||||
в изолированный пустой tmp-каталог в autouse-фикстуре `fresh_db`, зеркало уже пиннимого
|
||||
`worktrees_dir`). **Прежний P2 устранён** — повторно проверено локально: red-ранее тест
|
||||
`test_r2_held_deploy_staging_not_rolled_back` теперь зелёный, инвариант ORCH-123 R-2 проверяем
|
||||
order-independently.
|
||||
|
||||
Все 4 оси (ТЗ, ADR, качество, документация) пройдены. Все 8 AC и 4 FR удовлетворены.
|
||||
13/13 тестов ORCH-119 + serial-gate зелёные. Единственный красный в полном прогоне —
|
||||
**доказанно пред-существующий, вне-скоупный flake чужой задачи** (см. P2 ниже), не
|
||||
вносимый ORCH-119.
|
||||
**Скоуп PR (против `origin/main`, merge-base `39fe1a5`):** `src/` — ровно 3 файла, предписанных
|
||||
ТЗ §2 (`webhooks/plane.py`, `agents/launcher.py`, `db.py`); тесты —
|
||||
`test_orch119_business_request.py` (новый, +263), `test_serial_gate_branch.py` (+spy-арг),
|
||||
`test_orch123_staging_runner_exec.py` (+гермеичность, +11); `CHANGELOG.md` + work-item доки.
|
||||
(Гигантский `main...HEAD`-diff — артефакт **устаревшего локального** `main`-рефа `64ba121`;
|
||||
истинный скоуп считается против `origin/main`.)
|
||||
|
||||
## Соответствие ТЗ / AC (ось 1) — PASS
|
||||
|
||||
| AC / FR | Статус | Подтверждение |
|
||||
|---------|--------|---------------|
|
||||
| AC-1 / FR-1 — реальное описание вместо `TBD` | ✅ | `_render_business_request` рендерит тело из `description`; TC-01 (genuine red→green). |
|
||||
| AC-2 / FR-2 — прямой путь A | ✅ | `start_pipeline` передаёт `description` в `_create_initial_docs` (`plane.py:716`); TC-04. |
|
||||
| AC-3 / FR-3 — отложенный путь B / персист | ✅ | персист в атомарном INSERT; чтение `SELECT ..., description` в `_spawn` → 5-й арг `_materialize_deferred_branch`; TC-03. |
|
||||
| AC-4 / FR-4 — fail-safe fallback | ✅ | `_BUSINESS_REQUEST_FALLBACK`, `try/except` → never-raise; TC-02 (`""`/`" "`/`None`). |
|
||||
| AC-5 — гейты/схема не тронуты | ✅ | коммит не касается `stages.py`/`qg/checks.py`; единственная схема — аддитивная `tasks.description`; TC-07. |
|
||||
| AC-6 — идемпотентность / BC | ✅ | Gitea 422 → `return` (тело не перезаписывается); `_ensure_column` no-op; TC-05/TC-06. |
|
||||
| AC-7 — регресс red→green + полный прогон | ⚠️ | TC-01 доказанно red до фикса (функция отсутствовала + `TBD` хардкод на `main`), green после; полный прогон — см. P2 (пред-существующий вне-скоупный flake, не ORCH-119). |
|
||||
| AC-1 / FR-1 — реальное описание вместо `TBD`, header/`Work Item ID` целы | ✅ | `_render_business_request` рендерит тело из `description`; TC-01 (genuine red→green). |
|
||||
| AC-2 / FR-2 — прямой путь A | ✅ | `start_pipeline` передаёт `description` в `_create_initial_docs` (`plane.py:716`); TC-04 (ассертит отсутствие `## Description\n\nTBD\n`). |
|
||||
| AC-3 / FR-3 — отложенный путь B / durable-персист | ✅ | персист в атомарном INSERT (`plane.py:645`); чтение `SELECT …, description` в `_spawn` (`launcher.py:570`) → 5-й арг `_materialize_deferred_branch` (`launcher.py:594`); TC-03. |
|
||||
| AC-4 / FR-4 — fail-safe fallback | ✅ | `_BUSINESS_REQUEST_FALLBACK`, `try/except` → never-raise; TC-02 (`""`/`" "`/`"\n\t"`/`None`). |
|
||||
| AC-5 — гейты/схема не тронуты | ✅ | коммит не касается `stages.py`/`qg/checks.py`; единственная схема — аддитивная `tasks.description`, базовый `CREATE TABLE tasks` цел; TC-07. |
|
||||
| AC-6 — идемпотентность / BC | ✅ | Gitea 422 → no-op (тело не перезаписывается); `_ensure_column` no-op; TC-05/TC-06. |
|
||||
| AC-7 — регресс red→green + полный прогон зелёный | ✅ | TC-01 red до фикса (функция отсутствовала + `TBD` хардкод на `main`), green после; **полный прогон теперь зелёный** (прежний P2-flake устранён `26d6f31`; commit-протокол: 2173 passed). |
|
||||
| AC-8 — сопровождение | ✅ | `CHANGELOG.md` содержит запись ORCH-119. |
|
||||
|
||||
`description` определён в scope `start_pipeline` (`plane.py:518`, обогащается из Plane API
|
||||
`:540–545`) **до** обоих call-site (`:645`, `:716`) — NameError исключён; персистится тот же
|
||||
enriched-текст, что уходит analyst-job (`:731`) — консистентно.
|
||||
|
||||
## Соответствие ADR (ось 2) — PASS
|
||||
|
||||
- **D1** (аддитивная колонка в атомарном INSERT) — реализовано буквально: `_ensure_column(conn,"tasks","description","TEXT")` рядом с `tasks.title`; запись встроена в существующий INSERT `create_task_atomic`, не отдельным UPDATE (нет race-окна vs ORCH-053). ✅
|
||||
- **D1** (аддитивная колонка в атомарном INSERT) — реализовано буквально: `_ensure_column(conn,"tasks","description","TEXT")` рядом с `tasks.title`; запись встроена в существующий INSERT `create_task_atomic`, не отдельным UPDATE → нет race-окна vs ORCH-053. ✅
|
||||
- **D2** (чистый рендер-хелпер + проброс на обоих путях) — `_render_business_request` чистый/network-free; проброс A и B. ✅
|
||||
- **D3** (fail-safe fallback + идемпотентность) — маркер + never-raise + 422-no-op. ✅
|
||||
- **D4** (инварианты) — ORCH-088 момент/условие среза не меняются (только источник данных), ORCH-053 семантика цела, гейты байт-в-байт, без kill-switch (фикс дефекта). ✅
|
||||
- **Трассировка (TRACEABILITY):** правки блоков с маркерами ORCH-088 (`_materialize_deferred_branch`) и ORCH-053 (`create_task_atomic`) сверены — аддитивные, с дефолтами, зафиксированные инварианты не сломаны; комментарии кода корректно ссылаются на оба ADR. ✅
|
||||
- **D4** (инварианты) — ORCH-088 момент/условие отложенного среза не меняются (дополняется только источник данных), ORCH-053 семантика `(row, created)` цела, гейты байт-в-байт, без kill-switch (обосновано — фикс дефекта). ✅
|
||||
- **Трассировка (TRACEABILITY):** правки блоков с маркерами **ORCH-088** (`_materialize_deferred_branch`) и **ORCH-053** (`create_task_atomic`) сверены — аддитивные, с дефолтами; зафиксированные инварианты не сломаны; комментарии кода корректно ссылаются на оба ADR. ✅
|
||||
- Сквозной (global) ADR не требуется — локальное аддитивное решение по прецеденту. ✅
|
||||
|
||||
## Качество кода (ось 3) — PASS
|
||||
|
||||
- Чистый, network-free, unit-тестируемый хелпер; docstrings на всех новых/изменённых функциях. ✅
|
||||
- never-raise контракт соблюдён (`try/except` в рендере; создание задачи не падает). ✅
|
||||
- BC: все добавленные параметры аддитивны с дефолтами; единственный прочий потребитель (serial-gate spy в `test_serial_gate_branch.py`) синхронно обновлён. ✅
|
||||
- **Багфикс-регресс (ORCH-019 / BR-4):** TC-01 — настоящий фиксатор дефекта (red до фикса: `_render_business_request` отсутствовал + `_create_initial_docs` хардкодил `TBD` на `main`; green после). Подтверждено `git show main:src/webhooks/plane.py`. ✅
|
||||
- Тесты содержательные: 7 TC покрывают регресс, fallback (4 параметра), оба пути, schema-BC, идемпотентность 422, multiline/спецсимволы, анти-регресс гейтов. ✅
|
||||
- BC: все добавленные параметры аддитивны с дефолтами; единственный прочий потребитель сигнатуры (serial-gate spy в `test_serial_gate_branch.py`) синхронно обновлён. ✅
|
||||
- **Багфикс-регресс (ORCH-019 / BR-4) — фиксатор присутствует:** TC-01 настоящий red до фикса (`_render_business_request` отсутствовал + `_create_initial_docs` хардкодил `TBD` на `main`), green после; усилен TC-04 (бьёт реальный баг-путь `_create_initial_docs`). ✅
|
||||
- Тесты содержательные: 7 TC покрывают регресс, fallback (4 параметра), оба пути, schema-BC, идемпотентность 422, multiline/спецсимволы verbatim, анти-регресс гейтов. ✅
|
||||
- Гермеичность-фикс `test_orch123` (`26d6f31`) — test-only, продкод/семантика гейтов не тронуты; делает чужой тест order-independent.
|
||||
- **Локальная проверка:** `tests/test_orch119_business_request.py` — **10 passed**; ранее красный `test_orch123…::test_r2_held_deploy_staging_not_rolled_back` — **1 passed**. ✅
|
||||
|
||||
## Документация (ось 4) — PASS
|
||||
|
||||
Изменён `src/` → проверка обязательна. Документация обновлена в том же PR:
|
||||
- **`CHANGELOG.md`** — подробная запись ORCH-119 (AC-8). ✅
|
||||
- **ADR-001** (`06-adr/ADR-001-source-backed-business-request-doc.md`) + **`08-data-requirements.md`** — присутствуют, исчерпывающие. ✅
|
||||
- **Центрального schema-дока колонок `tasks` нет** — конвенция проекта: per-task скалярные колонки документируются в ADR задачи + data-requirements + CHANGELOG (так же оформлены `tasks.title` / `tasks.track` / `tasks.cancelled_at`). ORCH-119 ей следует. ✅
|
||||
- **Витрина `docs/overview/` (ORCH-011):** `tech-agents.md` по-прежнему верно указывает `00-business-request.md` как вход аналитика; `tech-data-model.md` описывает `tasks` концептуально (без перечня колонок) — не устаревает добавлением колонки. Обновление не требуется. ✅
|
||||
- **ADR-001** (`06-adr/ADR-001-source-backed-business-request-doc.md`) + **`08-data-requirements.md`** (документирует схему `tasks.description`) — присутствуют, исчерпывающи. ✅
|
||||
- **API** — изменений нет (ТЗ §4) → таблица API в `docs/architecture/README.md` обновления не требует. ✅
|
||||
- **Стадии/QG** — не тронуты → `docs/architecture/README.md` / `internals.md` обновления не требуют. ✅
|
||||
- **Витрина `docs/overview/` (ORCH-011):** `tech-agents.md` по-прежнему верно указывает `00-business-request.md` как вход аналитика; `tech-data-model.md` описывает `tasks` концептуально (без перечня колонок) — не устаревает добавлением колонки; смена **тела** артефакта (внутренняя деталь генерации) описанных стадий/гейтов/агентов/способностей не меняет. Обновление не требуется. ✅
|
||||
- **`README.md` «Известные ограничения» (ORCH-079):** TBD-баг `00-business-request.md` **не** числится среди открытых ограничений (Telegram-48h / intra-repo deps / batch-автоном) — закрывать/снимать нечего, обновление README не требуется. ✅
|
||||
- **`PIPELINE_DOCS.md` / `HANDOFF_PROTOCOL.md`:** описывают артефакт по владельцу/гейт-статусу (`_create_initial_docs`, информационный, не парсится) — продюсер и статус не изменились, не устаревают. ✅
|
||||
- **Центрального schema-дока колонок `tasks` нет** — конвенция проекта: per-task скалярные колонки документируются ADR задачи + data-requirements + CHANGELOG (так же оформлены `tasks.title` / `tasks.track` / `tasks.cancelled_at`). ORCH-119 ей следует. ✅
|
||||
|
||||
**Итог по документации:** при изменении `src/` документация обновлена в том же PR — P0 «`src/` изменён, документация не обновлена» **не наступает**.
|
||||
|
||||
## Findings
|
||||
|
||||
@@ -85,31 +99,28 @@ ADR-001: аддитивная колонка `tasks.description` через `_en
|
||||
### P1 — Must fix
|
||||
- Нет.
|
||||
|
||||
### P2 — Should fix (вне скоупа ORCH-119 — НЕ блокер; рекомендация отдельной задачи)
|
||||
- [ ] **Полный `pytest tests/ -q` красный: 1 fail** — `tests/test_orch123_staging_runner_exec.py::test_r2_held_deploy_staging_not_rolled_back` (2172 passed, детерминированно). Номинально это задевает букву AC-7 («полный прогон зелёный»), но провал **доказанно пред-существующий и полностью независимый от ORCH-119**:
|
||||
- **Не ORCH-119:** ORCH-119-коммит `4390851` не трогает `stage_engine` / `staging_runner` / `qg/checks` / `15-staging-log` / конфиг, читаемый `check_staging_status`. Тест-файл ORCH-119 **не** загрязняет ORCH-123 (вместе 11/11 зелёных); провал воспроизводится при **полностью деселектнутом** ORCH-119.
|
||||
- **Корень — isolation-дефект чужого (уже смерженного) теста ORCH-123:** тест переиспользует `work_item_id="ORCH-123"`, а в дереве лежит **закоммиченный** артефакт `docs/work-items/ORCH-123/15-staging-log.md` (приехал при мерже ORCH-123). При полном импорте сьюта (module-level env/CWD-мутации множества тест-файлов) `check_staging_status` резолвит этот закоммиченный лог → гейт «зеленеет» → `advance` вызывается → `assert result is None` падает. Файл ORCH-123 **изолированно** зелёный (26/26).
|
||||
- **Не блокирует пайплайн в реальной среде:** ORCH-116 смержен в `main` **после** ORCH-123 и прошёл весь конвейер (включая `testing`/детерминированный test-runner ORCH-116) при уже присутствующем `15-staging-log.md` ORCH-123 → flake не воспроизводится в реальном test-runner/CI, это артефакт локального порядка импорта полного `tests/`.
|
||||
- **Действие:** завести отдельный bug на test-hygiene ORCH-123 (тест не должен переиспользовать живой `work_item_id` с закоммиченными артефактами и зависеть от глобального CWD/конфига). Править здесь нельзя — чужой артефакт стадии, вне скоупа ORCH-119 (правило «не править артефакты других этапов»).
|
||||
### P2 — Should fix
|
||||
- Нет. *(Прежний P2 v1 — красный полный прогон из-за вне-скоупного flake `test_orch123` — **устранён** в этом же PR гермеичность-фиксом `26d6f31`; полный прогон зелёный.)*
|
||||
|
||||
### P3 — Nice-to-have
|
||||
- [ ] Тест-файл `tests/test_orch119_business_request.py` мутирует `os.environ` (`ORCH_DB_PATH`/`ORCH_REPOS_DIR`) на уровне модуля (импорт) — добавляет к общей import-pollution-поверхности сьюта. Соответствует существующей конвенции многих тест-файлов проекта (не новый грех), на ORCH-119-провалы не влияет; на будущее — скоупить через фикстуру.
|
||||
### P3 — Nice-to-have (не блокирует)
|
||||
- [ ] `tests/test_orch119_business_request.py` мутирует `os.environ` (`ORCH_DB_PATH`/`ORCH_REPOS_DIR`) на уровне модуля — добавляет к общей import-pollution-поверхности сьюта. Соответствует существующей конвенции многих тест-файлов проекта (не новый грех), на корректность не влияет; на будущее — скоупить через фикстуру.
|
||||
- [ ] `_render_business_request`: `try/except Exception` вокруг `(description or "").strip()` — `.strip()` на строке не бросает, ветка недостижима. Намеренный never-break «belt-and-suspenders» в стиле кодбейза; оставить как есть допустимо.
|
||||
|
||||
## Документация
|
||||
|
||||
**Статус: обновлена в том же PR — достаточно.** `CHANGELOG.md` (AC-8) + ADR-001 +
|
||||
`08-data-requirements.md` — присутствуют и исчерпывающи. Витрина `docs/overview/`,
|
||||
обзорный `README.md` («Известные ограничения»), `PIPELINE_DOCS.md`/`HANDOFF_PROTOCOL.md`
|
||||
проверены явно — не устаревают (артефакт остаётся информационным, продюсер/владелец/гейт-статус
|
||||
не изменились; TBD-баг не числился среди открытых ограничений). Центрального schema-дока
|
||||
колонок `tasks` нет — аддитивная колонка документирована по конвенции (ADR + data-requirements +
|
||||
CHANGELOG, как `tasks.title`/`track`/`cancelled_at`). **Необновлённой обязательной документации не найдено.**
|
||||
`08-data-requirements.md` (схема `tasks.description`) — присутствуют и исчерпывающи. Витрина
|
||||
`docs/overview/`, обзорный `README.md` («Известные ограничения»),
|
||||
`PIPELINE_DOCS.md`/`HANDOFF_PROTOCOL.md` проверены явно — не устаревают (артефакт остаётся
|
||||
информационным, продюсер/владелец/гейт-статус не изменились; TBD-баг не числился среди открытых
|
||||
ограничений). Центрального schema-дока колонок `tasks` нет — аддитивная колонка документирована
|
||||
по конвенции (ADR + data-requirements + CHANGELOG, как `tasks.title`/`track`/`cancelled_at`).
|
||||
**Необновлённой обязательной документации не найдено.**
|
||||
|
||||
## Вердикт
|
||||
|
||||
**APPROVED.** Нет P0/P1. Все AC/FR/ADR удовлетворены; реализация — точное зеркало
|
||||
**APPROVED.** Нет P0/P1/P2. Все AC/FR/ADR удовлетворены; реализация — точное зеркало
|
||||
одобренного прецедента с нулевым касанием конвейерной машинерии и сохранёнными инвариантами
|
||||
ORCH-088/ORCH-053. Единственный красный полного прогона — доказанно пред-существующий,
|
||||
детерминированный, вне-скоупный flake чужой смерженной задачи (ORCH-123), который ORCH-119 не
|
||||
вносил и не может починить в своём скоупе; дух AC-7 (отсутствие внесённых регрессий, собственные
|
||||
тесты зелёные) соблюдён.
|
||||
ORCH-088/ORCH-053; обязательный регресс-тест-фиксатор присутствует (red→green). Прежний
|
||||
вне-скоупный flake (ORCH-123) устранён в этом же PR, полный прогон зелёный. Документация
|
||||
синхронна. Готово к стадии `testing`.
|
||||
|
||||
Reference in New Issue
Block a user