# Decision ledger

Version: 1.0
Updated: 2026-10-02
Method: https://suhailmohebi.com/notes/decision-ledgers/

Purpose: keep every inherited rule together with its reason, its evidence and the event that should reopen it.

Output: a compact, append-only ledger whose rules can explain themselves after the original conversation is gone.

## Use when

Long-running agent work keeps inheriting rules, and someone is about to obey an old rule blindly or drop a sound one because its reason is invisible.

## Quick start

1. List the rules a new agent would be tempted to question, and write one entry for each (section 1).
2. Give each entry a status and an observable review trigger (sections 1 and 2).
3. From then on, append evidence before changing any rule, and record every review outcome (sections 3 and 4).

Record a decision as a supported claim, not a commandment.

## 1. Write one compact entry per rule

Add an entry when a choice changes how later work is done, settles a recurring ambiguity, protects a boundary or reverses an earlier rule. Skip routine activity, temporary preferences and facts a better source already owns.

```text
D-000 · Owner: [role] · Opened: YYYY-MM-DD
Status: Provisional | Active | Under review | Revised (replaced by D-0xx) | Retired
Rule: [one scoped, actionable sentence]
Why: [the observation that made it sensible; link an ADR if one exists]
Review trigger: [an observable event that could make the rule wrong]
Supersedes: [D-0xx or none]
Evidence (append only):
- YYYY-MM-DD [+ supports | - challenges | ~ narrows] [fact] ([source])
Outcomes (append only):
- YYYY-MM-DD [trigger that fired] -> Keep | Revise (D-0xx) | Retire: [reason]
```

## 2. Move the status, never the history

| Status | Meaning | Moves to |
|---|---|---|
| Provisional | the smallest rule that fits the observation | Active when the owner accepts it |
| Active | future work follows it | Under review when its trigger fires |
| Under review | the trigger fired; the rule still applies until judged | the recorded outcome |
| Revised (replaced by D-0xx) | the principle survives; its wording, boundary or owner changed in a successor entry | nothing; the successor carries on |
| Retired | the constraint is gone, or the rule now adds more risk than it removes | nothing |

Never erase a revised or retired entry: an agent may still meet the old rule, and a visible status and successor link let it reject it safely.

## 3. Append evidence; do not rewrite the past

- Add new evidence to the entry before changing the rule. A changed rule is a new entry, never an edit.
- Log only evidence that changes confidence, scope or timing: one dated line with a source, marked `+`, `-` or `~`.
- Keep disagreement visible: a challenge stays in the log even if the rule is kept.
- The only line you may edit in place is `Status:`.

If the ledger lives in git, check each change to it (in CI, pass `origin/main...HEAD` from a full clone):

```bash
# ledger-check.sh [REV]   Read-only. Fails if a change edits or removes any ledger line but Status.
LEDGER="docs/decisions.md"; rev="${1:-HEAD}"
[ -f "$LEDGER" ] && d=$(git diff --no-color --no-ext-diff -U0 "$rev" -- "$LEDGER") || { echo "STOP: cannot diff $LEDGER against $rev"; exit 2; }
if printf '%s\n' "$d" | grep '^-' | grep -v '^--- ' | grep -v '^-Status:'; then
  echo "STOP: the lines above rewrite ledger history; append evidence or a new entry instead"; exit 1
fi
echo "OK: $LEDGER change is append-only"
```

A pass proves history was not edited, not that the evidence is true.

## 4. Review when a trigger fires, not when the calendar says so

Good triggers: the source of truth changes; a protected boundary disappears; the same exception recurs; a new capability removes the original constraint; conflicting evidence reaches the weight of the original case. “Review quarterly” is not a trigger. A calendar may surface dormant entries, but only a trigger tells the reviewer what to look for.

1. Set `Status: Under review` and append the event that fired as evidence.
2. Re-read Why: does the original observation still hold?
3. Weigh every evidence line, for and against, against the rule’s current scope.
4. Decide explicitly:
   - Keep: the reason holds and evidence supports the same scope.
   - Revise: the principle survives, but its wording, boundary or owner changes. Open a successor with `Supersedes:` and set this entry to `Revised (replaced by D-0xx)`.
   - Retire: the constraint is gone, or the rule creates more risk than it removes.
5. Append the outcome and its reason, then update every brief, prompt or instruction file that copies the rule.

## 5. Check for policy theatre

| Symptom | Fix |
|---|---|
| Conclusion only: the rule keeps no cause | write the smallest Why that explains it, or set it back to Provisional |
| Evidence as decoration: links that change nothing | add only lines that move confidence, scope or timing |
| No trigger: Active has quietly become permanent | name one observable event |
| History rewritten: current wording hides reversals | restore the old text from version control; append instead |
| Everything logged: decisions buried in activity | retire non-decisions with that reason; keep activity in a work log |
| No successor link: two valid-looking rules compete | open a successor whose `Supersedes:` names both; set both to `Revised (replaced by …)` |

## 6. Ledger entry or architecture decision record?

| | Ledger entry | Architecture decision record (ADR) |
|---|---|---|
| Unit | one operating rule that future work inherits | one significant decision and the forces behind it |
| Holds | rule, why, evidence, trigger, status, outcomes | context, decision, status, consequences; MADR adds options, drivers and confirmation |
| Over time | evidence and outcomes are appended | a later ADR changes or reverses it; the old one is marked deprecated or superseded |
| Size | a few lines | one or two pages |

Write an ADR when the decision shapes structure, dependencies, interfaces, non-functional qualities or construction techniques, when alternatives were weighed, or when stakeholders must accept it. Then keep a ledger entry whose Why links the ADR: the ADR holds the reasoning, the ledger the operating rule and its trigger.

## Worked example

```text
D-021 · Owner: integration lead · Opened: 2026-07-30
Status: Revised (replaced by D-027)
Rule: Agents change a generator's inputs, never its generated files.
Why: A hand-edited sitemap was overwritten by the next build (2026-07-29).
Review trigger: A generated file loses its generator, or the same exception is requested twice.
Supersedes: none
Evidence (append only):
- 2026-08-12 + An agent proposed editing feed.json; the rule sent it to the source data instead (handoff H-31).
- 2026-09-18 - llms.txt is now written by hand; no generator exists for it (repository audit).
Outcomes (append only):
- 2026-09-18 trigger fired (llms.txt has no generator) -> Revise (D-027): keep the rule for files that have a
  generator in the repository; list hand-maintained files explicitly.
```

Only `Status:` changed (Active, Under review, Revised). D-027 opens with `Supersedes: D-021`, the narrower rule and the same trigger.

**Verdict:** the rule survived in a narrower form. An agent that still reads D-021 sees the successor and can reject the old wording.

## Stop if

- You cannot state an entry’s Why: do not enforce it; mark it Provisional and ask its owner.
- Two active rules conflict and neither links the other: settle them with both owners before acting on either.
- A trigger fired and nobody owns the decision: keep it Under review and escalate; an agent must not decide its own boundary.
- The change edits a rule’s wording or old evidence: write a successor entry instead.
- The decision needs stakeholder agreement or a record of options and consequences: write an ADR first.

## Sources

- Michael Nygard (Cognitect): Documenting Architecture Decisions — https://www.cognitect.com/blog/2011/11/15/documenting-architecture-decisions (checked 2026-10-02)
- ADR organisation: Markdown Architectural Decision Records (MADR) — https://adr.github.io/madr/ (checked 2026-10-02)
