kadence

Recording why

Decisions as events, superseding that cannot half-apply, and documents linked to the work they explain.

The journal records what happened. Since 0.3.0 it also records why — and the reasoning cannot quietly go stale, because reversing a decision is one event rather than two edits somebody has to remember to make.

Record a decision

kadence decision add "Store sessions in a signed cookie" \
  --why "The redirect drops server-side session state" \
  --rejected "Server-side sessions: the redirect is where they break" \
  --task KAD-1
DEC-1 recorded.

--why is required. Without it the record says only what changed, and git already says that. --rejected is the field that pays for itself later: it is what stops the next session — human or AI agent — from proposing the thing that was already tried.

--task attaches the decision to the work it came out of, so it comes back with kadence task show. --doc points at a document that carries the detail.

Reverse it later

kadence decision add "Signed cookie, rotated hourly" \
  --why "A stolen cookie stayed valid for a week" --supersedes DEC-1
DEC-2 recorded.
It replaces DEC-1, and both links were written by one event — neither side can go stale.

That sentence is the whole feature. In a file-based tool, superseding is two edits: mark the old record replaced, and note in the new one what it replaces. The sources on ADR practice are blunt about what happens — somebody updates one side, and a reversed decision goes on looking authoritative. Here the backward link is derived while folding, so nobody writes the second half and nobody forgets it.

What you get back is what still holds

kadence decision list          # decisions in force
kadence decision list --all    # with the history
kadence decision show DEC-1
DEC-1  Store sessions in a signed cookie

!! SUPERSEDED by DEC-2 — this is no longer in force.

Why:      The redirect drops server-side session state
Rejected: Server-side sessions: the redirect is where they break
Task:     KAD-1

The default is the safe answer, because an AI agent quoting a reversed reason as current is worse than one with no memory at all. show announces the supersession before the reasoning, for the same reason.

DEC-N is derived, like KAD-N

Identity is the ULID; the number is assigned while folding. Two branches can each record a decision and merge without a conflict and without a renumber — an integration test on real git branches proves it. log4brains, a mature ADR tool, dropped file numbering entirely to avoid exactly this conflict; keeping both is what the event model buys.

Who wrote it

Since 0.3.1 every decision carries its author's kind — source: "human" or "agent", taken from KADENCE_SOURCE at the moment the event was written. kadence never guesses this when writing; the field is what makes that refusal worth something when reading. decision list and decision show print it, and the human output marks only agent-written records: in a repository written mostly by people, labelling every human one would hide the exception.

DEC-3  Fold notes into prime          agent

Documents, linked rather than stored

kadence task doc KAD-1 docs/design.md
kadence decision add "…" --why "…" --doc docs/auth.md

kadence does not store the document. It stays plain markdown, and git keeps versioning it. What git cannot say is that this file explains this task, and that is the only thing recorded.

A missing file is a warning, not a refusal — it may arrive in a later commit or live on another branch, and refusing would make the journal depend on what happens to be checked out.

There is deliberately no kadence doc command. The event model gives a document nothing git does not already give it; the link is the part that was missing.

What that is worth, measured

Across five real questions in the kadence repository, a grep for the natural term finds the answering document every time — and buries it among 10–35 candidates: 1.3 MB of candidates against 39 KB of linked documents.

The link does not save the search. It saves the sifting, and sifting is what costs a context window. The stronger argument needs no numbers: grep requires knowing the term, and a link arrives with the task.

Full write-up: Probe D.

For an AI agent

task show --json carries decisions and docs; both are always arrays, so an agent never has to branch on their absence.

kadence decision list --json
{"schema":"kadence/v1","ok":true,"decisions":[{
  "label":"DEC-2","title":"Signed cookie, rotated hourly",
  "why":"A stolen cookie stayed valid for a week","rejected":null,
  "task":"KAD-1","docs":[],"supersedes":"DEC-1","supersededBy":null,
  "superseded":false,"at":"2026-09-08T14:31:39.221Z","by":"ana@example.com"}]}

The reasoning is in ADR-010.

On this page