decision-journal / references/entry-kinds.md
Entry kinds
A reference shipped with the skill · 1,263 words
Entry kinds
Six kinds. Choosing the wrong one is not fatal, but each carries different fields and is read differently, so the choice affects what a later reader can ask.
All six share the same envelope, the same anchors and influences, the same retraction
edges, and the same disclosure class. Every kind takes
--disclosure private|team|published on record (and invalidate takes it too) — the
write default is team, and an unrecognised value is refused rather than silently
contained. See references/digest-and-disclosure.md for what
the class controls, and the asymmetry between what a write defaults to and what a parse
defaults to.
Separate from disclosure, and with no flag of its own because no kind opts out of it:
every write also passes through automatic secret redaction. A recognised credential
appearing in free text is masked in place before the entry is stored; a payload the
redactor cannot scan at all — oversized, or too deeply nested — is refused outright.
That runs identically whichever disclosure class the entry is headed for; a private
entry gets no less scrutiny than a published one.
Every kind takes its own fields through record, and only its own — passing a field
that belongs to another kind is refused with a message naming what this kind does take,
rather than being silently dropped. --rejected, --evidence and --premise are
repeatable and store arrays.
decision
A choice between options that a reasonable person could have made differently.
| Field | Holds |
|---|---|
question |
What was being decided |
chosen |
What was picked |
rejected[] |
Alternatives and why not — the field nothing else captures |
rationale |
Why |
reversibility |
trivial / moderate / hard / one-way |
blastRadius |
Who or what is affected when it takes effect |
agent-journal record --workspace api --kind decision --id d1 \
--question "how do we bound the retry queue?" \
--chosen "in-process ring buffer, 256 entries" \
--rejected "redis list — needs a broker we do not run" \
--rejected "kafka — three days of setup for one queue"
reversibility and blastRadius are not the same thing, and conflating them is a
real error. Flipping an enforcement flag is trivial to reverse — unset it and redeploy
— while its blast radius is every user currently signed in. The rollback cost and the
user cost are unrelated, and the trivial score is precisely the wrong signal.
finding
Something you learned that was not obvious, and that changes what someone should do.
| Field | Holds |
|---|---|
claim |
What you found |
evidence[] |
What supports it |
premise[] |
What must be true for this to hold |
scope |
This machine / this workspace / general |
agent-journal record --workspace api --kind finding --id f2 \
--claim "the 256 bound is never reached in practice" \
--evidence "two weeks of queue-depth samples" \
--premise "traffic stays within its current envelope" \
--scope workspace
scope here is one of machine, workspace or general — a constraint's scope is
free text, because it names a subject rather than a reach.
premise is what makes a premise re-check possible later. scope prevents the most
common failure with findings: a fact true of one laptop's PATH propagating as a fact
about the project. If you are not certain a finding generalises, scope it narrowly — a
finding wrongly marked general is worse than one wrongly marked local.
assumption
Something you proceeded as though were true, without checking.
| Field | Holds |
|---|---|
assumed |
What you took to be true |
ifWrong |
What breaks if it is not |
checked |
yes / no |
agent-journal record --workspace api --kind assumption --id a1 \
--assumed "the upstream call is idempotent" \
--ifWrong "retries double-charge" --checked no
These are the entries people are least inclined to write and that pay off most. Every incident worth the name has one of these at its root, unrecorded. When context is about to be compacted, sweeping for assumptions is the highest-value thing you can do with the remaining tokens.
blocker
Work that cannot proceed, and what would unblock it.
| Field | Holds |
|---|---|
blocked |
What cannot proceed |
on |
What it waits for |
owner |
Who can clear it |
clearedBy |
What actually cleared it, once it is |
progress
A checkpoint. Use sparingly — if you have a tracker, this duplicates it, and a journal full of progress notes buries the entries that carry judgement. Bind it to an existing ticket id rather than restating status.
constraint
A standing obligation that later work must respect. The only forward-looking kind.
| Field | Holds |
|---|---|
statement |
The obligation |
origin |
Who imposed it |
scope |
Where it applies |
expiry |
When it lapses, if it does |
enforcement |
advisory or blocking |
agent-journal record --workspace api --kind constraint --id c1 \
--statement "never a third-party sink for this telemetry" \
--origin "client contract" --scope telemetry --enforcement blocking
Everything else in the journal points backwards: this decision replaced that one, this finding rests on that evidence. A constraint points forward — never a third-party sink for this client's telemetry, this control is fixed-height by decision, not oversight, do not edit that checkout.
Constraints are checked at projection, never at write time. A new decision whose subject matches a live constraint is surfaced for a human. Nothing blocks and nothing auto-resolves — the point is that the obligation becomes visible at the moment it is relevant, not that a machine adjudicates it.
Outcome and retraction
Every kind carries an outcome: unknown, held, reverted, invalidated. This is a
schema field the CLI does not yet write directly — no kind takes an --outcome flag, so
reverted and invalidated are reached only through --supersedes/--invalidates, and
held is not reachable through record at all.
unknown is displayed, never hidden. An entry nobody revisited stays unknown, and
that is itself the signal — "nobody checked whether this held" is information a reader
needs. Silently rendering it as fine would be the single most misleading thing the
journal could do.
Two retraction edges, and the difference carries real weight:
supersedes |
invalidates |
|
|---|---|---|
| Means | A later decision replaced this | This entry's premise was false |
| The original was | Reasonable at the time | Never sound |
| Effect on descendants | None | Suppressed, transitively |
| In a digest | outcome reverted |
outcome invalidated |
Invalidation propagates through influences links of type journal, walked at the
projection layer. If B records that it rests on A and A is invalidated, B goes too — and
anything resting on B. That is the whole reason the two edges are separate: superseding
a decision does not cast doubt on the work built atop it, and invalidating one does.
Record the edge with --influence journal:<role>:<id>. agent-journal show reports the
result: an entry that declared a dependence on an invalidated one reads
outcome: invalidated, live: false without being named in the retraction.
Neither edge deletes. Both are appended events that change how the record projects.