---
name: writing-adrs
description: >-
  Use when writing, proposing, or accepting Architecture Decision Records (ADRs)
  in this repo. Use when a decision has crystallized from a problem doc and needs
  to be recorded, or when updating living documents after an ADR is accepted.
---

# Writing ADRs

## Overview

An ADR records exactly **one** decision. Problem docs explore; ADRs decide.
`docs/architecture.md` and problem docs are the current state (mutable). ADRs
are point-in-time records that can receive minor annotations but should not be
substantially rewritten.

### ADRs are point-in-time records, not evolving documents

An ADR captures a decision and the context that existed when it was made. It is
not a living design document -- that role belongs to `docs/architecture.md`.

That said, accepted ADRs are **not 100% frozen**. Minor annotations after the
fact are welcome and encouraged:

**Acceptable modifications to an accepted ADR:**

- Changing its `status` (e.g., from Accepted to Deprecated or Superseded)
- Adding cross-reference links to related or superseding ADRs
- Adding short notes that connect the ADR to newer decisions or clarifications
- Fixing typos, broken links, or formatting

These annotations keep ADRs useful as navigational aids rather than dead-end
documents. When a reader lands on an older ADR, links to subsequent decisions
help them find the current state of thinking.

**Not acceptable -- write a new ADR instead:**

- Substantially rewriting Context to reflect updated understanding
- Editing the Decision to match a revised approach
- Modifying Consequences based on what actually happened
- Turning the ADR into a running log of how the decision evolved

If a decision turned out to be wrong, that is what supersession is for. The
original ADR remains as a historical record of what was decided and why. For
ongoing design narrative, use `docs/architecture.md`.

### docs/architecture.md is always current

Unlike ADRs, `docs/architecture.md` is a **living document**. It must always
reflect the current state of architectural decisions. When a new ADR is accepted
(or when an ADR supersedes an older one), `docs/architecture.md` must be updated
to reflect the latest decision. It is the single place a reader can go to
understand what is true *now*, without tracing a chain of ADRs.

## When to Use

- A specific decision has emerged from discussion in a problem doc
- You need to frame an upcoming decision
- An ADR has been accepted and living documents need updating

Do NOT use for open-ended exploration -- that belongs in problem docs.

## The Rules

### One decision per ADR

Each ADR decides a single thing. If you find yourself writing "Additionally, we
decide..." or "We also require...", stop. That is a second ADR.

### Be concise

- **Context:** 1-3 short paragraphs. Link to problem docs for background
  instead of restating them.
- **Decision:** State the decision directly. A few paragraphs at most.
- **Consequences:** 3-5 bullet points. Each one sentence.

| Section | Target | Anti-pattern |
|---------|--------|-------------|
| Context | 1-3 paragraphs | Restating entire problem docs |
| Options (if any) | 1 paragraph each | Multi-page analysis per option |
| Decision | Direct statement + brief rationale | Burying the decision in prose |
| Consequences | 3-5 one-sentence bullets | Essay-length explanations |

### Link, don't repeat

Problem docs exist. Architecture.md exists. Reference them:

```markdown
# Good
The threat model establishes least-privilege as a cross-cutting principle
(see [security-threat-model.md](../problems/security-threat-model.md)).

# Bad
[3 paragraphs restating the threat model's least-privilege section]
```

### Cross-reference other ADRs

If this decision builds on or relates to another ADR, say so in Context.

### Normative specs (`docs/normative/`)

- **Use** when the decision needs **byte-level or field-level** contracts, JSON
  Schema (or equivalent), **canonical YAML** or snapshots, or **compatibility
  / conformance** artifacts aimed at **multiple implementations** or automated
  checks.
- **Do not use** for open-ended trade-off exploration (that stays in **problem
  docs**), for a **single architectural choice** with no large artifact (keep
  that in the **ADR only**), or for duplicating
  [ADR 0003](../../docs/ADRs/0003-org-config-repo-convention.md)-style
  repository convention **without** a versioned contract (do not invent a
  normative subtree for that).
- **Relationship:** the **ADR** states the decision, high-level versioning
  expectations, and **links** to `docs/normative/<topic>/v<major>/...`; the
  normative folder holds the detailed, **versioned** contract (`v1`, `v2`, …).

