dira decision memory for AI coding agents
$dira whydec-0032
dec-0032Ledger ids: persist a monotonic counter instead of allocating from a directory scanstaged 2026-09-03
✗ Keep scan-then-exclusive-create (current), only add a distill reject/tombstone dispositionDoes not stop deletion from freeing a number for reuse (issue #35); reuse-after-deletion is a categorically separate hole a persisted counter closes outright, independent of whether a live create-vs-create race also exists.
✗ git-ref reservation before each write (claim a ref before writing)Correct ordering mechanism but adds a network round-trip to every dira log call and introduces an orphaned-lock failure mode this fleet already lives with elsewhere (a stale claim past its expiry, unable to tell if the holder is alive).
✗ Server-side atomic id allocation serviceCorrect, but makes recording a decision depend on a service being up -- worse than the bug it fixes, and against dira's local-first design point (int-0002).
✗ Switch to content-addressed or time-ordered ids (ULID/KSUID)Removes the race/reuse class entirely but costs the human-readable sequential ids people already cite by number in prose, a real usability property.
dec-0032Ledger ids: persist a monotonic counter instead of allocating from a directory scan
✗Keep scan-then-exclusive-create (current), only add a distill reject/tombstone disposition
✗git-ref reservation before each write (claim a ref before writing)
✗Server-side atomic id allocation service
✗Switch to content-addressed or time-ordered ids (ULID/KSUID)
dec-0032 ◆ staged 2026-09-03

Ledger ids: persist a monotonic counter instead of allocating from a directory scan

Triage finding, 2026-09-02: internal/ledger/local/local.go Store.Create already does atomic exclusive-create (os.Link, fails if the target exists) and internal/ledger/write.go Add() already retries correctly on ErrExists, marking the id taken and advancing. This has been true since commit 4b7a0d9/b7c2f61 (2026-07-30), before v0.1.0/v0.1.1 and before every reported occurrence of issue #27. Git archaeology on hq's ledger (dec-0542/dec-0544, via macbook-chief) shows a single linear commit history with no merge and no discarded parent, ruling out a cross-branch merge collision and best fitting a single shared working tree. The most likely mechanism: an entry was created (successfully, atomically) but never committed, then deleted before commit (matching issue #35's exact bug), freeing its number for a later session's legitimate reuse -- not a live Add-vs-Add race. A persisted monotonic counter closes #35 unconditionally either way, and as a side effect turns two sessions independently bumping the same counter into a loud git merge conflict on the counter file, instead of a silent duplicate id.

Alternatives on record — 4

✗Keep scan-then-exclusive-create (current), only add a distill reject/tombstone dispositionrefused Does not stop deletion from freeing a number for reuse (issue #35); reuse-after-deletion is a categorically separate hole a persisted counter closes outright, independent of whether a live create-vs-create race also exists.

Does not stop deletion from freeing a number for reuse (issue #35); reuse-after-deletion is a categorically separate hole a persisted counter closes outright, independent of whether a live create-vs-create race also exists.

✗git-ref reservation before each write (claim a ref before writing)refused Correct ordering mechanism but adds a network round-trip to every dira log call and introduces an orphaned-lock failure mode this fleet already lives with elsewhere (a stale claim past its expiry, unable to tell if the holder is alive).

Rejected in GH issue #27's own comment thread, 2026-09-02.

✗Server-side atomic id allocation servicerefused Correct, but makes recording a decision depend on a service being up -- worse than the bug it fixes, and against dira's local-first design point (int-0002).

Rejected in the same #27 thread.

✗Switch to content-addressed or time-ordered ids (ULID/KSUID)refused Removes the race/reuse class entirely but costs the human-readable sequential ids people already cite by number in prose, a real usability property.

Issue #27's own body raised this as a fallback, not a first choice.

revisit ifa stress test on ledger.Add finds a genuine live create-vs-create collision the current exclusive-create retry does not catch, at which point the fix must also touch Add itself, not only allocation

Every decision in this repo is recorded like this one.

Keep your own →