Contracts
A contract is plain Markdown with mdv rules — kept beside the document, template, or workflow it checks.
A contract is your existing Markdown template plus hidden <!-- mdv: --> rules — a PR template that can fail CI.
Captain's Log, Stardate 47988. Every away mission ends with a report filed to Starfleet. The format never changes: who went, what happened, what they brought back. The form is the contract; the mission is the document.
A contract is a .mdv.md file: ordinary Markdown annotated with <!-- mdv: … --> directives. It describes the Markdown you expect; mediva checks a real document against it. Think of it as the standing orders — written once, applied to every mission report that comes in.
Anatomy
Here's the away-team report contract every starship uses before transmitting a release.md:
<!-- mdv: document -->
<!-- mdv: section required minWords=20 -->
## Summary
<!-- mdv: endsection -->
<!-- mdv: section required -->
## Changes
<!-- mdv: list required minItems=1 -->
- Added the retro-thruster diagnostic to the away-team kit.
<!-- mdv: endlist -->
<!-- mdv: endsection -->- A section owns a heading:
<!-- mdv: section <rules> -->opens immediately before the ATX heading,<!-- mdv: endsection -->closes after its whole body. Sections are the only tag that carries a heading, and the only one that nests — a section's body can hold child sections and leaves. - A leaf governs one construct inside a section and never carries a heading of its own:
list/endlist,evidenceList/endevidenceList,taskList/endtaskList,choice/endchoice,table/endtable,line/endline,code/endcode,media/endmedia. documentandfrontare markers — they take no end tag.- Plain Markdown between directives is the contract's own structure (the headings the document must match —
## Summary,## Changes). By default their order isn't enforced; add theordered(orstrict) structure atom when sequence matters — see Strictness.
A contract reads like the LCARS template on the bridge: the slots are fixed, the crew fills them in, and nothing transmits until every slot is real. Hand it a document with a thin Summary and an empty Changes list and it says exactly what's wrong and where:
Form — edit the document
log.md
5 error Empty section empty-section
The "Changes" section needs a list with at least one item.
fix: This heading promises content to the reader. Write the actual details for this section. If no information genuinely exists yet, write `Not specified.` — do not invent content to fill the gap.
State — do the work, then record it
log.md
3 warning Too short too-few-words
The "Summary" section is too short (3 words).
fix: Add more detail - aim for at least 20 words.
contract: release.mdv.md
Restructuring on purpose? Update the contract in the same change so document and contract move together. One-off exception: <!-- mdv: disable-next-line <rule> -- reason -->
✖ 2 problems (1 error, 1 warning)Drop the ## Summary heading entirely and you get [missing-section] instead — the contract notices what isn't there, not just what's malformed.
That can be as small as turning a normal PR template heading into an enforceable slot:
<!-- mdv: section required minWords=20 noPlaceholder -->
## Summary
<!-- mdv: endsection -->Where contracts live
Keep a contract beside what it checks — same shelf, same shuttle bay:
README.mdv.mdnext toREADME.md.github/pull_request_template.md(mediva can validate PR bodies against it)docs/changelog.mdv.mdfor yourCHANGELOG.md
One contract validates many documents — write the shape once, check every output. The Enterprise doesn't redesign the report form for every planet; it reuses one and lets the contents vary.
Validated against the generated document
mediva checks the rendered Markdown, not the contract. The contract's example rows and prose are the spec; the document under test is what must conform. That's the point: catch drift in generated or hand-edited Markdown before it ships — before the report reaches Starfleet Command and someone notices the Summary is blank.
Next: Tags & rules.