122 lines
10 KiB
Markdown
122 lines
10 KiB
Markdown
---
|
||
verdict: APPROVED
|
||
work_item: ORCH-027
|
||
stage: review
|
||
author_agent: reviewer
|
||
status: approved
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
type: review
|
||
work_item_id: ORCH-027
|
||
version: 2
|
||
---
|
||
|
||
# Review ORCH-027 — Code coverage как гейт
|
||
|
||
## Summary
|
||
|
||
Дисциплинированная реализация детерминированного coverage-гейта строго по образцу
|
||
security/merge/image-freshness под-гейтов. Соответствие ТЗ/ADR — полное; код качественный,
|
||
тесты содержательны (`test_coverage_gate.py` — 30 тестов; **полный регресс `tests/ -q`
|
||
зелёный: 1466 passed**); документация обновлена исчерпывающе.
|
||
|
||
**Единственный прежний блокер закрыт.** Ревизия v1 выносила P1 за повреждённую (дословно
|
||
продублированную) запись ORCH-095 в `CHANGELOG.md` — коммит `75c33ab docs(changelog): repair
|
||
duplicated ORCH-095 entry body` устранил дубль: тело bullet ORCH-095 теперь присутствует ровно
|
||
один раз (`git revert occurrences on line 16: 1`), артефакт чужой задачи восстановлен. Новых
|
||
P0/P1 не выявлено.
|
||
|
||
Проверено: 4 оси (ТЗ / ADR / качество кода / документация) + трассировка маркеров + полный
|
||
прогон тест-сьюта.
|
||
|
||
## Findings
|
||
|
||
### P0 — Blocker
|
||
- (нет)
|
||
|
||
### P1 — Must fix
|
||
- (нет) — прежний P1 (дубль записи ORCH-095 в CHANGELOG) исправлен коммитом `75c33ab`.
|
||
|
||
### P2 — Should fix
|
||
- [ ] **Несоответствие формулировки ADR-001 D7 фактическому артефакту: 6-польная схема 52c
|
||
не эмитится.** `ADR-001-coverage-gate.md` D7 утверждает: «Артефакт несёт **аддитивно**
|
||
обязательную 6-польную схему 52c, не трогая `coverage_status:`». Фактически и генератор
|
||
(`coverage_gate.render_coverage_report`), и скелет `docs/_templates/18-coverage-report.md`
|
||
эмитят только `coverage_status`/`work_item` + coverage-поля; отсутствуют 5 из 6 полей схемы
|
||
52c (`stage`/`author_agent`/`status`/`created_at`/`model_used`). **Почему не блокер:** (а)
|
||
TRZ §6 формулирует это условно («*Если* отчёт несёт обязательную 6-польную схему 52c —
|
||
добавить её аддитивно»), (б) валидация схемы warning-only по умолчанию
|
||
(`frontmatter_validation_strict=False`), (в) гейт-генерируемые артефакты (прецедент
|
||
`17-security-report.md`) исторически несут лишь свой machine-key — эпик 52c (ORCH-077)
|
||
скоупил схему на 6 агент-промптов, не на машинные отчёты. Машинный вердикт читается из
|
||
`coverage_status:` корректно, контракт не нарушен. **Действие (на усмотрение, не блокирует
|
||
приёмку):** привести формулировку D7 к факту (отчёт несёт `coverage_status:` + coverage-поля,
|
||
без полной 52c-схемы) ЛИБО добавить 5 полей в генератор+шаблон.
|
||
|
||
## Документация
|
||
|
||
**Статус: обновлена исчерпывающе** (golden source синхронизирован в том же PR, AC-10 PASS):
|
||
|
||
- `docs/architecture/README.md` — реестр `QG_CHECKS` дополнен `check_coverage_gate (ORCH-027)`;
|
||
добавлен раздел «Coverage-гейт: защита от деградации покрытия» (точка/порядок, измерение,
|
||
чистая функция, baseline+ratchet, условность/fail-open, артефакт/наблюдаемость). ✅
|
||
- `docs/_standards/PIPELINE_DOCS.md` — диапазон доков `…18-coverage-report.md`; строка карты
|
||
`стадия→агент→документ→гейт→machine-key` + строка таблицы вердикт-парсеров
|
||
(`coverage_status:` → `check_coverage_gate`). ✅
|
||
- `docs/_templates/18-coverage-report.md` — скелет с frontmatter зарегистрирован. ✅
|
||
- `docs/work-items/ORCH-027/06-adr/ADR-001-coverage-gate.md` (D1…D8) +
|
||
сквозной `docs/architecture/adr/adr-0029-coverage-gate.md`. ✅
|
||
- `CHANGELOG.md` — детальная корректная запись ORCH-027; повреждение соседней записи ORCH-095
|
||
устранено (v1-P1 закрыт). ✅
|
||
- `CLAUDE.md` — паспортный блок «Гейт покрытия тестами (ORCH-027)» добавлен. ✅
|
||
- `.env.example` / `src/config.py` — флаги `ORCH_COVERAGE_*` задокументированы. ✅
|
||
- Маркеры `ORCH-027` проставлены в коде/доках (AC-10). ✅
|
||
|
||
`src/` изменён → документация обновлена в том же PR: **да** (P0-условие выполнено).
|
||
**Обзорные доки (ORCH-079):** PR не закрывает ни один пункт `README.md` «Известные ограничения»
|
||
(coverage-деградация там не значилась) → обновление витрины не требуется, finding отсутствует.
|
||
|
||
## Оси проверки (детально)
|
||
|
||
**1. Соответствие ТЗ (02-trz / 03-acceptance) — PASS.**
|
||
AC-1 измерение инструментально (`measure_coverage` → `pytest --cov=src` → `totals.percent_covered`,
|
||
`pytest-cov==5.0.0` в `requirements.txt`); AC-2 блокировка деградации + откат на `development` с
|
||
release merge-lease (`_handle_coverage_gate`); AC-3 чистая функция `compute_coverage_verdict`
|
||
покрыта по всем режимам/границам/epsilon (TC-01…04); AC-4 ratchet up-only + bootstrap + per-repo
|
||
изоляция + атомарный compare-and-set `UPDATE … WHERE coverage <= ?` (`db.ratchet_coverage_baseline`);
|
||
AC-5 kill-switch/scope + `applies(repo)` ПЕРВЫМ (дорогой прогон только при `applies==True`) —
|
||
регресс зелёный, enduro не затронут; AC-6 fail-open дефолт / fail-closed по флагу; AC-7 never-raise
|
||
+ leaf (не импортирует `stage_engine`) + AST-проверка отсутствия деплой/force-push токенов; AC-8
|
||
контракты `STAGE_TRANSITIONS`/`check_*`/вердикт-ключи байт-в-байт, таблица `coverage_baseline`
|
||
аддитивна; AC-9 вердикт только из frontmatter (`parse_coverage_status` через
|
||
`frontmatter.parse_frontmatter`) + `GET /queue` блок `coverage` + Telegram с кликабельным номером.
|
||
|
||
**2. Соответствие ADR (ADR-001 D1…D8 / adr-0029) — PASS** (с P2-оговоркой по тексту D7).
|
||
Порядок под-гейтов `security → merge → coverage → image-freshness` реализован ровно как в D1
|
||
(врезка `_handle_coverage_gate` между merge-handling и ORCH-058 freshness в `advance_stage`);
|
||
coverage ПОСЛЕ merge-gate (догнанный HEAD) и `merge_gate.release_merge_lease` при FAIL —
|
||
соответствует D1/TR-2 (зеркало image-freshness rollback, в отличие от security — тот до захвата
|
||
lease). Ratchet в choke-point `_handle_merge_verify` (ребро `deploy→done`, D5), БД-таблица
|
||
`coverage_baseline` (D4), машинный вердикт/парсинг (D7), override `POST /coverage/baseline` (D8).
|
||
Глобальные ADR (INV-4 merge только через Gitea API; не трогать `main`/прод) не нарушены — leaf
|
||
только мерит/читает/пишет/решает.
|
||
|
||
**3. Качество кода — PASS.**
|
||
Docstrings на всех публичных функциях; never-raise контракт выдержан последовательно (все
|
||
внешние границы обёрнуты, исключение не всплывает в `advance_stage`); единый frontmatter-контракт
|
||
переиспользован (нет дублирования парс-логики); тесты содержательные (режимы/границы/epsilon,
|
||
ratchet up-only + bootstrap + per-repo изоляция, fail-open/closed, never-raise, write/read-back
|
||
отчёта, self-hosting AST-инвариант, интеграция в `advance_stage` с откатом+release lease).
|
||
Фикс `sys.executable` вместо bare `python` (коммит `8cd7c20`) корректен — pytest-cov живёт в
|
||
интерпретаторе орка. Нет утечек/security-дыр; измерение offline. Замечание (не finding):
|
||
синхронный `pytest --cov` в hot-path `advance_stage` (тайм-аут `coverage_run_timeout_s=900`)
|
||
наследует established-паттерн merge-gate re-test/security-gate — нового класса риска не вводит.
|
||
|
||
**4. Документация — см. раздел «Документация» выше (P0-условие выполнено; обзорные доки N/A).**
|
||
|
||
**Трассировка маркеров (TRACEABILITY).** Правки рядом с маркерами `ORCH-022`/`ORCH-043`/`ORCH-058`
|
||
в `advance_stage` — аддитивная врезка между merge-gate и image-freshness; инварианты соседних
|
||
под-гейтов не сломаны (release-lease зеркалит image-freshness rollback, merge через Gitea API
|
||
не тронут). Врезка в `_handle_merge_verify` (ORCH-071/073) — never-raise best-effort ratchet,
|
||
SHA-in-main choke-point не изменён. Чужие артефакты не повреждены (восстановлена запись ORCH-095).
|