## Checklist

Follow these steps in order:

1. **Find the next number.** List `docs/ADRs/` on current `main`, then scan
   **open pull requests** for new `docs/ADRs/NNNN-*.md` files so you do not
   collide with in-flight ADRs. Pick the lowest unused four-digit `NNNN`.
2. **Read the template.** Use `docs/ADRs/0000-adr-template.md` exactly.
3. **Fill in frontmatter.** `relates_to` must reference existing filenames
   (without `.md`) from `docs/problems/`. Use `"*"` only for ADRs that truly
   apply to all problem areas. The `status` in frontmatter must match the
   `## Status` heading in the body (the linter enforces this). The number in
   the `title` field and the `# heading` must have **no leading zeros**
   (e.g., `"1. Use ADRs"`, not `"0001. Use ADRs"`). The four-digit
   zero-padded format is only for filenames.
4. **Choose the right status.** Use **Accepted** when the decision is made.
   Use **Deprecated** or **Superseded** when retiring an ADR. Include an
   Options section only when there are genuine alternatives worth documenting;
   if the decision is obvious, just decide it.
5. **Write the ADR.** Follow the conciseness rules above.
6. **Run linters.** Stage your changes, then execute `make lint` and fix any errors before committing.
7. **If status is Accepted, update living documents** (see below).

## Updating Living Documents After Acceptance

When an ADR is accepted, the current-state documents must reflect the decision.

### docs/architecture.md

Add a "Decided:" line or short paragraph under the relevant component. Keep
the existing structure -- do NOT rewrite entire sections. Add a link to the ADR.
Remove or annotate open questions that the ADR resolves. Add new open questions
for consequences that surface new unknowns.

```markdown
## Agent Sandbox

[existing description unchanged]

**Decided:**

- Filesystem access model: ephemeral read-only source mounts with separate
  writable workspace ([ADR 0002](ADRs/0002-ephemeral-sandbox-filesystems.md)).

**Open questions:**

- [remaining unanswered questions]
- [any new questions raised by the ADR's consequences]
```

### Problem docs

If an ADR resolves an open question in a problem doc, annotate that question
with a link to the ADR. Do NOT delete the question -- mark it answered:

```markdown
- ~~How do agents access source code?~~ Decided in
  [ADR 0002](../ADRs/0002-ephemeral-sandbox-filesystems.md).
```

If the ADR partially answers a question, add a parenthetical:

```markdown
- How do we provide agents with resources? (Filesystem access decided in
  [ADR 0002](../ADRs/0002-ephemeral-sandbox-filesystems.md); tool and API
  access remain open.)
```

### What NOT to update

- Do not update documents unrelated to the ADR's `relates_to` problem areas.
- Do not rewrite sections. Make surgical additions.
- Do not change the tone or structure of existing prose.

## Red Flags -- Stop and Reconsider

- Context section restates information from problem docs at length
- You wrote "Additionally, we decide..." -- split into two ADRs
- You're rewriting a section of architecture.md -- make a surgical edit instead
- `relates_to` lists more than 3 problem docs -- the decision may be too broad
- You didn't stage and run `make lint` -- stop and do it
- You're substantially rewriting the Context, Decision, or Consequences of an
  accepted ADR -- write a new superseding ADR instead
- You're turning an old ADR into a running changelog -- use
  `docs/architecture.md` for evolving design narrative

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Bundling multiple decisions | Split into separate ADRs |
| Verbose context | Link to problem docs |
| Forgetting frontmatter `relates_to` | Check template, list problem doc filenames |
| Not updating architecture.md | Follow the update checklist above |
| Rewriting existing doc sections | Make surgical additions only |
| Skipping linters | Stage changes, then run `make lint` before committing |
| Wrong ADR number | Check existing files in `docs/ADRs/` first |
| Substantially rewriting an accepted ADR | Write a new ADR that supersedes it |
| Omitting cross-references to related ADRs | Link older ADRs to newer related decisions |
| Treating old ADRs as evolving design docs | Use `docs/architecture.md` for living narrative |
| Forgetting to update architecture.md | It must always reflect current decisions |
| Leading zeros in title number | Use `"1. Title"` not `"0001. Title"` — zero-padded numbers are only for filenames |
