adr-writer · git:20260901.c8706d7 · 2026-09-01 · sha256 5da961877276cb85

adr-writer git:20260901.c8706d7A

Immutable. This exact content is served forever at /api/v1/blob/5da961877276cb85.

---
name: adr-writer
description: Author an Architecture Decision Record that captures a non-obvious technical choice — its context, the decision, the consequences, the rejected alternatives, and the reversibility cost. Use whenever a non-trivial dependency is picked, a framework is chosen, a one-way door is opened, two specialists disagree and the orchestrator must pick, or anyone in a future session would ask "why did we do this?" An ADR exists so the answer is on disk, not in someone's head.
id: skill.adr-writer
tier: 2
kind: skill
origin: seed
title: adr-writer — record non-obvious technical choices as short, superseded-never-edited ADRs
owns:
  - adr-writer.method
  - adr-writer.reversibility
  - adr-writer.numbering
requires:
peers:
  - skill.grill-planner
  - agent.architect
load_when:
  - "write an ADR"
  - "record an architecture decision"
  - "why did we choose this dependency or design"
  - "supersede an existing decision record"
  - "opening a one-way door decision"
artifacts:
  - templates/adr.template.md
  - decisions/README.md
est_tokens: 1400
---

# adr-writer

ADRs (Architecture Decision Records) live in `docs/graph/decisions/` and
record every non-obvious technical choice. They are not philosophy
papers and not design docs; they are a recorded answer to "why did
we pick this?"

This skill encodes the discipline of writing them well.

## When to apply this skill

- A new dependency is being committed to (the wiki page handles
  the *what*; the ADR handles the *why*).
- A framework, language, or platform is being chosen.
- A one-way door is being opened (data model, public API contract,
  vendor lock-in).
- A boundary between two services or modules is being drawn.
- Two specialists disagreed and the orchestrator picked an option.
- A bug post-mortem revealed an implicit decision that should have
  been explicit.
- Anyone asks "why did we do it this way?" and the answer isn't in
  an existing ADR.

## ADR numbering

ADRs are numbered monotonically: `adr-NNNN-short-slug.md`. Find the
next free number in `docs/graph/decisions/`. **Never reuse a number.** To
replace a decision, write a new ADR with a new number; mark the old
ADR's status as `superseded by ADR-NNNN`.

The index lives at `docs/graph/decisions/README.md`.

## The template (4 sections that matter most)

Use `docs/graph/templates/adr.template.md`. The four sections that earn their
keep:

### Context

What is the situation that forces a decision? Include the
constraint that makes "do nothing" not viable. Cross-link to
grill.md and the relevant spec.

Bad: "We need a database."

Good: "Spec SPEC-0003 requires submissions to persist across
restarts. Grill.md §4 caps p95 latency at 200ms and cost at
$X/month. The current implementation uses an in-memory map,
which loses state on restart. We need to choose a persistent
store."

### Decision

What we have decided, in **one sentence**. Optionally a short
paragraph naming the central tradeoff.

Bad: "We'll use PostgreSQL."

Good: "We will persist submissions in PostgreSQL 16, using the
managed instance on platform X, accepting an additional ~$45/mo
in exchange for ACID guarantees and ecosystem maturity over the
in-memory alternative."

### Consequences

What changes downstream. Be concrete:
- New constraints (e.g. "migrations now belong in
  `migrations/` and run on deploy").
- Migration or rewrite cost if reversed.
- Effect on the verification plan (new gates, integration tests
  against a test database).
- Effect on the wiki (new library to wikify: the database driver
  and the migration tool).

### Alternatives considered

For each rejected alternative: one paragraph naming the
alternative and the **concrete** reason it lost.

Bad: "SQLite — not as good for our use case."

Good: "SQLite — rejected because grill.md §4 requires concurrent
writes from multiple workers; SQLite serializes them and would
violate the 200ms p95 budget at the projected request rate."

## Reversibility tag

Every ADR tags reversibility as one of:

- **`reversible`** — can be changed in a single session without
  data migration.
- **`expensive`** — can be changed but requires a multi-day
  project.
- **`one-way`** — changing it later requires a rewrite or a
  migration on live data.

`one-way` ADRs get extra scrutiny. They are the ones where the
"alternatives considered" section earns its keep — the next agent
needs to understand why the alternative was rejected, not just
that it was.

## What counts as a decision — don't fabricate one

An ADR records a *choice that was made*, not a fact about how the
system happens to be built. An implementation detail reconstructed
from source is an **observation**, not a decision: record it where
observations live (a node, a runbook) with its rationale marked
"not recorded", and never dress it up as a ratified ADR. If a survey
turns up no genuine decisions, the index stays empty and says so — a
fabricated ADR is worse than a missing one, because the next agent
trusts it.

Two decisions people forget to record because they feel like inaction:

- **"Do nothing now" is a decision.** Ratifying a destination while
  taking no code yet — deferring the first increment behind a named,
  checkable trigger — is an ADR. Separate the *destination* (which
  end-state is correct) from the *timing* (what licenses starting),
  and state what makes waiting safe ("the drift is now tested, not
  invisible").
- **The asymmetric cost of being wrong** is often the whole rationale.
  Record what being wrong costs *in each direction* — "wrong on X
  risks an irreversible incident; wrong on Y costs a bounded,
  recoverable delay" — and let the asymmetry decide, rather than
  arguing which option is abstractly "best".

## Workflow

1. Find the next free number. Read the most recent few ADRs to
   match the project's tone.
2. Copy `docs/graph/templates/adr.template.md` to
   `docs/graph/decisions/adr-NNNN-<slug>.md`.
3. Fill **Context** first. If you can't write the context, you
   don't yet know what decision you're making.
4. Fill **Decision** in one sentence. If you can't, the decision
   isn't yet made; back up to research or brainstorm.
5. Fill **Consequences** — concretely, with file paths and budget
   impacts where applicable.
6. Fill **Alternatives considered** — at least one alternative,
   usually two or three, each with a concrete rejection reason.
7. Fill **Reversibility** and, if `expensive` or `one-way`, name
   the cost in concrete terms.
8. Cross-link: spec, grill.md, wiki pages, external sources.
9. Add a row to `docs/graph/decisions/README.md` (the index).
10. Add a row to grill.md §6 with the ADR's identifier.

## Anti-patterns

- **ADR as design doc.** Design docs are different artifacts; ADRs
  are decision records. Keep ADRs short.
- **Decision sentence that is actually three decisions.** Split
  into three ADRs.
- **Alternatives with vague rejection reasons.** "Not as good"
  doesn't help the next agent. Be concrete.
- **No reversibility tag.** Without it, the next agent doesn't
  know how much weight this decision carries.
- **ADR with no cross-links.** Link to grill.md, the spec, the
  wiki pages — the ADR isn't an island.
- **Rewriting an ADR after the fact.** Supersede; do not edit.
- **An as-built observation dressed as a decision.** Reconstructed
  detail with no recorded rationale is an observation, not an ADR —
  don't mint one to fill an empty index.

## Reference files

- `docs/graph/templates/adr.template.md` — the template.
- `docs/graph/agents/01-architect.md` — the agent that primarily writes
  ADRs.
- `docs/graph/templates/docs/` + `decisions/README.md` — the index template installed at
  `docs/graph/decisions/README.md`.