ADR-0028 — Deferred work, technical debt, and the four-slot rule
ADR-0028 — Deferred work, technical debt, and the four-slot rule #
- Status: Accepted
- Date: 2026-05-08
- Deciders: Natan
- Source: Survey of the literature (Cunningham, Fowler, McConnell,
Feathers, Martin, Hunt & Thomas, Wright at Google, Fournier). Convergent finding: tracker + ADR + lint markers + scheduled review is the four-slot system mature teams use; new artifacts beyond those rot.
Context
Context #
We've accumulated four kinds of "do this later" in the codebase:
STANDARDS_ALLOWmarkers waving past lint rules with prose
like "deferred to a future PRD" — but no future PRD existed.
- Inline
TODO:/FIXME:— already forbidden by Rule 14
in code-standards.md, but we'd want a place for the work they would have named.
- ADR bodies ending with "follow-up: …" or "future PRD
will…" — language that hides actionable work in decision documents.
- PRD bodies with
DEFERRED — NOT STARTEDrows — work
that's documented but isn't scheduled.
Each type belongs in a slot the literature already endorses; the problem isn't missing artifacts, it's missing enforcement and a single home for "deferred but real."
Decision — the four slots
Decision — the four slots #
| Slot | What it carries | Lifetime | Source citation |
|---|---|---|---|
STANDARDS_ALLOW markers | Bounded, lint-detectable rule exceptions | Until the marker's referenced ticket closes | Wright (Google) on linkable inline markers |
| ADR | Decisions — including deferral decisions with explicit revisit triggers | Immutable; superseded never edited | Nygard 2011 "ADRs"; Fowler |
PRD (01–98) | Self-contained, scheduled scopes of work | Closes when complete; tracker reflects state | Existing project convention |
| PRD-99 (this ADR) | Deferred-but-real work — the debt register | Permanent; rows graduate out into numbered PRDs when scheduled | McConnell (Construx) "debt list"; Fowler "TechnicalDebt" |
No new artifacts. No TODO.md, no wiki debt-log, no BACKLOG.md. The four slots above are the only places deferred work lives. Anything else gets rejected at review.
Rules
Rules #
R1 — STANDARDS_ALLOW must reference a tracker entry #
Every STANDARDS_ALLOW marker carries one of three recognizable references after the rule name:
- A PRD sub-item id:
STANDARDS_ALLOW: rule-22-test-coverage — see PRD-99 §99.1.1. - An accepted ADR id:
STANDARDS_ALLOW: rule-30-env — see ADR-0021. - The literal
permanent (per ADR-0028 R1)token plus a one-
sentence rationale, for permanent exemptions where no follow-up work exists or is expected. Example: STANDARDS_ALLOW: rule-22-test-coverage — permanent (per ADR-0028 R1): glue around third-party transports.
Bare deferral language ("deferred to a future PRD", "convention adoption tracked" without an id, etc.) is rejected at review. The lint check (rule-32-allow-marker-references, added in this ADR) flags missing ids on every STANDARDS_ALLOW line.
Why a permanent token at all? Some markers (third-party glue, reviewer-only conventions whose enforcement would be busywork) genuinely have no follow-up. ADR-0028 R1 says: name that fact explicitly so the lint rule passes and reviewers know not to file a PRD-99 row for it. Permanent markers should be rare; if more than ~5 accumulate, the rule itself is suspect.
R2 — Inline TODO/FIXME/XXX forbidden (existing Rule 14, restated) #
Already enforced. Anything that survives commit review must point at a tracker row. The negative space — no inline TODOs — is load-bearing; we delete-or-track instead of accumulating bit-rot markers (Hunt & Thomas's broken-windows principle).
R3 — PRD-99 carries deferred-but-real work #
Every sub-item in PRD-99 carries the standard six fields the tracker already requires (What / Files / Contract / Dependencies / Verification / Subagent prompt) plus a seventh:
- Trigger — the condition under which this sub-item should
graduate to a numbered PRD. Examples: "when gap-rate > 0 across 5 consecutive runs," "when SQA gains a second SUT," "when N >= 3 contributors are working on the codebase."
The Trigger field is what distinguishes debt from a TODO. If you can't write a trigger, the work isn't well-scoped enough to defer. If the trigger reads "we should do this someday," delete the row — it isn't debt, it's noise.
R4 — ADR deferrals point at PRD-99 rows #
When an ADR's Consequences section says "follow-up: …" or "a future PRD will…", the ADR must reference an existing PRD-99 row id. ADR bodies don't create work — they record decisions that reference work already filed in PRD-99.
R6 — A sub-item is not "done" until 4/4 tracker checkboxes are [x] #
Every tracker row has four checkpoints earned in order:
implemented → tested → verified → changelog → (commit)The fourth checkpoint, Changelog, requires that the CHANGELOG.md [Unreleased] block contain an entry describing the sub-item, staged in the same commit that lands Implemented. This is the order the README's "Working on the codebase" loop and CONTRIBUTING.md already prescribe — the tracker now makes it visible per sub-item.
Why this matters: without the explicit checkbox the Changelog step rots first. CI's doc-sync gate catches code-vs-doc drift but doesn't enforce per-sub-item changelog entries. This rule turns the human-facing tracker into the enforcement point. A reviewer seeing [x][x][x][ ] knows the change is missing its CHANGELOG entry and rejects the PR.
Backfill: rows from before this rule landed where the historical commit didn't touch CHANGELOG.md carry [?] rather than [ ] or [x] — visible audit surface; we don't fabricate compliance, we mark it unknown. Future rows must be [x] from the first commit.
R5 — Cadence: monthly review #
PRD-99 gets reviewed monthly. The review's job:
- Promote rows whose Trigger has fired into a numbered PRD.
- Delete rows whose Trigger is no longer plausible.
- Re-cost rows that have aged.
- Reject new bare-text additions — every row must carry the
seven fields including Trigger.
McConnell argues 10–20% capacity allocation; for SQA's stage that's premature. Monthly review is cheap and stops PRD-99 from becoming a landfill.
Consequences
Consequences #
Behavioural #
- The four
STANDARDS_ALLOWmarkers currently saying "deferred
to a future PRD" without an id get updated to cite PRD-99 sub-items in the same commit as this ADR's seed entries.
- A new lint rule (
rule-32-allow-marker-references) rejects
STANDARDS_ALLOW lines that don't end with a recognizable reference (PRD-NN §NN.M.K, ADR-NNNN, or none).
- PRD-99 starts populated with the 4–5 known debt items
(test-file gaps, gap-log durability, second-SUT scaffolding).
- Tracker grows a
99 — Tech Debtsection. Rows in that section
use the same six checkbox columns; the Trigger field lives in the PRD body, not the tracker (otherwise tracker becomes unreadable).
Architectural #
PRD-99is the only PRD reserved permanently. Numbers01–98
remain available; 99 is debt; 100+ if ever needed (this is not a problem we'll have for years).
- ADRs that create work get rejected — work goes in PRD-99
first, then the ADR references it.
- The four-slot rule is now a doc-sync gate concern: the LLM
pre-commit gate (scripts/llm-gate.ts) reads ADR-0028's rules and flags additions that don't conform.
Falsifiability #
- After 6 months, count
STANDARDS_ALLOWmarkers without ids:
should be zero. If non-zero, R1 isn't enforced and this ADR has failed.
- After 12 months, count PRD-99 rows older than the cadence
with no Trigger evaluation: should be zero. If non-zero, R5 isn't being practiced and the register has rotted.
- A reviewer rejects a PR adding a bare
TODO:orFIXME:and
cites this ADR — the system is working.
What this ADR does NOT do #
- It doesn't introduce capacity allocation rules. Future ADR
if/when the team grows.
- It doesn't introduce automated debt scoring (Fowler's
Technical Debt Quadrant remains aspirational here). Cost is a rough estimate per row, eyeballed, not modelled.
- It doesn't change any existing PRD numbering or content.
See also
See also #
rules; 99-tech-debt.md follows them.
- Code standards ↗ Rule 14
(no inline TODOs) and the new Rule 32.
- Cunningham (1992): https://www.youtube.com/watch?v=pqeJFYwnkjE
- Fowler, TechnicalDebt: https://martinfowler.com/bliki/TechnicalDebt.html
- McConnell (Construx), Technical Debt:
https://www.construx.com/blog/technical-debt-2/
- Feathers, Working Effectively with Legacy Code (2004).
- Martin, Clean Code (2nd ed.) Ch. 17.
- Nygard 2011, Documenting Architecture Decisions.