dira decision memory for AI coding agents
$dira whydec-0029
int-0002Zero-ceremony operation — one binary, no server, no daemonactive 2026-07-29
dec-0029The cold-start budget is measured on a spawned binary, asserted on the median, gated by the minimumaccepted 2026-08-10
✗ Measure the budget in process, the way E1-L5 and internal/index already doE1-L5's 17.3ms warm and 61.2ms cold over the 200-entry fixture are honest numbers and they are not this one.
✗ Assert the ceiling against the minimum sample instead of the medianmin <= median by construction, so a ceiling read off the minimum fires strictly LESS often than one read off the median — a run whose median is 80ms passes a 60ms budget on the strength of one lucky sample.
✗ Apply a stated CI multiplier to budget.go's numbersRejected on three counts.
✗ Assert a higher percentile (p90, p99) instead of the medianA strict loosening of the statistic int-0002 was written against, and at N=20 the p90 is a SINGLE observation — the 18th sample — which is noisier than the median, not less noisy.
…4 further refusals on record
int-0002Zero-ceremony operation — one binary, no server, no daemon
dec-0029The cold-start budget is measured on a spawned binary, asserted on the median, gated by the minimum
✗Measure the budget in process, the way E1-L5 and internal/index already do
✗Assert the ceiling against the minimum sample instead of the median
✗Apply a stated CI multiplier to budget.go's numbers
✗Assert a higher percentile (p90, p99) instead of the median
…4 further refusals on record
dec-0029 ◆ accepted 2026-08-10

Arising from int-0002 — Zero-ceremony operation — one binary, no server, no daemon

The cold-start budget is measured on a spawned binary, asserted on the median, gated by the minimum

`int-0002` says a hook invocation must return in well under 100ms on a cold cache. This entry is not that number — the number is unchanged — it is what dira is allowed to conclude from measuring it.

What is measured: the shipped binary, spawned

`internal/perf` builds `./cmd/dira` and runs it as a subprocess, twenty times per measurement, over the 200-entry fixture with `.dira/cache` removed before every cold run. Never `go run`, which times the compiler. Never an in-process call.

E1-L5 measured the read path in process and reported **17.3ms warm and 61.2ms cold** over the same fixture. Both figures are honest and neither is a hook's cost: they begin at `local.Open` and a hook begins at `execve`. Everything between — process creation, the dynamic loader, Go runtime start, package init, the config read, the cache open — was measured by nothing in this repository before this lane. `E1-L6-T5`'s phase attribution put that excluded prefix at **60.8% of one cold invocation** on the maintainer's machine, with the phases summing to **98.0% of the same run's measured minimum**. An attribution that does not add up is a story; this one reconciles inside 1% against an acceptance line that asked for 10%.

Two statistics, two different jobs

**The MEDIAN carries every absolute assertion.** It is the statistic `int-0002` was written against, and since `min <= median` by construction, a ceiling read off the minimum fires strictly less often than one read off the median. That is not a theoretical hazard here: it was done once, to a live 60ms budget, and argued for as robustness.

**The MINIMUM decides whether the machine is entitled to a verdict at all.** A best sample comfortably inside the ceiling is proof the code CAN meet it, so a median outside it is a statement about the scheduler rather than about dira. Reporting that as a regression is the error this repo keeps making in new costumes: a check announcing a verdict it lacked the evidence to reach.

Three absolute budgets now carry both statistics for exactly this reason — `internal/index/latency_test.go`'s warm-cache budget, `internal/ledger/fixture`'s full-read budget, and `hooks/pre-commit`'s own spawn-floor check, which measures `dira version` and prints **NOT RUN TO A VERDICT** rather than red when that floor eats half the tightest ceiling. `internal/perf` reports its minimum today and asserts nothing with it; making that a verdict is a task with its own two-sided proof, not a constant.

**Reporting the minimum is not asserting against it, and the two must not be unified.**

The CI policy: a dedicated runner, and budget.go untouched

The perf job runs on a GitHub-hosted runner per measurement — a fresh VM executing one job and nothing else — with `-p 1`, in a job of its own, on both `ubuntu-latest` and `macos-latest`, asserting `internal/perf/budget.go` exactly as written. No multiplier, no percentile substitution, not `continue-on-error`. That is `internal/index/latency_test.go`'s lesson applied at the job level: **the answer to contention is to remove the contention, not to loosen the assertion.** What was rejected is in the alternatives above, because the alternative to writing it down is re-litigating it after the first red run.

Both platforms, because darwin-arm64 is `int-0002`'s primary user platform and a latency budget certified only on linux is certified where nobody runs the hook.

Run `31230739083` (2026-08-08), both legs green, `budget.go` unmodified:

| | ubuntu-latest | macos-latest | |---|---|---| | cold brief, median (asserted, 100ms) | 38.967 ms | 55.294 ms | | cold brief, min (uncontended estimate) | 36.987 ms | 43.245 ms | | warm brief, median (asserted, 80ms) | 14.130 ms | 29.752 ms | | cold `reindex`, median (asserted, 400ms) | 35.126 ms | 53.972 ms |

