---
name: fp-write-adr
description: Write a formal Architectural Decision Record (ADR) in Michael Nygard format to fastpace/docs/adr/. Auto-numbers the next ADR, interviews the user for the 4 parts (context, decision, alternatives, consequences), appends a one-line pointer to decisions.md. Use for substantive decisions; for one-liners use /fp-remember instead. Triggers on /fp-write-adr <slug-or-topic>.
---

# fp-write-adr

Produce a durable ADR that future reviewers will cite. ADRs answer "why" in full, with alternatives and consequences — they're what you read a year later when someone asks "should we change X?"

## When this vs. /fp-remember

Use `/fp-write-adr` if **any** of the following is true:

- The decision affects a module boundary or the data model.
- You're choosing between libraries / frameworks / architectural styles with real tradeoffs.
- Someone will later ask "why did we do this?" — and the answer can't fit in one sentence.
- The decision is hard or expensive to reverse.
- You want future PR reviewers to cite it explicitly.

Otherwise, `/fp-remember` is the right tool — it appends a short entry to `decisions.md` without ADR ceremony.

## Preflight

1. Confirm `fastpace/docs/adr/` exists (installer creates it). If not, create it.
2. Resolve the slug from the invocation: `/fp-write-adr use-postgres-over-dynamo` → `use-postgres-over-dynamo`. Slug is lower-kebab.
3. **Check for supersession candidates.** Grep `fastpace/docs/adr/*.md` and `fastpace/context/decisions.md` for terms related to the topic. If a prior decision covers this area, surface it: "Found `ADR 0004 — Use DynamoDB`. Is this ADR superseding it, updating it, or a separate concern?" Handle per the user's answer:
   - Superseding: this ADR's Status becomes `accepted`; the old ADR's Status becomes `superseded by NNNN`. Both reference each other.
   - Updating an existing decision without reversal: redirect to `/fp-remember` (new entry on `decisions.md`).
   - Separate concern: proceed.

## Discover the next ADR number

1. Read `fastpace/docs/adr/`.
2. Count files matching `^\d{4}-` (four-digit prefix).
3. Next number = count + 1, zero-padded to 4 digits (`0001`, `0002`, …, `9999`).
4. Filename: `<NNNN>-<slug>.md`. Never reuse numbers, even for rejected/superseded ADRs.

## Interview

Ask these *one at a time*. Read the repo first — only ask for what you can't find:

