MeDiVa
DocsRecipes

Enforce Architecture Decision Records

Require every ADR to carry a single status, real context, a decision, and consequences.

A decision record with an empty Consequences section is a decision nobody finished thinking about.

Architecture Decision Records are only useful when they're complete and honest: one clear status, the forces that drove the call, the decision itself, and what it costs. A contract beside the template keeps half-written ADRs out of the log.

The contract

docs/adr/template.mdv.md
<!-- mdv: document strict -->

<!-- mdv: choice required oneChecked -->
## Status

- [ ] Proposed
- [ ] Accepted
- [ ] Superseded
<!-- mdv: endchoice -->

<!-- mdv: block required minWords=15 noPlaceholder -->
## Context

What forces a decision, and what constraints bound it.
<!-- mdv: endblock -->

<!-- mdv: block required minWords=10 noPlaceholder -->
## Decision

What we are doing.
<!-- mdv: endblock -->

<!-- mdv: block required minWords=10 noPlaceholder -->
## Consequences

What becomes easier or harder as a result.
<!-- mdv: endblock -->

document strict locks the section set and their order — exactly Status, Context, Decision, Consequences, nothing else. The choice oneChecked makes Status a single-select: precisely one of Proposed / Accepted / Superseded. Each prose section needs real substance (minWords) and no leftover template text (noPlaceholder).

What it catches

An ADR that's half-filled and out of shape:

## Status

- [ ] Proposed
- [ ] Accepted
- [ ] Superseded

## Context

We need to pick a logging approach soon.

## Decision

We will adopt structured JSON logging.

## Consequences

Dashboards get simpler over time.

## Notes

random
adr-0007.md:19  error  [unexpected-section] The "Notes" section is not one the schema declares here.
adr-0007.md:3   error  [need-exactly-one] The "Status" section needs exactly one box checked (found 0).
adr-0007.md:11  error  [too-few-words] The "Context" section is too short (8 words).
adr-0007.md:17  error  [too-few-words] The "Decision" section is too short (6 words).
adr-0007.md:23  error  [too-few-words] The "Consequences" section is too short (5 words).

No status chosen, three thin sections, and a stray Notes heading — five errors, exit 1. Fill it in honestly and it passes.

Run it in CI

Keep the contract as docs/adr/template.mdv.md and validate new records explicitly, or let the zero-config scan pair each NNNN-title.md with a sibling contract:

npx mediva check docs/adr/0007-structured-logging.md --schema docs/adr/template.mdv.md

Variations

  • If your team writes ADRs in a fixed order but sometimes adds an optional ## Alternatives Considered, swap document strict for document noExtraSections (no order constraint) and declare the optional section with block optional.
  • Add a front block for machine-readable metadata — front date date=iso and front id pattern=/^ADR-\d{4}$/ — when an index generator reads the records. See Frontmatter.
  • To require the decision to cite a driving issue, add issueKeyword=Refs to the Decision block — it checks the prose carries a Refs #NN reference and needs no --context. Add issueState=open (and pass --context) only if you also want CI to verify the issue is actually open.

On this page