generated from coulomb/repo-seed
Contract framework with markdown-native contracts utilizing fenced YAML blocks
This commit is contained in:
161
docs/contract-framework.md
Normal file
161
docs/contract-framework.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Document Contract Framework
|
||||
|
||||
Date: 2026-05-03
|
||||
|
||||
## Purpose
|
||||
|
||||
The contract framework makes markdown documents practically checkable. It keeps
|
||||
Markdown as the authoring surface and uses fenced YAML as a structured extension
|
||||
for rules that need machine interpretation.
|
||||
|
||||
The first implementation is deterministic. It checks document type, fields,
|
||||
sections, ordering, metric bands, and text assertions. Forms, context, and LLM
|
||||
rubrics are represented in the contract vocabulary as extension points before
|
||||
runtime adapters are added.
|
||||
|
||||
## Contract File Shape
|
||||
|
||||
A contract is a Markdown document with optional frontmatter and one fenced YAML
|
||||
block marked as `yaml contract`.
|
||||
|
||||
````markdown
|
||||
---
|
||||
title: ADR Contract
|
||||
version: "1.0"
|
||||
---
|
||||
|
||||
# ADR Contract
|
||||
|
||||
```yaml contract
|
||||
id: adr-contract-v1
|
||||
document:
|
||||
type: adr
|
||||
title: Architecture Decision Record
|
||||
fields:
|
||||
status:
|
||||
type: string
|
||||
required: true
|
||||
sections:
|
||||
- id: context
|
||||
title: Context
|
||||
presence: required
|
||||
level: 2
|
||||
metrics:
|
||||
document:
|
||||
words:
|
||||
min: 100
|
||||
max: 1200
|
||||
severity: warning
|
||||
```
|
||||
````
|
||||
|
||||
Markdown carries the explanation. YAML carries the contract.
|
||||
|
||||
## Core Terms
|
||||
|
||||
| Term | Meaning |
|
||||
| --- | --- |
|
||||
| Document contract | The machine-readable agreement for one typed Markdown artifact. |
|
||||
| Document type | A named kind such as `adr`, `prd`, `workplan`, or `business-letter`. |
|
||||
| Section spec | A semantic section role with matching headings, presence, level, order, metrics, and assertions. |
|
||||
| Field spec | A typed value expected in frontmatter or later external context. |
|
||||
| Metric band | A soft or hard size/complexity target. |
|
||||
| Assertion | A deterministic content expectation over document or section text. |
|
||||
| Diagnostic | A structured finding with severity, code, source, contract location, rule id, and guidance. |
|
||||
|
||||
## Section Presence
|
||||
|
||||
Section specs support these presence values:
|
||||
|
||||
- `required`: missing section is an error.
|
||||
- `recommended`: missing section is a warning.
|
||||
- `optional`: section is allowed but not required.
|
||||
- `discouraged`: present section is a warning.
|
||||
- `forbidden`: present section is an error.
|
||||
|
||||
Headings are matched case-insensitively against `title`, `id`, `headings`, or
|
||||
`aliases`.
|
||||
|
||||
## Metric Bands
|
||||
|
||||
Supported metrics are:
|
||||
|
||||
- `characters`
|
||||
- `words`
|
||||
- `sentences`
|
||||
- `paragraphs`
|
||||
- `sections`
|
||||
- `headings`
|
||||
- `list_items`
|
||||
- `code_blocks`
|
||||
- `max_heading_depth`
|
||||
- `nesting_depth`
|
||||
|
||||
Document-level bands live under `metrics.document`. Section-level bands live
|
||||
inside a section spec.
|
||||
|
||||
The current metrics layer follows the parser model: every heading-led region is
|
||||
a section, including the document H1 title section.
|
||||
|
||||
## Assertions
|
||||
|
||||
Assertions currently support:
|
||||
|
||||
- `contains`
|
||||
- `contains_any`
|
||||
- `not_contains`
|
||||
- `matches`
|
||||
- `not_matches`
|
||||
|
||||
Assertions are deterministic and produce the same diagnostic model as sections,
|
||||
fields, and metric bands. This is the bridge to later LLM rubrics: semantic
|
||||
checks can become additional assessments without changing how failures are
|
||||
reported.
|
||||
|
||||
## Forms And Context
|
||||
|
||||
Field specs are the first step toward form-backed Markdown generation. Runtime
|
||||
form handling should build on the same field vocabulary:
|
||||
|
||||
- `id`
|
||||
- `type`
|
||||
- `required`
|
||||
- `default`
|
||||
- `source`
|
||||
- `path`
|
||||
- `enum`
|
||||
- `pattern`
|
||||
- `min` / `max`
|
||||
- `min_length` / `max_length`
|
||||
|
||||
Dynamic requiredness, visibility, calculations, and prefill should be declared
|
||||
as context-aware rules in later work. The contract should remain the source of
|
||||
truth, while UI and generation layers act as adapters.
|
||||
|
||||
## LLM Assessment Extension
|
||||
|
||||
LLM-assisted checks should be declared as rubrics, scoped to document or section
|
||||
roles. Core Markitect should not call a provider directly. A future adapter
|
||||
should accept a provider-neutral request:
|
||||
|
||||
- contract id and rule id
|
||||
- document or section text
|
||||
- relevant fields and context
|
||||
- rubric criteria
|
||||
- cache key material
|
||||
|
||||
It should return:
|
||||
|
||||
- pass/fail
|
||||
- score
|
||||
- reason
|
||||
- model/provider metadata
|
||||
- diagnostics using the shared diagnostic model
|
||||
|
||||
## CLI
|
||||
|
||||
```text
|
||||
mkt contract validate <contract.md>
|
||||
mkt contract check <document.md> --contract <contract.md>
|
||||
mkt metrics <document.md>
|
||||
```
|
||||
Reference in New Issue
Block a user