Use when authoring an Architecture Decision Record (ADR) — a short document that captures one significant, hard-to-reverse technical or architectural decision, its context, and its consequences. Triggered by the sdlc ADR pipeline (the knowledge-engineer agent behind /sdlc:docs seed adr and /sdlc:docs distill) when generating an ADR from a story, and by anyone hand-authoring an ADR under docs/adr/ today. Covers why ADRs are kept short and inverted-pyramid, the required sections (Title, Status, Decision, Context, Alternatives Considered, Consequences), the proposed→accepted→superseded (or →rejected) status lifecycle and the never-edit-only-supersede immutability rule, the NNNN-decision-slug.md filename convention, and the ADR frontmatter fields (status, agents, source-stories) the pipeline reads to route a generated ADR into docs/adr/index.md.
Core principle: an ADR records ONE decision — not a design, not a feature, not a whole subsystem. If you find yourself wanting to describe several decisions in one file, that's a signal to split it into several ADRs.
Announce at start: "I'm using the writing-adrs skill to author this ADR."
/sdlc:docs seed adr / /sdlc:docs distill + knowledge-engineer
agent) generates an ADR from a Jira story or a completed piece of work — in a repo where that
pipeline is adopted.Every ADR — hand-authored or pipeline-generated — MUST contain these sections, in this order. One decision per record, not one document per subsystem — a bundled record can't be individually superseded; the moment one part of it changes, a reader can no longer trust any of it.
proposed, accepted, superseded, rejected (see Status Lifecycle
below). If superseded, link to the ADR that replaces it. If superseding another ADR, link back
to the one it replaces.An ADR MAY also carry an optional Confidence note inside Consequences (or its own short subsection) when the decision was made under real uncertainty — say what assumption it hinges on and what evidence would change the answer, since false certainty teaches the wrong lesson. Omit it when confidence was genuinely high; don't manufacture doubt that wasn't there.
proposed → accepted → superseded
proposed → rejectedproposed — under discussion, not yet binding. Safe to edit freely while in this state.accepted — the team has agreed and the decision is active.rejected — the proposal was discussed and declined; terminal, it never later becomes
accepted. If the idea resurfaces, write a fresh ADR at a new number rather than reviving a
rejected one — the number stays retired, same as any other ADR number.superseded — no longer the operative decision, but preserved so the history of what the team
believed (and when it changed its mind) stays intact.Immutability rule (stated once, here — every other mention in this skill is a pointer back to
this paragraph, not a restatement): once an ADR reaches accepted, never edit its substance —
an ADR's value is as a historical log, and an in-place edit destroys that: a reader with a link
to it later has no way to know the ground shifted under them. The only permitted in-place change
is a purely cosmetic fix (typo, broken link) that no reader could interpret as changing the
decision, context, alternatives, or consequences; anything else requires a new superseding ADR
instead.
Supersede flow: when a decision needs to change, write a brand-new ADR at the next sequence
number and let it follow the normal lifecycle like any other — it starts proposed, not
accepted. Only at the moment the new ADR is itself accepted do the two records flip together:
the new one becomes accepted, and the old one becomes superseded — never before, since the old
decision is still the operative one until its replacement is actually accepted, not merely
drafted. Add the cross-links both ways at that same moment (old → "Superseded by ADR-NNNN", new →
"Supersedes ADR-NNNN"). The superseded record stays in the repo permanently — it's a historical
fact, not a mistake to delete.
Kept in the source repo, in plain markdown, monotonically numbered — ADRs travel with the code (checked out, diffed, reviewed the same way), and a directory listing alone shows decision order.
docs/adr/NNNN-decision-slug.md — a four-digit, zero-padded, monotonically increasing number
(never reused, even for a superseded or rejected ADR) followed by a kebab-case slug of the
decision itself (not the problem). Example: 0001-htmx-for-active-web-pages.md.docs/adr/ and take the highest existing number + 1 — don't
guess or leave gaps.This is distinct from this SKILL.md's own frontmatter above — it's the YAML frontmatter that
belongs at the top of every generated ADR file itself, so the sdlc ADR pipeline (the
knowledge-engineer agent behind /sdlc:docs seed adr / /sdlc:docs distill) can route and index
it without re-parsing prose.
Authoring with this frontmatter costs nothing even in a repo that hasn't adopted the pipeline yet,
and needs no retrofitting once it does:
---
status: proposed # proposed | accepted | superseded | rejected
agents: [web-engineer, platform-engineer] # which sdlc agents this decision is routed to
source-stories: [PROJ-142, PROJ-156] # Jira keys that motivated or are evidenced by this decision
---status — mirrors the Status section inside the document body; keep both in sync. This is the
field the pipeline reads to decide whether an ADR is still binding.agents — the sdlc agent name(s) (matching the agent identifiers used elsewhere in this
plugin, e.g. web-engineer, platform-engineer, database-administrator) whose future work
this decision constrains or informs. An ADR can name more than one agent when the decision
spans domains; name every agent it's genuinely relevant to, not just the one that happened to
write it.source-stories — the Jira story key(s) that led to this decision (an evidence trail back to
why it exists), as a list even when there's only one.Where the sdlc ADR pipeline is installed and in use — the knowledge-engineer agent and its
regeneration tooling, shipped with this plugin — a generated docs/adr/index.md is rebuilt
deterministically from this frontmatter across every file in docs/adr/: grouped into a section
per agent named in agents, plus one General (unrouted) section for any ADR whose agents list
is empty or omitted, so no ADR is ever silently dropped from the index just because it wasn't
routed anywhere. Each listing carries the ADR's number, title, and status. Because the index is
fully derived from frontmatter in a repo that has adopted the pipeline, never hand-edit
docs/adr/index.md directly there; fix the frontmatter of the source ADR(s) and regenerate
instead — otherwise the index will just be silently overwritten out of sync on the next
regeneration. In a repo that hasn't adopted the pipeline (or hasn't yet run /sdlc:docs seed adr /
/sdlc:docs distill), a hand-maintained index (or no index at all) is perfectly fine — the
never-hand-edit rule only starts to apply once there's something to regenerate from.
Hand-authored ADRs that aren't part of the pipeline may omit agents/source-stories if there's
no sdlc routing use for them yet, but should still carry status — it costs nothing and keeps
the file consistent with every other record in the directory.
Artifact encoding contract: unpadded tables, no section dropped, one-line N/A, verbatim contracts, rationale as annotation, prose < 10 lines between headings. plugins/sdlc/refs/artifact-encoding.md
---
status: proposed
agents: []
source-stories: []
---
# NNNN. [Decision title — a short noun phrase naming what was decided]
## Status
Proposed
## Decision
[The commitment, in active voice: "We will …". Lead with this — inverted pyramid.]
## Context
[The forces at play: technical, organizational, timeline, cost. Value-neutral — describe the
tension, don't argue for the outcome yet.]
## Alternatives Considered
### [Alternative 1 name]
- Pros: [...]
- Cons: [...]
### [Alternative 2 name]
- Pros: [...]
- Cons: [...]
## Consequences
- [Positive consequence]
- [Negative consequence — never omit these]
- [Neutral consequence, if any]
- Revisit this decision if: [the condition that should trigger re-evaluation]The example below (adr-tools' own ADR set on GitHub, and Harmel-Law's and Rowse/Shepherd's format variants on martinfowler.com, are further worked examples worth reading) shows the required sections filled in at the right level of detail — decision first, honest alternatives, explicit consequences including the negative one:
---
status: accepted
agents: [database-administrator, platform-engineer]
source-stories: [PROJ-89]
---
# 0007. Use PostgreSQL as the primary datastore
## Status
Accepted
## Decision
We will use PostgreSQL as the primary datastore for all new services, replacing the
per-service choice that previously let teams pick their own database.
## Context
Each service currently owns its choice of datastore, chosen independently by whichever team
built it first. This has produced four different databases in production, each requiring its
own backup tooling, monitoring, and on-call expertise. New hires need to learn a different
query language and operational model depending on which service they touch first. At the same
time, two of our services have genuinely relational, multi-table transactional workloads that a
key-value store handles awkwardly, while none of our workloads yet require the horizontal write
throughput that would justify a distributed database's added operational cost.
## Alternatives Considered
### Keep per-service choice (status quo)
- Pros: teams retain full autonomy; no migration cost; no risk to services already stable on
their current datastore.
- Cons: four operational surfaces to maintain indefinitely; onboarding cost compounds with every
new service; no shared tooling for backups, migrations, or observability.
### Standardize on a distributed/NoSQL store
- Pros: horizontal write scaling available if a future workload needs it; some existing services
are already comfortable with a document model.
- Cons: none of our current workloads need that scale, so we'd be paying its operational
complexity cost today for a benefit we don't yet use; relational workloads would need
significant application-level rework to fit a document model.
### Standardize on PostgreSQL
- Pros: handles our existing relational workloads natively; one operational surface (backups,
monitoring, migrations, on-call runbooks); mature tooling and hiring pool; a managed offering
is already in use for one service, so some operational muscle exists.
- Cons: services already comfortable on their current non-relational store face a real migration
cost; PostgreSQL's horizontal write scaling story is weaker than a distributed store's, which
matters if a future workload needs it.
## Consequences
- One database technology to operate, monitor, back up, and hire for — the onboarding and
tooling cost this decision was meant to fix goes away for every service built from here on.
- Existing services on other datastores are not migrated by this decision alone — each needs its
own migration plan and its own ADR when that work is scheduled, since data migration risk is a
separate decision from "which store new services use."
- We are accepting a weaker horizontal write-scaling story than a distributed store would give
us. Confidence here is moderate, not high: none of our current workloads are close to the
point where this would matter, but if a future workload needs sustained high write throughput,
that's the specific trigger to revisit this decision rather than defaulting to PostgreSQL by
habit.NNNN-decision-slug.md in docs/adr/, number is the next unused onestatus matches the Status section in the bodyagents names every sdlc agent this decision is genuinely relevant
to; source-stories lists the motivating Jira key(s)status is set
to supersededaccepted: nothing about the decision, context, alternatives, or
consequences was edited after acceptance — a substantive change went into a new ADR instead| Anti-pattern | Fix |
|---|---|
Editing an accepted ADR's Decision/Context/Consequences in place | Write a new ADR, link both ways, mark the old one superseded |
| Bundling several decisions into one record | Split into separate ADRs, one decision each |
| Alternatives section that only lists the option that "lost," no pros | Give every alternative real pros AND cons — a one-sided list reads as rationalization |
| Consequences section that only states positives | List negative and neutral consequences too — never leave them implied |
| Multi-page document covering a whole subsystem's design | Cut to the single decision; link to supporting material instead of inlining it |
| Writing with false certainty about a decision made under real doubt | State the uncertainty and the revisit trigger honestly |
| Filename without a monotonic number, or reusing a superseded ADR's number | Always take the highest existing number in docs/adr/ + 1 |
Hand-editing a pipeline-generated docs/adr/index.md directly | Fix the source ADR's frontmatter and regenerate instead (fine to hand-maintain the index until the pipeline exists) |
8a737ca
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.