src/frontmatter.py grows from a single-key reader into the full machine
contract: reader (read_frontmatter_value, unchanged), one parse primitive
(parse_frontmatter), writer (render/write_frontmatter), schema validator
(validate_schema/REQUIRED_FIELDS, warning-only by default) and a shared
strip_frontmatter helper. The five verdict gates (check_reviewer_verdict,
_parse_tests_verdict, _parse_deploy_status, _parse_staging_status,
parse_security_status) now read through the single parse_frontmatter point
instead of duplicated ad-hoc YAML logic; review_parse._strip_frontmatter and
security_gate.extract_security_findings reuse the shared helper.
Strictly backward compatible + never-raise: STAGE_TRANSITIONS, the QG_CHECKS
composition, verdict semantics (incl. ORCH-047 three-field tester + negative
token priority), reason-strings and worktree->origin/main fallback are 1:1.
The schema validator never influences a gate verdict by default; hard-fail is
reserved behind the frontmatter_validation_strict kill-switch (default False).
New formal handoff spec docs/_standards/HANDOFF_PROTOCOL.md ("stage -> required
output" + required frontmatter schema), aligned 1:1 with PIPELINE_DOCS.md.
Tests: test_frontmatter.py (TC-01..07), test_qg_verdicts.py (TC-08..15),
test_security_gate.py (TC-12), test_stages_invariants.py (TC-16). Full
tests/ green (1212).
Refs: ORCH-076
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 KiB
HANDOFF_PROTOCOL — формальный контракт handoff «стадия → обязательный выход»
Назначение. Нормативная спека: что КАЖДАЯ стадия конвейера обязана оставить на выходе — какие документы и какие frontmatter-ключи. Дополняет
PIPELINE_DOCS.md(карта «документ → агент → стадия → гейт → machine-key») «вертикальным» срезом по стадиям и вводит обязательную frontmatter-схему для машинной проверки.Статус истины (важно). Источник истины поведения — код:
src/stages.py(STAGE_TRANSITIONS),src/qg/checks.py(QG_CHECKS/check_*/_parse_*),src/stage_engine.py(врезки под-гейтов). Машинный контракт чтения/записи/валидации frontmatter —src/frontmatter.py. Эта спека документирует; при расхождении первичен код (правило ORCH-075).
Введено задачей ORCH-076 (ORCH-52c — слой 2 эпика ORCH-52: машинный контракт). Слой 1
(ORCH-075/52b) дал описательный стандарт документов; ORCH-52c реализовала единый машинный
frontmatter-контракт (reader + writer + валидатор) и свела чтение пяти вердиктов к одной точке
парсинга. Сквозной ADR: adr-0020-frontmatter-contract.md;
детально — ORCH-076/06-adr/ADR-001-frontmatter-contract.md.
1. Обязательная frontmatter-схема (машинный источник: frontmatter.REQUIRED_FIELDS)
Forward-looking аддитивная схема: набор полей, которые handoff-документ стадии должен нести
в ведущем YAML-frontmatter. Машинный источник истины — кортеж
src/frontmatter.py REQUIRED_FIELDS:
| Поле | Смысл |
|---|---|
work_item |
ID задачи (ORCH-NNN / ET-NNN) — к какой задаче относится выход |
stage |
стадия, на выходе которой написан документ (analysis … deploy) |
author_agent |
роль-автор (analyst / architect / developer / reviewer / tester / deployer) |
status |
человеко/машинно-читаемый статус выхода стадии |
created_at |
дата создания артефакта (YYYY-MM-DD) |
model_used |
модель агента, сгенерировавшего артефакт (claude-…) |
Режим проверки (ORCH-52c, критично для self-hosting). Валидатор схемы
frontmatter.validate_schema / maybe_warn_schema по умолчанию warning-only и никогда не
влияет на boolean-вердикт ни одного гейта: отсутствие полей логируется (logger.warning), но не
роняет конвейер и не заваливает гейт. Жёсткий режим (hard-fail) зарезервирован на будущее
(ORCH-52d) и включается ТОЛЬКО kill-switch'ем frontmatter_validation_strict
(env ORCH_FRONTMATTER_VALIDATION_STRICT, дефолт False). Схема аддитивна: старый
документ-вердикт без этих полей читается гейтом ровно как раньше (см. §3).
2. Контракт handoff по стадиям
Категории документов — как в PIPELINE_DOCS.md §2: required (всегда), when-applicable
(при наличии предмета: инфра / данные / security / post-deploy — отсутствие не нарушение).
«Machine-verdict ключ» — поле, которое exit-гейт/под-гейт ребра читает ТОЛЬКО из frontmatter
(никогда из прозы). Набор документов/ключей/гейтов согласован 1:1 с PIPELINE_DOCS.md §2–§3.
| Стадия (выход) | Агент | Обязательные документы на выходе | Machine-verdict ключ (читает гейт ребра) | Гейт ребра |
|---|---|---|---|---|
created |
система (_create_initial_docs) / заказчик |
00-business-request.md |
— (вход, не гейтится) | — |
analysis |
analyst | 01-brd.md, 02-trz.md, 03-acceptance-criteria.md, 04-test-plan.yaml |
— (гейт проверяет наличие файлов + Approved) | check_analysis_approved |
architecture |
architect | 06-adr/ADR-NNN-<slug>.md (≥1); 07-infra-requirements.md, 08-data-requirements.md, 10-tech-risks.md (when-applicable/required-info) |
— (гейт проверяет наличие 06-adr/ ≥1 ИЛИ 07-…) |
check_architecture_done |
development |
developer | код + тесты в ветке (артефакт-док не пишется; гейт — зелёный CI) | — (гейт читает CI-статус Gitea) | check_ci_green |
review |
reviewer | 12-review.md |
verdict: (APPROVED | REQUEST_CHANGES) |
check_reviewer_verdict |
testing |
tester | 13-test-report.md |
result: / verdict: / status: (PASS | FAIL | BLOCKED; три равноранговых, ORCH-047) |
check_tests_passed |
deploy-staging |
deployer | 15-staging-log.md (required для self-hosting); 17-security-report.md (security-под-гейт, when-applicable) |
staging_status: (SUCCESS | FAILED); security_status: (PASS | FAIL) |
check_staging_status (ребро); под-гейты ребра deploy-staging→deploy: check_security_gate → check_branch_mergeable → check_staging_image_fresh |
deploy |
deployer / deploy-finalizer | 14-deploy-log.md |
deploy_status: (SUCCESS | FAILED) |
check_deploy_status |
done |
— | — (терминал) | — | — |
пост-done наблюдение |
post-deploy-monitor | 16-post-deploy-log.md (when-applicable, ORCH-021) |
post_deploy_status: (HEALTHY | DEGRADED) — информационный, не гейт |
— (телеметрия петли уроков / наблюдаемость) |
Примечания (нормативные)
- Под-гейты ребра
deploy-staging → deploy(check_security_gate→check_branch_mergeable→check_staging_image_fresh) — это врезки вadvance_stage, а НЕ строкиSTAGE_TRANSITIONS. Их порядок и условность раската не меняются этой спекой. 15-staging-log.mdобязателен только для self-hosting репо (orchestrator); для прочих репо staging-гейт — N/A (ORCH-35), документ не требуется.16-post-deploy-log.mdнесётpost_deploy_status:, но это информационный ключ (телеметрия ORCH-8 / наблюдаемость), гейтом он НЕ парсится.09-…/05-…/11-…— зарезервированные/legacy номера; канон reviewer'а —12-review.md.
3. Machine-verdict доки vs информационные (честный механизм проверки)
Полностью согласовано с PIPELINE_DOCS.md §3. Machine-verdict док — гейт читает ТОЛЬКО
YAML-frontmatter (через единый frontmatter.parse_frontmatter), маппит ключ в вердикт; имя ключа
чувствительно к регистру, значение парсер приводит к верхнему регистру.
| Документ | Machine-key | Парсер | Эффект вердикта |
|---|---|---|---|
12-review.md |
verdict: |
check_reviewer_verdict |
APPROVED → дальше; REQUEST_CHANGES → откат на development |
13-test-report.md |
result: / verdict: / status: |
_parse_tests_verdict |
PASS → дальше; FAIL/BLOCKED → откат (негативный токен авторитетен) |
14-deploy-log.md |
deploy_status: |
_parse_deploy_status |
SUCCESS → done; FAILED → откат (БАГ-8) |
15-staging-log.md |
staging_status: |
_parse_staging_status |
SUCCESS → дальше; FAILED → откат (self-hosting; иначе N/A) |
17-security-report.md |
security_status: |
check_security_gate → parse_security_status |
PASS → дальше; FAIL → откат |
Информационные доки (гейтом НЕ парсятся): 00-business-request.md, 08-data-requirements.md,
10-tech-risks.md, 16-post-deploy-log.md.
Аддитивность схемы (§1). Документ-вердикт БЕЗ полей схемы из §1, но с вердикт-ключом, читается
гейтом РОВНО как раньше: схема не участвует в вычислении вердикта при дефолтном
frontmatter_validation_strict=False.
4. Единый машинный контракт — src/frontmatter.py
Все операции с frontmatter сведены в один leaf-модуль (never-raise):
read_frontmatter_value(path, key) -> str | None— single-key reader (контракт неизменен, BC).parse_frontmatter(content) -> FrontmatterParse— единственная точка парсинга YAML-frontmatter (data/has_block/malformed/yaml_error); пять вердикт-парсеров делегируют сюда.parse_frontmatter_dict/read_frontmatter— ярлыки к распарсенному mapping.render_frontmatter/write_frontmatter— writer (формат совместим с существующими парсерами).validate_schema/REQUIRED_FIELDS/maybe_warn_schema— схема §1 (warning-only по умолчанию).strip_frontmatter— общий хелпер тела (заменил дубли).- Kill-switch жёсткой валидации:
config.frontmatter_validation_strict(envORCH_FRONTMATTER_VALIDATION_STRICT, дефолтFalse).
Перед написанием номерного дока бери скелет из
docs/_templates/и не меняй имя machine-key frontmatter (регистр чувствителен — иначе гейт упадёт ложно).