1. **Context.** "What forces are at play? Be concrete — name real systems, real pain. What changed recently that made this a decision now?"
2. **Decision.** "In one sentence, what's the choice?"
3. **Alternatives.** "What did you seriously consider? Walk me through two or three." (Never accept "none" without pushing — there's always an alternative, even "do nothing".)
4. **Consequences.** Three buckets: positive, negative, neutral. "What do we gain? What do we pay for? What changes in operations that isn't clearly good or bad?"

Stop when you have enough to write. Don't ask everything for every ADR.

## ADR format (Michael Nygard, exact)

```markdown
---
number: NNNN
title: <short human title>
status: proposed | accepted | deprecated | superseded by NNNN
date: <YYYY-MM-DD>
author: <user>
supersedes: <NNNN>   # optional — only if this ADR replaces another
---

# NNNN. <Title>

## Status

<proposed | accepted | deprecated | superseded by NNNN>

<If superseding, add: "Supersedes [ADR <NNNN>](./<NNNN>-<slug>.md).">

## Context

<What's the issue? What forces are at play? Reference real systems, real pain,
real dates. A reader 18 months from now needs to understand *why this was even
a decision*, not just what was chosen.>

## Decision

<The change we're proposing or doing. Short and precise — the details belong
in Consequences and Context.>

## Alternatives considered

- **<Option A>:** <what it was, and why rejected — specific tradeoff>.
- **<Option B>:** <…>.
- **Do nothing:** <if this was a real option, explain why we didn't>.

## Consequences

### Positive

- <concrete good — what becomes possible / easier>
- <…>

### Negative

- <cost / risk / new thing to maintain>
- <…>

### Neutral

- <things that change but aren't clearly good or bad>
- <…>

## References

- Prior decisions: <fastpace/context/decisions.md § <date> | ADR NNNN>
- Related code: <path — optional>
- External docs: <link — optional>
```

## Supersession rules

If this ADR supersedes a prior one:

1. **New ADR** (this one): Status = `accepted`. Title includes nothing special. Context references the old ADR explicitly ("ADR 0004 chose DynamoDB; this ADR replaces that choice because…"). Add `supersedes: 0004` to frontmatter.
2. **Old ADR**: update its Status to `superseded by NNNN` (and frontmatter too). **Never delete or rewrite the body.** The old rationale stays visible — history matters.
3. **`decisions.md` pointer**: the new pointer says "(ADR NNNN — supersedes ADR 0004)".

## decisions.md pointer (always append)

After writing the ADR, append a one-line entry to `fastpace/context/decisions.md`:

```markdown
## <YYYY-MM-DD> — <short title> (ADR NNNN)

See [ADR <NNNN>](../docs/adr/<NNNN>-<slug>.md).
```

This keeps `decisions.md` useful as an *index* without duplicating the full ADR. Every `fp-ask` / `fp-review-pr` run checks this index first.

## Rules

- **Never renumber.** Once an ADR has number N, it keeps N forever, even if rejected or superseded.
- **Supersession, not deletion.** To undo an ADR, write a new one. Never edit the old one's body.
- **One decision per ADR.** If you find yourself writing two distinct decisions, split into two ADRs.
- **"Alternatives considered: none" is a lie.** Push for at least one real alternative — even "do nothing" is an alternative. If the user insists, document their insistence: "Alternatives considered: none — user judged the space trivial. See Consequences."
- **Dates are absolute ISO.** No "last week".
- **Author is the human, not the model.** Use the repo's configured user name if available.
- **Don't code in an ADR.** Function signatures or short schema snippets are fine; full implementations aren't.
- **Write before you ask too much.** If the user gives you enough in 2 questions, write the draft — they can edit. Interrogation kills ADRs.
- **Check for conflicts aggressively.** If grep turns up even a borderline-related decision, bring it up. Silently stepping on a prior decision is how tech debt compounds.

## Good example (excerpt)

```markdown
## Context

Multi-tenant SaaS; each tenant writes JSON blobs with 2-5 updates per request.
In production we've seen ~200 concurrent writes per tenant during onboarding bursts.
DynamoDB's eventual consistency on secondary indices caused two audit bugs in Q1 —
see incident #142 and ADR 0003's rollback discussion. We need transactional writes
across multiple rows per request, with serializable isolation.

## Decision

Postgres 15 as the primary store; Redis retained for session state only.
DynamoDB is deprecated for new services.
```

## Bad example (what to avoid)

```markdown
## Context

We needed a database.

## Decision

Use Postgres.

## Alternatives considered

None.
```

Reject this shape — push the user until the ADR earns its number.

## Integration

- After writing, report:
  - ADR path: `fastpace/docs/adr/<NNNN>-<slug>.md`
  - Updated pointer in `fastpace/context/decisions.md`
  - If superseded: which ADR's status you updated
- Suggest: `git add fastpace/docs/adr/<file> fastpace/context/decisions.md` and a conventional commit `docs(adr): accept <title> (<NNNN>)`.
- If the ADR touches module boundaries or the data model, suggest `/fp-review-pr` on the next PR in that area — reviewers should cite it.

## Exit criteria

- `fastpace/docs/adr/<NNNN>-<slug>.md` written with full four-section body.
- `fastpace/context/decisions.md` updated with a one-line pointer.
- If superseding: the old ADR's Status field updated (body untouched).
- Report: both file paths + the number + supersession info (if any).
