64 lines
5.6 KiB
Markdown
64 lines
5.6 KiB
Markdown
# adr-0020: Единый frontmatter-контракт + спека handoff (reader/writer/валидатор)
|
||
|
||
Статус: **Accepted** · Дата: 2026-06-09 · Источник: **ORCH-076** (ORCH-52c)
|
||
Детально: [`docs/work-items/ORCH-076/06-adr/ADR-001-frontmatter-contract.md`](../../work-items/ORCH-076/06-adr/ADR-001-frontmatter-contract.md)
|
||
|
||
## Контекст
|
||
|
||
Слой 1 эпика ORCH-52 (ORCH-075/52b) дал **описательный** стандарт документов
|
||
(`docs/_standards/PIPELINE_DOCS.md`), явно отложив машинную проверку на ORCH-52c. В коде:
|
||
`src/frontmatter.py` — только single-key reader (never-raise), а ~10-строчный блок парсинга
|
||
YAML-frontmatter **продублирован** в 5 вердикт-парсерах (`check_reviewer_verdict`,
|
||
`_parse_tests_verdict`, `_parse_deploy_status`, `_parse_staging_status`, `parse_security_status`)
|
||
+ в `_strip_frontmatter`/`extract_security_findings`. Единого контракта чтения, writer'а, схемы
|
||
и формальной спеки handoff — нет. Эти парсеры читают вердикты **на гейтах self-hosting**
|
||
инструмента, обслуживающего прод других проектов из общего инстанса → любой регресс = стоп
|
||
конвейера всех проектов.
|
||
|
||
## Решение
|
||
|
||
1. **`src/frontmatter.py` → полный frontmatter-контракт** (функции в существующем leaf-модуле,
|
||
контракт **never-raise**): сохранённый `read_frontmatter_value` (без изменений) + единый
|
||
парс-примитив `parse_frontmatter(content) -> FrontmatterParse` (единственная точка
|
||
YAML-логики, структура различает no-block / malformed / yaml-error / data) + `render_/
|
||
write_frontmatter` (writer) + `validate_schema` (обязательная схема
|
||
`work_item, stage, author_agent, status, created_at, model_used`) + `strip_frontmatter`.
|
||
2. **Унифицируется механизм парсинга, НЕ семантика.** Все 5 вердикт-парсеров читают YAML через
|
||
`parse_frontmatter`; token-наборы, upper-casing, приоритет негативного токена, 3-полевой
|
||
контракт tester'а (ORCH-047), fallback `worktree→origin/main` — **1:1**. Сигнатуры и
|
||
`tuple[bool, str]` — неизменны. Reason-строки переносятся дословно.
|
||
3. **Валидатор не hard-fail по умолчанию.** Флаг `frontmatter_validation_strict` (env
|
||
`ORCH_FRONTMATTER_VALIDATION_STRICT`, дефолт `False`): default — warning/лог, **вне
|
||
вердикт-пути гейтов** (нулевая регрессия); hard-fail — зарезервированный strict-режим
|
||
(включение — с ORCH-52d). Иначе ORCH-52c заблокировала бы собственный деплой.
|
||
4. **Формальная спека handoff** `docs/_standards/HANDOFF_PROTOCOL.md` — «стадия → обязательный
|
||
выход» (документы + frontmatter-ключи), согласована 1:1 с `PIPELINE_DOCS.md` §2–§3; источник
|
||
истины — код. `PIPELINE_DOCS.md` обновляется ссылкой + отметкой о реализации машинного слоя.
|
||
5. **Без изменений** `STAGE_TRANSITIONS`, состава `QG_CHECKS`, API, схемы БД.
|
||
|
||
## Альтернативы
|
||
|
||
- Общий «умный» verdict-резолвер (поле+токены для всех гейтов) — отклонён: различия token-логики
|
||
→ риск тонкого регресса на гейте при self-hosting. Унифицируем только парс YAML.
|
||
- Класс/новый пакет — отклонён: состояния нет, лишний blast radius.
|
||
- Hard-fail валидатор по умолчанию — отклонён (NFR-3: self-block собственного деплоя).
|
||
- Сторонняя `python-frontmatter` — отклонена: лишняя зависимость ради ~30 строк.
|
||
|
||
## Последствия
|
||
|
||
- **+** Конец дублирования/рассинхрона парсинга; writer+валидатор+схема готовы к ORCH-52d;
|
||
спека handoff закрывает пробел контракта стадий.
|
||
- **+** Нулевая регрессия по построению: семантика и reason-строки 1:1, валидатор инертен при
|
||
дефолте, never-raise сохранён, enduro 1:1.
|
||
- **−** Унификация частичная (парс, не семантика); strict-режим «спящий» до ORCH-52d.
|
||
- **Обратимость:** `frontmatter_validation_strict=False` ⇒ прежнее поведение; перевод гейтов
|
||
поведенчески инвариантен.
|
||
- **Риск:** первый боевой `autoDeploy` орка (ORCH-089) — наблюдение за стадией `deploy`
|
||
(`docs/work-items/ORCH-076/10-tech-risks.md`).
|
||
|
||
## Связи
|
||
|
||
- Опирается: adr-0019 (pipeline-docs-standard, ORCH-075), ORCH-016 (reader), ORCH-047
|
||
(3-полевой tester), adr-0012 (security-гейт), adr-0018 (auto-label/`autoDeploy`).
|
||
- Готовит: ORCH-52d (эмиссия полной схемы агентами; возможное включение strict).
|