111 lines
6.1 KiB
YAML
111 lines
6.1 KiB
YAML
work_item: ORCH-027
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
title: "Code coverage gate — защита от деградации покрытия тестами"
|
||
framework: pytest
|
||
scope: >
|
||
Покрываются: чистая логика вердикта покрытия (режимы absolute/baseline/both, границы,
|
||
epsilon), ratchet-обновление базовой линии, условность (kill-switch + per-repo область),
|
||
fail-open/fail-closed при ошибке инструмента, never-raise, наблюдаемость (GET /queue,
|
||
Telegram при FAIL), интеграция гейта в advance_stage / точку конвейера. Вне покрытия:
|
||
фактические измерители не-Python стеков (jest/jacoco), мутационное тестирование.
|
||
notes: >
|
||
Тесты не должны исполнять реальный прод-деплой и не трогают prod-контейнер/main.
|
||
Измерение покрытия в тестах мокается/стабится (фиктивная метрика), реальный pytest-прогон
|
||
под coverage проверяется отдельным интеграционным тестом на минимальном фикстур-репо/worktree.
|
||
Полный регресс tests/ должен оставаться зелёным (нулевая регрессия для enduro-trails).
|
||
|
||
tests:
|
||
- id: TC-01
|
||
type: unit
|
||
description: "compute_coverage_verdict, policy=absolute: measured>=floor → PASS; measured<floor-epsilon → FAIL; ровно на пороге → PASS"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-02
|
||
type: unit
|
||
description: "compute_coverage_verdict, policy=baseline: measured>=baseline → PASS; ниже baseline-epsilon → FAIL (no-regression / ratchet)"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-03
|
||
type: unit
|
||
description: "compute_coverage_verdict, policy=both: PASS только при выполнении обоих условий; нарушение любого → FAIL"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-04
|
||
type: unit
|
||
description: "epsilon-допуск: дрожание покрытия в пределах epsilon у границы не заворачивает задачу (анти-флап, NFR-4)"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-05
|
||
type: unit
|
||
description: "Ratchet базовой линии: при слиянии baseline растёт до смёрженного покрытия только если >= текущей; меньшее значение не понижает baseline"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-06
|
||
type: unit
|
||
description: "Bootstrap базовой линии: первичная инициализация фактическим покрытием main при отсутствии сохранённого значения"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-07
|
||
type: unit
|
||
description: "Условность applies(repo): пустой coverage_gate_repos → только self-hosting (is_self_hosting_repo); repo вне области → no-op (True, 'N/A'), дорогой прогон не запускается"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-08
|
||
type: unit
|
||
description: "Kill-switch coverage_gate_enabled=False → гейт инертен, advance_stage ведёт себя 1:1 как до ORCH-027"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-09
|
||
type: unit
|
||
description: "Fail-open по умолчанию: ошибка/недоступность coverage-инструмента и coverage_tool_fail_closed=False → PASS + WARNING-лог; флаг True → FAIL (fail-closed)"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-10
|
||
type: unit
|
||
description: "never-raise: внутреннее исключение (битый вывод coverage, отсутствие worktree) перехватывается, не всплывает в advance_stage"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-11
|
||
type: unit
|
||
description: "Запись/чтение отчёта: write_coverage_report пишет coverage_status: PASS|FAIL во frontmatter; parse читает обратно из того же файла через src/frontmatter.py (single source of truth)"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-12
|
||
type: unit
|
||
description: "Self-hosting безопасность: гейт не вызывает деплой-хук, не перезапускает прод-контейнер, не пушит/форс-пушит в main/master"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-13
|
||
type: integration
|
||
description: "Гейт в конвейере: при measured ниже политики advance_stage не продвигает к деплою и инициирует откат на development (инкремент developer-retry); при PASS — продвигает штатно"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-14
|
||
type: integration
|
||
description: "Реальное измерение: pytest под coverage в ensure_worktree на минимальном фикстур-репо возвращает корректную метрику line coverage и тайм-аутится по coverage_run_timeout_s"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|
||
|
||
- id: TC-15
|
||
type: integration
|
||
description: "Наблюдаемость: FAIL даёт Telegram-алерт с кликабельным номером (измеренное/порог/дельта); GET /queue несёт read-only блок coverage; совместимость — STAGE_TRANSITIONS/QG_CHECKS/существующие вердикт-ключи не изменены"
|
||
module: tests/test_coverage_gate.py
|
||
expected: PASS
|