ADR (Architecture Decision Record) Rules
These rules validate Architecture Decision Records (ADRs) against the Nygard format and MADR 4.0 format, ensuring consistency and completeness in your architectural documentation.
Rules
Structure Rules
| Rule ID | Name | Description |
|---|---|---|
| ADR001 | adr-title-format | Title follows appropriate format for ADR type |
| ADR002 | adr-required-status | Status is defined (section or frontmatter) |
| ADR003 | adr-required-date | Date is defined (line or frontmatter) |
| ADR004 | adr-required-context | Context section is present |
| ADR005 | adr-required-decision | Decision section is present |
| ADR006 | adr-required-consequences | Consequences section is present (Nygard only) |
Validation Rules
| Rule ID | Name | Description |
|---|---|---|
| ADR007 | adr-valid-status | Status value is recognized |
| ADR008 | adr-date-format | Date follows ISO 8601 format |
| ADR009 | adr-filename-matches-number | Filename matches ADR number (Nygard only) |
Collection Rules (Multi-Document)
| Rule ID | Name | Description |
|---|---|---|
| ADR010 | adr-superseded-has-replacement | Superseded ADRs reference replacement |
| ADR011 | adr-sequential-numbering | ADR numbers are sequential with no gaps |
| ADR012 | adr-no-duplicate-numbers | Each ADR number is unique |
| ADR013 | adr-valid-adr-links | Links to other ADRs point to existing files |
Content Quality Rules
| Rule ID | Name | Description |
|---|---|---|
| ADR014 | adr-non-empty-sections | Required sections should have meaningful content |
| ADR015 | adr-decision-drivers-format | Decision Drivers should be a bullet list (MADR) |
| ADR016 | adr-considered-options-format | Considered Options should list at least 2 options |
| ADR017 | adr-consequences-structure | Consequences should distinguish good/bad outcomes (MADR) |
Supported Formats
Nygard Format
The original ADR format proposed by Michael Nygard. Key characteristics:
- Title:
# N. Title(e.g.,# 1. Record architecture decisions) - Date:
Date: YYYY-MM-DDline after the title - Status:
## Statussection with status value - Required sections: Context, Decision, Consequences
# 1. Record architecture decisions
Date: 2024-01-15
## Status
Accepted
## Context
We need to record the architectural decisions made on this project.
## Decision
We will use Architecture Decision Records, as described by Michael Nygard.
## Consequences
See Michael Nygard's article for more details.
MADR 4.0 Format
Markdown Any Decision Records (MADR) version 4.0 uses YAML frontmatter for metadata and a different structure:
- YAML frontmatter with
statusanddatefields - Simple H1 title (no number prefix required)
- Different section names (Context and Problem Statement, Decision Outcome)
---
status: accepted
date: 2024-01-15
decision-makers:
- Alice Smith
consulted:
- Bob Jones
---
# Use PostgreSQL for persistence
## Context and Problem Statement
We need to select a database for our application.
## Decision Drivers
* Need ACID compliance
* Team familiarity with SQL
## Considered Options
* PostgreSQL
* MySQL
* MongoDB
## Decision Outcome
Chosen option: PostgreSQL, because it provides ACID compliance
and the team has extensive SQL experience.
### Consequences
* Good, because mature ecosystem
* Bad, because requires operational overhead
Format Detection
The rules automatically detect the ADR format based on:
- YAML frontmatter present - MADR 4.0 format
- No frontmatter, numbered title - Nygard format
- Path contains
/adr/or/adrs/- Treated as ADR document
Configuration
Configure ADR rules in your .mdbook-lint.toml:
# Enable all ADR rules (they're enabled by default)
[rules]
"ADR*" = true
# Configure valid status values
[ADR007]
valid-statuses = ["proposed", "accepted", "deprecated", "superseded", "rejected"]
# Customize minimum options for Considered Options
[ADR016]
min-options = 2
Why ADR Rules Matter
Architecture Decision Records are critical for:
- Knowledge Transfer: New team members understand past decisions
- Decision Quality: Forces structured thinking about alternatives
- Accountability: Documents who made decisions and why
- Reversibility: Makes it clear when to revisit decisions
- Consistency: Ensures all ADRs follow the same format
Common Issues
Missing Status
Problem: ADR doesn't indicate its current status.
# 1. Use Rust
Date: 2024-01-15
## Context
We need a language.
Solution: Add a Status section.
# 1. Use Rust
Date: 2024-01-15
## Status
Proposed
Placeholder Content
Problem: Sections contain placeholder text instead of real content.
## Context
TODO: Fill in context
Solution: Write meaningful content or mark the ADR as draft.
Superseded Without Reference
Problem: ADR is superseded but doesn't link to the replacement.
## Status
Superseded
Solution: Reference the new ADR.
## Status
Superseded by [ADR-0005](0005-use-kubernetes.md)
Integration with CI/CD
Validate ADRs in your pipeline:
# .github/workflows/adr-check.yml
name: ADR Validation
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install mdbook-lint
run: cargo install mdbook-lint
- name: Validate ADRs
run: mdbook-lint lint docs/adr/*.md --enable "ADR*"
Best Practices
- Number ADRs sequentially: Don't reuse numbers, even for rejected ADRs
- Keep ADRs immutable: Create new ADRs to supersede old ones
- Link related ADRs: Reference related decisions
- Include context: Future readers need to understand the situation
- Document alternatives: Show what was considered and why it was rejected
- Update status promptly: Keep the status current