DocsConcepts

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:

release.mdv.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.
  • document and front are 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 the ordered (or strict) 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:

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.

On this page