Strictness
Strictness is two independent axes — presence and closure. Start lax, dial up with a single closure rule.
Hammond: "We spared no expense." Muldoon: ...the fences are only as strict as you set them.
Jurassic Park had two separate questions about every paddock: is the right animal in it? and can anything get out that shouldn't? mediva keeps strictness exactly that simple — two independent axes you compose, not a ladder of modes.
Presence
Whether a declared item must exist: required / optional / recommended. This is the base level — lax (optional) up to strict (required). Is the paddock occupied at all?
recommended sits between the two: a missing section is a warning, not an error, so the run still passes (exit 0) while nudging the author.
<!-- mdv: section recommended minWords=3 -->
## Rollback Plan
<!-- mdv: endsection -->Omit that section and you get missing-recommended-section at warning severity — the footer reads ✖ 1 problem (0 errors, 1 warning) and the run still exits 0, so CI stays green. (Once the section is present, its other rules like minWords apply normally.)
Closure
Whether undeclared items are allowed. This is the perimeter fence — add one granular rule to seal the set:
| element | closure rule |
|---|---|
| checklist | exactLabels |
| table | noExtraCols |
| sections | noExtraSections |
| frontmatter | noExtraKeys |
Fences off, required only checks that the checklist exists and has at least one checkbox — it does not pin which items. The labels you write are just a starter template: someone can rename them, drop one, or let a clever raptor slip an extra item in, and it all still passes.
<!-- mdv: section required -->
## Checklist
<!-- mdv: taskList required -->
- [ ] Tests added or updated
- [ ] Docs updated
<!-- mdv: endtaskList -->
<!-- mdv: endsection -->Fences on with exactLabels — exactly these two items, nothing smuggled in or left out:
<!-- mdv: section required -->
## Checklist
<!-- mdv: taskList required exactLabels -->
- [ ] Tests added or updated
- [ ] Docs updated
<!-- mdv: endtaskList -->
<!-- mdv: endsection -->Section structure
The closure rules above gate items inside one element. To gate the sections themselves — which headings exist, and in what order — reach for the scope-level structure atoms on a document or section: noExtraSections (no undeclared sections), ordered (declared order), and strict (both at once), with freeText to opt a scope back out.
<!-- mdv: document strict -->
<!-- mdv: section required minWords=5 -->
## Summary
<!-- mdv: endsection -->
<!-- mdv: section required minWords=5 -->
## Changes
<!-- mdv: endsection -->strict here means exactly Summary then Changes, nothing else. Slip in a ## Notes and you get [unexpected-section]; swap their order and you get [out-of-order] — the bridge won't accept a mission log with the decks rearranged. See the structure atoms reference for the full set, including occurs= for repeating sections and requiredWhen for conditional ones.
Conditional sections
Some sections should only be mandatory when a switch is thrown. requiredWhen makes a section required only when a condition elsewhere in the document is met — a checkbox is ticked, or a frontmatter key matches a value. The rest of the time the section can be omitted entirely.
<!-- mdv: section required -->
## Type of Change
<!-- mdv: choice required oneChecked -->
- [ ] Bug fix
- [ ] Breaking change
<!-- mdv: endchoice -->
<!-- mdv: endsection -->
<!-- mdv: section requiredWhen.checked="Breaking change" minWords=5 noPlaceholder -->
## Migration Notes
Dropping the `v1` payload shape; callers must send `schemaVersion: 2` and the renamed `ownerId` field.
<!-- mdv: endsection -->Tick Bug fix and a PR with no Migration Notes passes. Tick Breaking change and the same omission fails with [missing-section] — "required when 'Breaking change' is checked." The frontmatter form is requiredWhen.<key>=<value>, e.g. requiredWhen.type=incident to demand a Postmortem section only on incident reports. This is the escape hatch from a blunt required: the slot appears on the form only when the mission actually calls for it.
How to adopt
Start lax — required only — so a team can integrate without a fight (nobody likes a perimeter fence on day one). Add the closure rule per element once the shape settles, and use Severity overrides (warn=, error=, off=) as the per-diagnostic complement. You rarely need a single global "strict" switch; reach for the one fence that matters. Clever girl.
Do not turn every fence on by default: avoid exactLabels while a checklist template is still changing, avoid noExtraSections on human-authored docs, and add closure only where extra content is actually harmful. A release checklist may need a locked paddock; a design note probably needs room to breathe.