Files
orchestrator/docs/architecture/adr/adr-0020-frontmatter-contract.md

5.6 KiB
Raw Blame History

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

Контекст

Слой 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/main1: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).