92 lines
4.8 KiB
YAML
92 lines
4.8 KiB
YAML
work_item: ORCH-098
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
title: "Журнал уроков: таблица, автозапись отклонений, выборка, ручная запись, never-raise"
|
||
framework: pytest
|
||
scope: >
|
||
Покрывается: создание аддитивной таблицы lessons (идемпотентность, поля атрибуции),
|
||
helper записи record(), автозапись из choke-point (gate-fail/HOLD/transient), read-only
|
||
выборка get_lessons + snapshot, ручная запись/обновление, kill-switch, never-raise.
|
||
Вне покрытия: ретроспективщик (E2), приоритизатор (E3), автоклассификация атрибуции,
|
||
слой-3 детекция здоровья продукта.
|
||
notes: >
|
||
Тесты используют изолированную временную SQLite-БД (фикстура init_db во временном файле).
|
||
Полный регресс tests/ должен оставаться зелёным. Self-hosting: журнал never-raise — ни один
|
||
тест не должен показать, что сбой записи урока роняет конвейер.
|
||
|
||
tests:
|
||
- id: TC-01
|
||
type: unit
|
||
description: "init_db() создаёт таблицу lessons идемпотентно (двойной вызов не падает, нет дублей); присутствуют все поля BR-1."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-02
|
||
type: unit
|
||
description: "Схема lessons несёт нуллабельные колонки атрибуции attribution/target_repo/target_domain; запись без них проходит (NULL/unknown), update проставляет их позже."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-03
|
||
type: unit
|
||
description: "lessons.record() вставляет строку с переданными полями (source=auto/manual), возвращает id; created_at заполняется."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-04
|
||
type: unit
|
||
description: "never-raise: при замоканной падающей БД record/get/update/snapshot возвращают None/[]/{} и не бросают исключение (logger.warning)."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-05
|
||
type: unit
|
||
description: "kill-switch: при lessons_enabled=False record/get/update/snapshot инертны (no-op, без обращения к БД)."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-06
|
||
type: unit
|
||
description: "get_lessons фильтрует по type/status/repo/work_item и соблюдает limit; порядок ORDER BY id DESC."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-07
|
||
type: unit
|
||
description: "update_lesson меняет status/attribution/target_*/related_task и стампит updated_at; несуществующий id безопасен."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-08
|
||
type: integration
|
||
description: "Автозапись gate-fail: смоделированный откат на development в _handle_qg_failure_rollbacks создаёт строку lessons type=gate_failure с контекстом (stage/agent/work_item/repo)."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-09
|
||
type: integration
|
||
description: "Автозапись transient/HOLD: транзиент-ветка merge_gate (или timeout/requeue launcher) пишет урок type=transient_retry/merge_hold; сбой записи не ломает основной путь (never-raise в горячем пути)."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-10
|
||
type: integration
|
||
description: "GET /lessons возвращает 200 с массивом и фильтрами; GET /queue содержит read-only блок lessons; чтение не мутирует данные."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-11
|
||
type: integration
|
||
description: "POST /lessons создаёт ручной урок (source=manual, с атрибуцией); POST /lessons/{id} обновляет его; при lessons_enabled=False эндпоинты отдают {enabled:false}."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|
||
|
||
- id: TC-12
|
||
type: unit
|
||
description: "Инварианты конвейера не тронуты: STAGE_TRANSITIONS/QG_CHECKS/machine-verdict-ключи неизменны (структурный анти-регресс по составу реестра)."
|
||
module: tests/test_lessons.py
|
||
expected: PASS
|