Adopt a trackable working method now the repo is public: - PRs onto a protected main; --no-ff merge commits; one worktree per branch. - Reserve-first ADR numbering: scripts/adr-reserve.sh claims the next number atomically against main (push = compare-and-swap; ledger docs/adr/RESERVATIONS.log), so a number is stable from creation. - Worktree helpers scripts/wt-new.sh + wt-clean.sh. - Local-origin test harnesses (reserve 10/10, worktrees 7/7, shellcheck clean). Record the decision in ADR-0059, supersede ADR-0000's placeholder-until-merge numbering default, and add the lean CONTRIBUTING.md sections + CLAUDE.md operational rules.
112 lines
5.1 KiB
Markdown
112 lines
5.1 KiB
Markdown
# ADR-0000: Record architecture decisions
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Context
|
|
|
|
The RDBMS Playground project will accumulate design decisions as it
|
|
grows. We want those decisions to be traceable, reviewable, and easy
|
|
to challenge later when context has changed.
|
|
|
|
## Decision
|
|
|
|
Record significant architecture and product decisions as Architecture
|
|
Decision Records (ADRs) in `docs/adr/`, using the Michael Nygard
|
|
format (Status, Context, Decision, Consequences). Files are numbered
|
|
sequentially with a four-digit prefix and a kebab-case slug, e.g.
|
|
`0001-language-and-tui-framework.md`.
|
|
|
|
Each ADR captures one decision. Superseding a decision means adding a
|
|
new ADR that references the old one and marking the old one as
|
|
"Superseded by ADR-NNNN".
|
|
|
|
ADRs document decisions, not speculation. An idea under discussion
|
|
belongs in conversation, an issue, or a design note — not an ADR. An
|
|
ADR is written once a decision has actually been made.
|
|
|
|
## Index discipline
|
|
|
|
`docs/adr/README.md` contains the canonical index of all ADRs.
|
|
Whenever an ADR is added, renamed, or has its status changed (e.g.
|
|
"Superseded by ADR-NNNN"), the index MUST be updated in the same
|
|
change. An ADR change without a corresponding index update is
|
|
incomplete.
|
|
|
|
The index lists ADRs in numerical order. Each entry shows the
|
|
number, title, and — where relevant — status annotations such as
|
|
"Superseded by ADR-NNNN" or "Deprecated".
|
|
|
|
## Numbering discipline
|
|
|
|
ADR numbers are a single global sequence, so two branches can each grab
|
|
"the next number" independently and collide on merge. (This happened when
|
|
the `website` branch's ADR-0042 met `main`'s ADR-0042, resolved by
|
|
renumbering the former to ADR-0044.) To prevent it:
|
|
|
|
**Reserve the number up front, via `scripts/adr-reserve.sh`** (ADR-0059,
|
|
which superseded the earlier placeholder-until-merge default). The moment
|
|
you know an ADR is needed — at branch start or mid-branch — run
|
|
`scripts/adr-reserve.sh <slug> "<title>"`. It atomically claims the next
|
|
free number against `main` (the remote ref is the registry; a `git push`
|
|
is the compare-and-swap, retried on contention) and records it in the
|
|
append-only ledger `docs/adr/RESERVATIONS.log`. The number is then **stable
|
|
from creation**, so it is safe to cite in commit messages (immutable under
|
|
the no-rewrite rule), in other ADRs, and in the PR from the first commit.
|
|
Create the ADR as `docs/adr/<NNNN>-<slug>.md` and add its README index row
|
|
as part of the branch's normal work.
|
|
|
|
A number is "taken" once its ledger line (or `NNNN-*.md` file) is on
|
|
`main`; the script reads both to compute the next free number — never
|
|
compute "next" by hand from a feature branch. The full rationale (why
|
|
reserve-first beats number-on-merge, issue-number ids, or an allocator bot)
|
|
is in **ADR-0059**.
|
|
|
|
### Subproject ADR namespaces
|
|
|
|
A long-lived subproject developed on its own branch can escape the shared
|
|
integer pool entirely by keeping its decision records in a **separate
|
|
namespace**, rather than fighting collisions on every merge. The **website**
|
|
(`docs/website/adr/`) is the first: its ADRs use a dated sequence —
|
|
`<date>-adr-website-<NNN>.md`, referenced in prose as `ADR-website-NNN` —
|
|
and are indexed by their own `docs/website/adr/README.md`. Because the
|
|
date-plus-subproject prefix is disjoint from `main`'s integer sequence, a
|
|
website ADR and a `main` ADR can never claim "the same number" again. (This
|
|
namespace was created on 2026-06-10 after the website's ADR collided with
|
|
`main`'s on consecutive numbers — drafted 0042, bumped to 0044, both times
|
|
landing on a number `main` had taken; the move retired it from the pool as
|
|
**ADR-website-001**.) The main `docs/adr/` index carries a pointer to each
|
|
such namespace. Use this for a new subproject only when it is genuinely
|
|
self-contained and branch-isolated; one-off cross-cutting decisions stay in
|
|
the global sequence.
|
|
|
|
## Out-of-scope discipline
|
|
|
|
ADRs (and the plans they spawn) lean heavily on "out of scope" language.
|
|
The phrase carries two very different meanings, and conflating them
|
|
misleads a later reader:
|
|
|
|
- **Deferred** — out of scope *for this plan / phase / step*, but a
|
|
reasonable thing to do later. A sequencing decision, effectively a
|
|
tracked TODO. Where possible, point at where it will be picked up.
|
|
- **Rejected** — considered and deliberately *not* done, on principle.
|
|
Durable. State the reason.
|
|
|
|
When writing an out-of-scope item, **say which kind it is** — e.g.
|
|
`OOS (deferred)` / `OOS (rejected: <reason>)`, or the equivalent in prose
|
|
— so a future reader can tell a standing decision from a not-yet. A bare
|
|
"out of scope" is ambiguous and tends to read, wrongly, as permanent.
|
|
(Motivating example: ADR-0030 §13 OOS-2 was a deferred scope exclusion
|
|
that read as a permanent rejection until ADR-0039 lifted it.)
|
|
|
|
## Consequences
|
|
|
|
- New significant decisions require an ADR before or alongside the
|
|
implementation that depends on them.
|
|
- Old decisions remain visible even after they are superseded.
|
|
- Reviewers can audit the rationale chain by reading `docs/adr/` in
|
|
order.
|
|
- The index in `README.md` stays trustworthy because keeping it
|
|
current is part of every ADR change, not an afterthought.
|