dira decision memory for AI coding agents
$dira whydec-0004
int-0003Replace the tool pile — kazi + dira + a subset of skills is the whole stackactive 2026-07-30
dec-0004Execution status is derived from kazi at read time, never stored in the ledgeraccepted 2026-07-29
✗ Store planned/in-progress/done/blocked as a state field on entriesA hand-entered status field is precisely what went stale in Obsidian and Linear.
✗ Have dira poll kazi and write status back into entry filesThis is the stale-field problem with extra steps, and it makes every status change a git commit — flooding the history that dec-0002 exists to keep readable.
✗ Let kazi own the whole picture and not derive anythingkazi groups by goal and can only see work that has a goal.
int-0003Replace the tool pile — kazi + dira + a subset of skills is the whole stack
dec-0004Execution status is derived from kazi at read time, never stored in the ledger
✗Store planned/in-progress/done/blocked as a state field on entries
✗Have dira poll kazi and write status back into entry files
✗Let kazi own the whole picture and not derive anything
dec-0004 ◆ accepted 2026-07-29

Arising from int-0003 — Replace the tool pile — kazi + dira + a subset of skills is the whole stack

Execution status is derived from kazi at read time, never stored in the ledger

dira owns **ledger** states (accepted, open, active). kazi owns **run** states. Every bucket a human asks for is the join of the two across `realized_by` edges, computed at read time:

| Bucket | Join rule | |---|---| | To be planned | accepted decision or active intent with **no** `realized_by` edge | | Planned | `realized_by` points at an approved proposal or an unapplied goal | | In progress | linked goal has a live run in kazi | | Completed | linked goal converged; kazi's evidence is attached by reference | | Execution-blocked | kazi reports the linked goal stuck or over-budget | | Decision-blocked | an **open question** with a `blocks` edge gating this entry |

The last row is the one only dira can produce, and it is the load-bearing one: work stalled because a human never answered a question does not appear in any execution tracker, because no goal was ever created to be stalled.

Two invariants follow. First, dira **never asserts doneness** — it inherits it, so "done" stays as objective as kazi's predicates make it. Second, when kazi is absent or errors, dira degrades to the ledger-side buckets (to-be-planned, decision-blocked, achieved/abandoned intents) and says so, rather than filling the gap with a guess.

Alternatives on record — 3

✗Store planned/in-progress/done/blocked as a state field on entriesrefused A hand-entered status field is precisely what went stale in Obsidian and Linear.

It is correct at the moment of writing and wrong within a day, and the wrongness is invisible. A derived view cannot lie: if the join says converged, kazi converged it.

revisit ifnever for hand-entry; a cached snapshot with a visible staleness timestamp is acceptable

✗Have dira poll kazi and write status back into entry filesrefused This is the stale-field problem with extra steps, and it makes every status change a git commit — flooding the history that dec-0002 exists to keep readable.

This is the stale-field problem with extra steps, and it makes every status change a git commit — flooding the history that dec-0002 exists to keep readable.

✗Let kazi own the whole picture and not derive anythingrefused kazi groups by goal and can only see work that has a goal.

The two buckets that hurt most — "decided but never planned" and "blocked on an unanswered question" — exist upstream of any goal, so kazi structurally cannot report them. That gap is the reason dira exists.

Every decision in this repo is recorded like this one.

Keep your own →