What the measured distribution says, which answers dec-0026's revisit_if

`dec-0026` parked a percentile ceiling until a measured distribution existed. It now does — **200 cold samples over 5 CI runs and 2 platforms** — and the answer is that **a percentile ceiling still cannot be derived honestly**. macOS's pooled p90 is **111.1ms**, above the 100ms budget it would be enforcing, and the variance is *between* runs rather than within them: four macOS runs sit well inside the ceiling and the fifth has every sample shifted upward, including its minimum. A within-run percentile cannot separate those two populations, so no choice of percentile fixes it. The trigger has fired, been examined, and produced a refusal rather than a threshold.

One macOS run in five did break the **median**, and it is recorded here because the lane recorded it nowhere: run `30669750621` (2026-07-31), cold median **111.073ms**, perf job red — seven minutes before `dec-0026` was written. Its **minimum was 49.678ms** against a typical macOS minimum in the low 40s, so the whole distribution had shifted: a degraded runner, not a slower dira, and exactly the case the minimum-as-discriminator exists to name.

A correction to dec-0026, which is a correction and not a reversal

`dec-0026`'s second rejected alternative gave as its reason that "the median on CI passes at roughly 95ms against a 100ms ceiling". **No CI log supports 95ms.** The figure was a projection from an earlier task report, explicitly labelled an estimate there, carried into a decision entry as though it had been measured. Real cold medians observed on the perf job run from the high 30s on ubuntu to 111.073ms on the one degraded macOS run; `dec-0026` now carries the harvested list in its own correction note.

The conclusion it reached is unchanged and in fact stronger. At n=20 the maximum IS one observation with no averaging behind it, so a 191ms sample grades the scheduler; medians of roughly 39ms against a 100ms budget make that argument more comfortable, not less. **Claiming a number no log supports is the defect this lane's whole discipline is against**, and it was committed inside a decision entry about measurement, which is why it is corrected in the entry that codifies the discipline rather than quietly fixed.

Where a local run cannot judge, and why that is not a bypass

`/usr/bin/true` — a binary that does nothing — and `dira version` — an invocation that opens no ledger — are the floor under every budget here. On the maintainer's machine, running a dozen parallel sessions, `dira version` has been measured at a **95-107ms median through this harness**, already over `warmBudget`'s 80ms, and during T5's work at a 247.50ms median in a window where `/usr/bin/true` alone took 97.57ms. A budget verdict taken there is a report on the machine.

So `hooks/pre-commit` measures the floor before reporting a red, and prints **NOT RUN TO A VERDICT, and NOT treated as red** when it reaches half the tightest ceiling. The test is not "is the floor over the ceiling" but "does the floor leave enough of the ceiling to measure dira in". Below half, the red stands and the commit fails. **CI is the authority; a local number is a diagnosis.**

The socket claim, and the honest size of it (cst-0004)

The same spawned run that carries the latency claim is the one traced for sockets, so both claims are made about one execution rather than two. `strace` observes the run on the linux leg and the test fails on any `socket`, `connect` or `socketcall` attributed to it. Three things make that worth something: a positive control that provably opens a socket is traced first on every run, so an unattached tracer makes the test SKIP rather than certify dira by silence; the control is checked untraced first, so a broken control and a broken tracer are separated; and an empty trace file is a failure, because it means tracing did not happen.

**On darwin the assertion skips and says so.** SIP blocks dtrace, and the darwin path is fail-safe by construction: if the script is wrong or the probe cannot attach, the control shows no socket and the test skips. `internal/perf/NETWORK.md` publishes that, along with what the method does not reach — one command, one ledger, one execution; not `dira ui`, which correctly listens; not a linkage check, which would be red on a correct binary today because `cmd/dira` legitimately links `net`, `net/http` and `crypto/tls` through the localhost UI. **Linkage is not evidence of abstinence. The runtime trace is.** The linux leg is required to run that test to a verdict — CI errors if it skips there — and it passed on run `31230739083`, with the control's own sockets observed in the same trace.

What was refused, recorded as refusals

- **No daemon, no resident process, no warm-up trick.** The spawn floor is the largest single phase in the attribution and a pre-forked helper would remove most of it. `int-0002` forbids them and the budget exists to protect the property they would violate. - **No network cache**, and nothing on the measured path reaches the network (`cst-0004`). - **No edit to `internal/perf/budget.go`.** Raising a number there is a decision about `int-0002`, not a fix for a red run. - **`ix.Close()` is not skipped on the happy path**, though it happens after stdout is already written and would look free. The work moves to the next process's recovery — which is the hook invocation this budget is about — and "fast because it left a mess for the next run" is the trick the budget exists to prevent. - **The parsed entries are not memoised between the cold build and the render.** It would save about 4ms and would put a value that did not come from a file read on the rendering path, trading `internal/index`'s structural invariant for a careful one.

What was *not* refused is the one pass that decided nothing: a cold build read every entry file twice, once to hash and once to parse, and the hash existed only to be compared against cached rows that do not exist on an empty cache. Removing it took `sync.list` from an 11.212ms minimum to **0.457ms**, and the removed work benchmarked on its own at **60.60ms/op against 0.70ms/op**. It is asserted by counting calls rather than by timing them, because a 5ms effect is not resolvable on a machine whose spawn floor moves between 250ms and 2.2s — and a whole-binary A/B attempted there is reported as a failure of the instrument, not as a result.

int-0002 is met, and is not superseded

On the median, on a healthy runner, 38.967ms and 55.294ms against 100ms is "well under", not a near miss. No `supersedes` edge, no clause changed, no constant touched. This entry changes what the measurement is allowed to say, not what it is measured against.

Alternatives on record — 8

✗Measure the budget in process, the way E1-L5 and internal/index already dorefused E1-L5's 17.3ms warm and 61.2ms cold over the 200-entry fixture are honest numbers and they are not this one.

Taken in process, they exclude everything between execve and local.Open: process creation, the dynamic loader, Go runtime start, package init, the config read and the cache open. A hook pays all of it. E1-L6-T5's attribution measured that excluded part at 60.8% of one cold invocation, so an in-process budget would certify the minority of the wait and call it the whole.

✗Assert the ceiling against the minimum sample instead of the medianrefused min <= median by construction, so a ceiling read off the minimum fires strictly LESS often than one read off the median — a run whose median is 80ms passes a 60ms budget on the strength of one lucky sample.

This is not hypothetical here: the substitution was made once, to a live 60ms budget, under a robustness argument, and internal/index/latency_test.go's comment exists because of it. A weakened assertion wearing a robustness argument is still a weakened assertion.

revisit ifthe claim is comparative rather than absolute — "a warm cache beats reading every file" reads the minimum on purpose, because contention inflates both arms and can flip a true result

✗Apply a stated CI multiplier to budget.go's numbersrefused Rejected on three counts.

It has no honest derivation available: a multiplier needs a paired measurement of one tree on CI hardware and on a reference machine, and no such pair exists — a factor chosen to make the first run green is a budget edit under a different name. It cannot live where the assertion lives: the tests read the constants directly, so a multiplier would be a second comparison in the workflow YAML, and two gates over one number drift apart. And int-0002's 100ms is a claim about a user's machine; a CI-only ceiling certifies a number no user experiences.

✗Assert a higher percentile (p90, p99) instead of the medianrefused A strict loosening of the statistic int-0002 was written against, and at N=20 the p90 is a SINGLE observation — the 18th sample — which is noisier than the median, not less noisy.

The measured distribution dec-0026's revisit_if asked for now exists and refuses it on evidence as well as on principle: macOS's pooled p90 is 111.1ms, above the 100ms budget a p90 ceiling would be enforcing, and one set at 100ms would be red on a correct binary roughly one run in five. That is docs/lore.md L-0001 rule 2 in its purest form.

revisit ifenough runs accumulate to separate the two populations this data mixes — the variance is BETWEEN runs, not within them, so no percentile taken inside a run can tell a degraded runner from a slower dira

✗Run the gate on a dedicated self-hosted runnerrefused dira is a public repository, and a self-hosted runner on one executes fork-PR code on somebody's own hardware.

It would also make the gate unreproducible by any contributor, which is the cst-0004 failure .github/workflows/ci.yml's header exists to prevent.

✗Report a red local run as red, like every other gate in this reporefused Every other gate is a function of the tree; this one is a function of the tree AND the hardware. `dira version` opens no ledger at all and has been measured at a 95-107ms median through this same harness on the maintainer's machine, already above warmBudget's 80ms ceiling — a verdict taken there is a report on the box. hooks/pre-commit therefore measures that floor and reports NOT RUN TO A VERDICT when it reaches half the tightest budget.

It is not a bypass: with the floor under half the ceiling the red stands and the commit fails.

✗Reinstate a single-run ceiling now that a measured distribution existsrefused The harvest supports dec-0026's removal rather than reversing it.

Across 200 cold samples, 3 of 100 ubuntu samples exceeded 100ms and the pooled ubuntu maximum was 191.0ms, while every ubuntu run median passed. A ceiling asserted over the worst of twenty spawns would have been failing the scheduler on runs where dira met the budget.

revisit ifa widening tail is ever observed with the MINIMUM beside the median rather than far under it — that is dira getting slower, and the full sorted sample list is published to the step summary on every run so it is visible without being asserted

✗Leave all of this in the code comments and log no entryrefused It is already written down four times — internal/perf/doc.go, budget.go's header, internal/index/latency_test.go and the perf job's comment — and that is the problem rather than the coverage.

A comment can be deleted in the same diff that weakens what it guards, which is exactly how the 60ms budget above lost its statistic. The failure this repo keeps re-committing in new costumes is a check announcing a verdict it lacked the evidence to reach; an entry is the form of that argument somebody has to argue WITH.

Every decision in this repo is recorded like this one.

Keep your own →