work_item: ORCH-076 title: "ORCH-52c — handoff-протокол + frontmatter writer/валидатор/единый контракт вердиктов" framework: pytest scope: > Покрывается: writer/валидатор/единое чтение frontmatter (src/frontmatter.py); чтение пяти гейтов-вердиктов через единый API при семантике 1:1; обратная совместимость старых доков без новой схемы; never-raise; kill-switch строгой валидации. Вне покрытия: правка промптов агентов (ORCH-52d), ретро-фит старых документов, изменение STAGE_TRANSITIONS/состава QG_CHECKS. notes: > Полный регресс tests/ должен оставаться зелёным (анти-регресс гейтов, AC-4/AC-6). Регресс = любой существующий тест гейтов (review/tester/deploy/staging/security), ставший красным, или изменение вердикта при том же входном значении. Тесты не должны требовать сети (frontmatter — файловый/in-memory контракт). tests: # --- frontmatter.py: writer / валидатор / reader (AC-1, AC-5) --- - id: TC-01 type: unit description: "Writer сериализует mapping в каноничный ведущий YAML-frontmatter (--- ... ---), читаемый существующими парсерами" module: tests/test_frontmatter.py expected: PASS - id: TC-02 type: unit description: "Round-trip: writer записал frontmatter -> reader read_frontmatter_value возвращает те же значения по ключам" module: tests/test_frontmatter.py expected: PASS - id: TC-03 type: unit description: "Валидатор: полная схема (work_item/stage/author_agent/status/created_at/model_used) -> valid=True, нет отсутствующих полей" module: tests/test_frontmatter.py expected: PASS - id: TC-04 type: unit description: "Валидатор: отсутствие части обязательных полей -> valid=False со списком отсутствующих, но БЕЗ исключения (warning-only по умолчанию)" module: tests/test_frontmatter.py expected: PASS - id: TC-05 type: unit description: "never-raise: writer и валидатор на битом вводе (None/не-mapping/нечитаемый путь/битый YAML) не выбрасывают исключение, возвращают безопасное значение + лог" module: tests/test_frontmatter.py expected: PASS - id: TC-06 type: unit description: "reader read_frontmatter_value сохраняет прежний контракт (single-key, None на ошибку/отсутствие, strip, регистр сохранён)" module: tests/test_frontmatter.py expected: PASS - id: TC-07 type: unit description: "kill-switch frontmatter_validation_strict: False -> отсутствие полей не блокирует; True -> строгий режим сигнализирует невалидность" module: tests/test_frontmatter.py expected: PASS # --- единый контракт вердиктов: чтение через общий API, семантика 1:1 (AC-3, AC-6) --- - id: TC-08 type: unit description: "check_reviewer_verdict через единый API: verdict: APPROVED -> (True); REQUEST_CHANGES -> (False); отсутствие -> (False) — как до задачи" module: tests/test_qg_verdicts.py expected: PASS - id: TC-09 type: unit description: "_parse_tests_verdict через единый API: ORCH-047 три равноранговых поля (result/verdict/status), приоритет негативного токена (BLOCKED/FAILED) сохранён" module: tests/test_qg_verdicts.py expected: PASS - id: TC-10 type: unit description: "_parse_deploy_status через единый API: deploy_status SUCCESS -> (True); FAILED -> (False); missing/bad YAML -> (False) — семантика БАГ-8 неизменна" module: tests/test_qg_verdicts.py expected: PASS - id: TC-11 type: unit description: "_parse_staging_status через единый API: SUCCESS/FAILED семантика и условность ORCH-35 (non-self -> N/A pass) сохранены" module: tests/test_qg_verdicts.py expected: PASS - id: TC-12 type: unit description: "parse_security_status через единый API: security_status PASS -> (True); FAIL -> (False) — семантика неизменна" module: tests/test_security_gate.py expected: PASS # --- обратная совместимость / анти-регресс (AC-4) --- - id: TC-13 type: unit description: "Старый док-вердикт БЕЗ новой схемы (только verdict/result/deploy_status/staging_status/security_status) читается каждым из пяти гейтов как до задачи" module: tests/test_qg_verdicts.py expected: PASS - id: TC-14 type: unit description: "Док С новой полной схемой + вердикт-ключом читается гейтом с тем же вердиктом, что и без схемы (схема аддитивна, не влияет на вердикт)" module: tests/test_qg_verdicts.py expected: PASS - id: TC-15 type: integration description: "fallback worktree -> origin/main для check_deploy_status/check_staging_status сохранён при чтении через единый API" module: tests/test_qg_verdicts.py expected: PASS # --- инварианты конвейера (AC-6) --- - id: TC-16 type: unit description: "Состав QG_CHECKS и STAGE_TRANSITIONS не изменён (тот же набор ключей/стадий, что эталон)" module: tests/test_stages_invariants.py expected: PASS # --- полный регресс --- - id: TC-17 type: integration description: "Полный прогон tests/ зелёный (нет регресса существующих тестов гейтов и конвейера)" module: tests/ expected: PASS