docs(adr): add ADR scaffolding (templates, README, meta-ADR)
Set up docs/adr/ as the canonical home for architecture decisions: - templates/nygard.md — default four-section format (Status, Context, Decision, Consequences) for one-way-door decisions. - templates/madr.md — MADR v4 with YAML front-matter and explicit Considered Options for decisions where rejected alternatives matter. - README.md — naming convention (NNNN-kebab-case), template-selection guidance (Nygard default; MADR for auth, queue mechanics, agent integration), status lifecycle, and ADR roster. - 0000-record-architecture-decisions.md — meta-ADR establishing the practice itself, in Nygard format. Backfilling existing implicit decisions (base-ui-over-radix, float sort_order, demo-user three-layer policy, etc.) is fase 6 of the docs-restructure plan.
This commit is contained in:
parent
6e0827399a
commit
8a7d419972
4 changed files with 268 additions and 0 deletions
66
docs/adr/0000-record-architecture-decisions.md
Normal file
66
docs/adr/0000-record-architecture-decisions.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# ADR-0000: Record architecture decisions
|
||||
|
||||
## Status
|
||||
|
||||
accepted
|
||||
|
||||
## Context
|
||||
|
||||
Scrum4Me makes several non-obvious architectural choices that aren't visible
|
||||
from the code alone — for example, why we use `@base-ui/react` rather than
|
||||
Radix, why drag-and-drop ordering uses float `sort_order` instead of integer
|
||||
positions, why authentication runs on iron-session rather than NextAuth,
|
||||
and why the demo-user policy is enforced in three layers. These decisions
|
||||
are scattered across `CLAUDE.md`, individual pattern docs, plan files, and
|
||||
commit messages. New contributors and AI agents working on the codebase
|
||||
have no fast path to the *why*, which leads to one of two failure modes:
|
||||
they either re-litigate decisions that were already settled, or they make
|
||||
changes that violate constraints they didn't know about.
|
||||
|
||||
We want a single, predictable place to record significant architectural
|
||||
choices, with enough context that a reader six months from now can decide
|
||||
whether the decision still holds.
|
||||
|
||||
## Decision
|
||||
|
||||
We adopt Architecture Decision Records (ADRs) as the canonical format for
|
||||
documenting significant architectural choices in this codebase. ADRs live
|
||||
in `docs/adr/`, are numbered sequentially with a four-digit prefix
|
||||
(`0001-...md`, `0002-...md`, …), and follow one of two templates:
|
||||
|
||||
- **Nygard** ([`templates/nygard.md`](./templates/nygard.md)) — default,
|
||||
for one-way-door decisions with a clear motivating context.
|
||||
- **MADR v4** ([`templates/madr.md`](./templates/madr.md)) — for
|
||||
decisions where weighing multiple alternatives is part of the value
|
||||
the record provides (auth, queue mechanics, agent integration).
|
||||
|
||||
The full conventions — file naming, status lifecycle, template selection
|
||||
guidance — are documented in [`README.md`](./README.md).
|
||||
|
||||
ADRs are immutable once accepted: course corrections create a new ADR
|
||||
that supersedes the old one rather than editing the original.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Architectural choices have a single, predictable home that an AI agent
|
||||
or new contributor can find with one `ls docs/adr/`.
|
||||
- The "why" of each decision is captured at the moment it's made, when
|
||||
the context is fresh, rather than reconstructed later from commits.
|
||||
- Superseded decisions remain readable, so future contributors can see the
|
||||
history of a choice without git archaeology.
|
||||
- The format scales: writing an ADR is a 15-minute activity for the
|
||||
default Nygard template, low enough overhead to be worth doing every
|
||||
time.
|
||||
|
||||
### Negative
|
||||
|
||||
- Adds a small ritual to every significant architectural decision — easy
|
||||
to skip when moving fast, leading to a stale or incomplete record if
|
||||
not enforced through review.
|
||||
- Backfilling existing decisions requires writing 5–8 retrospective ADRs
|
||||
for choices that were never recorded (planned in fase 6 of
|
||||
[`../plans/docs-restructure-ai-lookup.md`](../plans/docs-restructure-ai-lookup.md)).
|
||||
- Two templates means a per-decision choice about which to use. Mitigated
|
||||
by making Nygard the explicit default in `README.md`.
|
||||
93
docs/adr/README.md
Normal file
93
docs/adr/README.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
title: Architecture Decision Records
|
||||
status: active
|
||||
audience: ai-agent, maintainer, contributor
|
||||
language: en
|
||||
last_updated: 2026-05-02
|
||||
---
|
||||
|
||||
# Architecture Decision Records
|
||||
|
||||
This directory contains the Architecture Decision Records (ADRs) for Scrum4Me.
|
||||
|
||||
## What is an ADR
|
||||
|
||||
An ADR is a short document that captures a single significant architectural
|
||||
decision: the context that forced the decision, the choice we made, and the
|
||||
consequences of that choice. ADRs are immutable once accepted — if a later
|
||||
decision changes course, we write a new ADR that supersedes the old one.
|
||||
|
||||
We use ADRs because the project mixes several non-obvious choices (Next.js 16
|
||||
specifics, `@base-ui/react` over Radix, float `sort_order` for drag-and-drop,
|
||||
iron-session over NextAuth, demo-user three-layer policy, MCP integration
|
||||
patterns) and an AI agent reading the codebase six months from now needs to
|
||||
find the *why* without spelunking through commit history.
|
||||
|
||||
## File naming
|
||||
|
||||
```
|
||||
NNNN-kebab-case-title.md
|
||||
```
|
||||
|
||||
- `NNNN` — four-digit zero-padded sequential number, starting at `0001`
|
||||
(`0000` is reserved for the meta-ADR that introduces the practice).
|
||||
- `kebab-case-title` — lowercase, hyphen-separated, short noun phrase
|
||||
echoing the decision (`base-ui-over-radix`, not `decided-to-use-baseui`).
|
||||
- Always `.md`.
|
||||
|
||||
## Choosing a template
|
||||
|
||||
Two templates live in [`templates/`](./templates/). Default to Nygard.
|
||||
|
||||
### Nygard (default — [`templates/nygard.md`](./templates/nygard.md))
|
||||
|
||||
Use Nygard for the common case: a decision that is essentially a one-way
|
||||
door with a clear motivating context and one obvious choice. Four sections:
|
||||
**Title, Status, Context, Decision, Consequences (Positive / Negative)**.
|
||||
|
||||
Aim: ≤60 lines. Reads in under a minute.
|
||||
|
||||
### MADR v4 (when alternatives matter — [`templates/madr.md`](./templates/madr.md))
|
||||
|
||||
Use MADR when the decision involves weighing multiple alternatives that a
|
||||
future reader would otherwise re-litigate. Triggers:
|
||||
|
||||
- **Authentication / session strategy** (NextAuth vs iron-session vs Clerk).
|
||||
- **Queue / messaging mechanics** (LISTEN/NOTIFY vs Redis vs SQS).
|
||||
- **Agent integration patterns** (REST polling vs MCP vs SSE channel).
|
||||
- **Schema or data-model choices with non-trivial migration cost.**
|
||||
- Any decision where you want to record the *rejected* options so future
|
||||
contributors don't propose them again.
|
||||
|
||||
MADR adds: YAML front-matter (status, date, decision-makers, consulted,
|
||||
informed), explicit Decision Drivers, Considered Options, Pros and Cons of
|
||||
each option, Confirmation, and More Information.
|
||||
|
||||
## Status lifecycle
|
||||
|
||||
```
|
||||
proposed → accepted → (optionally) superseded by NNNN
|
||||
↘ (optionally) deprecated
|
||||
```
|
||||
|
||||
- **proposed** — drafted, awaiting decision-maker sign-off.
|
||||
- **accepted** — current binding decision; the codebase reflects this.
|
||||
- **superseded by ADR-NNNN** — replaced. Keep the file; never edit the
|
||||
Decision section. Add a one-line "Superseded by …" note at the top of
|
||||
the Status section and link to the new ADR.
|
||||
- **deprecated** — still current but no longer recommended; usually a
|
||||
precursor to a future supersession.
|
||||
|
||||
Once an ADR is accepted, it is immutable except for the Status field and
|
||||
typo fixes. Course corrections always create a new ADR.
|
||||
|
||||
## Index of ADRs
|
||||
|
||||
| # | Title | Status | Template |
|
||||
|---|---|---|---|
|
||||
| [0000](./0000-record-architecture-decisions.md) | Record architecture decisions | accepted | Nygard |
|
||||
|
||||
When new ADRs are added, the docs index generator (`npm run docs:index`)
|
||||
will list them in [`../INDEX.md`](../INDEX.md). Update this table by hand
|
||||
when you add or supersede an ADR — the script aggregates across the whole
|
||||
docs tree, this README is the canonical ADR-only roster.
|
||||
78
docs/adr/templates/madr.md
Normal file
78
docs/adr/templates/madr.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
status: {{proposed | rejected | accepted | deprecated | superseded by ADR-NNNN}}
|
||||
date: {{YYYY-MM-DD when the decision was last updated}}
|
||||
decision-makers: {{list everyone who participated in the decision}}
|
||||
consulted: {{list everyone whose opinions were sought (typically subject-matter experts), and with whom there was a two-way communication}}
|
||||
informed: {{list everyone who is kept up-to-date on progress, and with whom there is one-way communication}}
|
||||
---
|
||||
|
||||
# ADR-{{NNNN}}: {{short title, representative of solved problem and found solution}}
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
{{Describe the context and problem statement, e.g., in free form using two
|
||||
to three sentences or in the form of an illustrative story. You may want
|
||||
to articulate the problem in form of a question and add links to
|
||||
collaboration boards or issue management systems.}}
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
- {{decision driver 1, e.g., a force, facing concern, …}}
|
||||
- {{decision driver 2, e.g., a force, facing concern, …}}
|
||||
|
||||
## Considered Options
|
||||
|
||||
- {{title of option 1}}
|
||||
- {{title of option 2}}
|
||||
- {{title of option 3}}
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
Chosen option: "{{title of option 1}}", because {{justification — e.g., only
|
||||
option which meets a knock-out criterion / which resolves a force / …
|
||||
turned out best (see "Pros and Cons of the Options" below)}}.
|
||||
|
||||
### Consequences
|
||||
|
||||
- Good, because {{positive consequence, e.g., improvement of one or more
|
||||
desired qualities, …}}
|
||||
- Bad, because {{negative consequence, e.g., compromising one or more
|
||||
desired qualities, …}}
|
||||
|
||||
### Confirmation
|
||||
|
||||
{{Describe how the implementation of/compliance with the ADR can be
|
||||
confirmed. E.g., a test, a peer review, a runtime check.}}
|
||||
|
||||
## Pros and Cons of the Options
|
||||
|
||||
### {{title of option 1}}
|
||||
|
||||
{{example | description | pointer to more information | …}}
|
||||
|
||||
- Good, because {{argument a}}
|
||||
- Good, because {{argument b}}
|
||||
- Neutral, because {{argument c}}
|
||||
- Bad, because {{argument d}}
|
||||
|
||||
### {{title of option 2}}
|
||||
|
||||
{{example | description | pointer to more information | …}}
|
||||
|
||||
- Good, because {{argument a}}
|
||||
- Bad, because {{argument b}}
|
||||
|
||||
### {{title of option 3}}
|
||||
|
||||
{{example | description | pointer to more information | …}}
|
||||
|
||||
- Good, because {{argument a}}
|
||||
- Bad, because {{argument b}}
|
||||
|
||||
## More Information
|
||||
|
||||
{{You might want to provide additional evidence/confidence for the decision
|
||||
outcome here and/or document the team agreement on the decision and/or
|
||||
define when this decision the decision should be realized and if/when it
|
||||
should be re-visited. Links to other decisions and resources might appear
|
||||
here as well.}}
|
||||
31
docs/adr/templates/nygard.md
Normal file
31
docs/adr/templates/nygard.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# ADR-{{NNNN}}: {{Short noun phrase describing the decision}}
|
||||
|
||||
## Status
|
||||
|
||||
{{proposed | accepted | superseded by ADR-NNNN | deprecated}}
|
||||
|
||||
## Context
|
||||
|
||||
{{What is the issue we're seeing that motivates this decision? Describe the
|
||||
forces at play — technical, organizational, business — that make this choice
|
||||
necessary now. State facts, not opinions. Keep it short: one or two
|
||||
paragraphs is usually enough. If a reader needs background that lives
|
||||
elsewhere, link to it instead of duplicating.}}
|
||||
|
||||
## Decision
|
||||
|
||||
{{The choice we've made, written in present tense as a declarative statement.
|
||||
"We will use X." "We adopt Y." Avoid hedging language. One paragraph.}}
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- {{What becomes easier or possible because of this decision?}}
|
||||
- {{What problem is no longer relevant?}}
|
||||
|
||||
### Negative
|
||||
|
||||
- {{What becomes harder, slower, or more expensive?}}
|
||||
- {{What did we accept as a trade-off?}}
|
||||
- {{What new risks does this introduce, and how do we mitigate them?}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue