ADR-0002: Type the frontmatter as a MADR superset with an `affects` matcher
| Field | Value |
|---|---|
| Status | accepted |
| Date | 2026-07-18 |
| Schema version | 0.1.0 |
| Reversibility | one-way-door |
| Blast radius | org |
| Scope | org |
| Tags | schema, core, interop |
| Deciders | @mbeacom |
| Authored by | agent-drafted |
| Ratified by | @mbeacom |
| Review tier | arb |
| Review reason | One-way door; every downstream package depends on this shape. |
| Assertions | schema-emit-matches (custom, error) |
| Relates to | 0001, 0004 |
| Affects | path:packages/core/src/schema/**, path:schema/** |
| Source | docs/adr/0002-typed-frontmatter-as-madr-superset.md |
Context
Section titled “Context”The existing ADR ecosystem is a large set of templates and static-site generators with no shared machine-readable contract. Tools interoperate at the level of “it’s markdown,” which is why nothing downstream — CI, IDP catalogs, agents — can act on a decision.
Two forces pull against each other. Adopting an established template (MADR is the de facto standard) buys migrations and credibility. But MADR carries nothing that lets a tool locate what a decision governs, route it for review, or record whether a model wrote it.
The most consequential field is the one that maps a decision to the artifacts it constrains. Without it, an ADR is a document. With it, CI can answer “which accepted decisions govern the code in this PR?” — and deliver the answer as a review comment, at the moment the next decision is being made.
Decision
Section titled “Decision”Define the frontmatter as a strict superset of MADR: every MADR field is
present or mechanically derivable, plus governance metadata (scope,
reversibility, blastRadius), routing state (review), authorship and origin
(provenance), enforcement (affects, assertions), and evaluator output
(evaluation).
provenance covers imported records as well as authored ones. An imported MADR
record is frequently accepted with no named decider, and inferring one from
git blame would attribute the decision to whoever committed the file — often
wrong, always unfalsifiable. So provenance.importedFrom records the source
kind, source reference, and content fingerprint, and its presence exempts the
record from the deciders-required invariant. The decision was made elsewhere;
an empty field is more honest than a fabricated one.
Author the schema once in Zod; emit JSON Schema from it. Version it
independently of the tooling, semver’d, published under a stable $id.
affects is a list of typed matchers — path (glob), entity (Backstage-
compatible catalog ref), package, resource (IaC type), api, data — with
optional repo qualifier and negate.
Options considered
Section titled “Options considered”Option A: Superset of MADR (chosen)
Section titled “Option A: Superset of MADR (chosen)”Migrations from the largest existing corpus are mechanical. Existing MADR tooling continues to render our files. Extension fields degrade gracefully to “unknown frontmatter” in tools that ignore them.
Option B: Clean-sheet schema
Section titled “Option B: Clean-sheet schema”Better internal coherence, no legacy fields. But it makes every existing corpus a manual migration and gives incumbents a reason to dismiss it as not-invented-here. For a project whose value increases with adoption, this is the wrong trade.
Option C: Frontmatter-light, infer from prose
Section titled “Option C: Frontmatter-light, infer from prose”Let a model extract structure from freeform ADRs. Zero authoring burden, but non-deterministic, unauditable, and unusable as a CI gate. Viable as an import path, not as the storage format.
Trade-offs
Section titled “Trade-offs”Carrying MADR’s field names means inheriting some awkward ones. Accepted: the interop is worth more than the elegance.
Authoring burden rises versus plain MADR. Mitigated by making nearly everything
optional with sensible defaults, and by adr new inferring affects from the
changed paths in the current branch.
Consequences
Section titled “Consequences”- Easier: CI enforcement, IDP integration, agent retrieval with structured filters, migration in from MADR, audit evidence mapping.
- Harder: schema evolution — this is a one-way door. Consumers will pin.
- Revisit if: the ecosystem converges on a competing machine-readable ADR standard. Then we adapt to it rather than defend ours.
Action items
Section titled “Action items”- Publish
schema/adr.schema.jsonunder a versioned$id -
adr migrate --from madr - Infer
affectsfrom branch diff inadr new - Contribute the schema back to the
adr.github.iotooling list