Locked Decisions in Docs
Locked decisions in docs
A long-lived project accumulates decisions that get debated once, settled, and then keep getting relitigated by every new contributor who didn't see the debate. The fix is a section in the docs that lists those decisions explicitly with a "do not relitigate" header.
The shape
In mxr's docs/web-app.md:
## Locked decisions (do not relitigate)
These were debated once and locked. Stack:
| Concern | Choice | Rationale |
|---|---|---|
| Framework | React 19 + TypeScript strict + Vite 7 | Industry-standard; Vite for fast dev |
| Routing | TanStack Router (typed, file-based) | Per-route chunks for free |
| Compose default | CodeMirror 6 + @replit/codemirror-vim | Full vim surface, Markdown source |
| ...
Paired with an explicit rejection list:
Architectural rejections (do not propose these):
- Provider-direct calls from the SPA
- Per-account UI prefs
- Mobile / phone responsive
- Native desktop wrapper
- Redirect-based OAuth
What this section does
A reviewer sees a PR proposing one of the rejected items and has somewhere to point: "this is in the rejection list; the rationale is X; open an issue if you want to revisit." Without the list, every new contributor relives the same conversation. With it, the conversation is short.
It's not gatekeeping; it's archived consensus. The "do not relitigate" framing is honest about why: not "this is forever," but "we already had this argument; if you want to reopen it, surface a new constraint, not the original one."
When a locked decision deserves revisiting
The list isn't sacred. Reopen when:
- A new external constraint appears (regulation, ecosystem change, dependency abandonment)
- The original rationale stops holding (benchmark changes, library matures, the constraint that drove the choice goes away)
- A pattern that the list rejects keeps coming up — that's a signal the constraint is mismatched with reality
What doesn't qualify: aesthetic preference, "I like X better," or "the docs of X are nicer." If the answer is "we considered that and rejected it," cite the rationale; don't reopen.
Where to put it
The locked-decisions section lives in the same doc as the architecture overview. Not in a separate ADR folder that nobody reads; in the doc that the next contributor reaches for. ADRs are great for the long history; the locked list is for the next thirty seconds of someone's PR review.
For long-running architectural choices, both can coexist: an ADR captures the full reasoning at decision time, and the doc's locked-decisions table is a one-line pointer with a decision-log.md link for anyone who wants the full debate.
The complementary section
Lock list pairs naturally with "Out of scope (do not implement)" — a list of things people will reasonably ask for but the project explicitly will not do. Same purpose: archived no, with rationale, so the next contributor doesn't open the PR.
Mxr's web app doc has both. They're under different headings because they answer different questions: "should I rewrite this with X?" (locked decisions) vs. "should I add Y?" (out of scope).
Where this fits in the docs discipline
It's an instance of operationally useful docs applied to architectural reading. A reviewer landing on the doc has a job: decide whether this PR is acceptable. The locked-decisions section is the section that section can land on and immediately use. It passes the deletion test in reverse — if you delete it, every PR review gets longer.
See also
- How I Write Software Docs — the broader docs principles this slots into
- Mxr —
docs/web-app.mdis the concrete example