dira decision memory for AI coding agents
$dira whydec-0022
int-0002Zero-ceremony operation — one binary, no server, no daemonactive 2026-07-29
dec-0003No model client in the binary — semantic extraction is delegated to the live sessionaccepted 2026-07-29
dec-0021The regex tier stages decisions only, and `alternatives` is required except when stagedaccepted 2026-07-31
dec-0022Confirming a regex-staged decision promotes it to the semantic tier; it does not accept itaccepted 2026-07-31
✗ Waive the minItems rule for entries confirmed from the regex tierIt buys an instant keystroke by handing `dira check` exactly the entry it cannot use.
✗ Make `y` open an editor demanding the why_not before the entry can leave stagedThe most honest about what a usable decision costs, and it breaks the premise the distill surface was designed on - agents propose, the human disposes, taps not typing.
✗ Correct the docs and leave the mechanism to whichever lane builds itStops the false claim spreading but decides nothing, and the lane would arrive at exactly this fork with less context than we have right now.
int-0002Zero-ceremony operation — one binary, no server, no daemon
dec-0003No model client in the binary — semantic extraction is delegated to the live session
dec-0021The regex tier stages decisions only, and `alternatives` is required except when staged
dec-0022Confirming a regex-staged decision promotes it to the semantic tier; it does not accept it
✗Waive the minItems rule for entries confirmed from the regex tier
✗Make `y` open an editor demanding the why_not before the entry can leave staged
✗Correct the docs and leave the mechanism to whichever lane builds it
dec-0022 ◆ accepted 2026-07-31

Arising from dec-0021 — The regex tier stages decisions only, and `alternatives` is required except when staged

Confirming a regex-staged decision promotes it to the semantic tier; it does not accept it

Pressing `y` on a **regex-staged** decision hands it to the semantic tier for extraction. It does not move the entry to `accepted`.

The contradiction this resolves

`dec-0021` gives `alternatives` `minItems: 1` the moment a decision leaves `staged`. `dira sniff` writes no alternatives and no body — `dec-0003` forbids the regex tier from asserting a `why_not` it cannot know, and `dec-0019` calls inventing one what it is.

So the two rules met and produced an impossible state: `docs/design.md` §10 promises *"You say 'confirm.' That is your entire clerical workload"*, and doing exactly that would have written a schema-invalid entry. **The promise was made before the schema rule existed and neither knew about the other.**

Why promotion rather than waiver

The keystroke survives. What changes is what it means: `y` is the human saying *this is a real decision, go get its reasoning*, not *this record is complete*. The entry stays `staged` — visibly, with its extraction pending — until something can supply the rejected alternative that makes it enforceable.

That keeps the one property the enforcement surface depends on: **every non-staged decision in the ledger can be cited back at a plan.** A ledger where some accepted decisions carry no rejection is one where `dira check` is silently weaker than it looks, and nothing on the surface would say which entries were which.

What this costs, stated plainly

Confirm is no longer instant. There is now a gap between the keystroke and the entry being usable, and if the semantic tier is unavailable that gap is unbounded. The queue therefore has to show *pending extraction* as a state a human can see, or entries will silently pile up in `staged` looking rejected.

`docs/design.md` §10 and §4 are corrected in the same change, because a promise that survived its own falsification once will survive it again.

Alternatives on record — 3

✗Waive the minItems rule for entries confirmed from the regex tierrefused It buys an instant keystroke by handing `dira check` exactly the entry it cannot use.

A decision with no recorded rejection has nothing to refuse a plan against, so the enforcement surface fills with records that look enforceable and are not - which is worse than an empty ledger, because it is invisible.

✗Make `y` open an editor demanding the why_not before the entry can leave stagedrefused The most honest about what a usable decision costs, and it breaks the premise the distill surface was designed on - agents propose, the human disposes, taps not typing.

A flow that demands prose at 2am is a flow nobody runs, and an unrun capture loop captures nothing.

revisit ifthe semantic tier's extraction proves unreliable enough that a human has to write the why_not anyway

✗Correct the docs and leave the mechanism to whichever lane builds itrefused Stops the false claim spreading but decides nothing, and the lane would arrive at exactly this fork with less context than we have right now.

The contradiction is cheap to resolve today and expensive to resolve mid-build.

Every decision in this repo is recorded like this one.

Keep your own →