Repository navigation
writ status fails on a store that has never been written; a fresh install cannot run it #756
Description
Feature: #762 — The writ lifecycle surface: reconcile, scopes, and the vocabulary settlement
writ status against a store that has never been written fails, where it should report that nothing has run.
$ writ status --store "$(mktemp -d)"
Error: read run index /tmp/tmp.XYZ/index.ndjson: open /tmp/tmp.XYZ/index.ndjson: no such file or directory
Why this surfaced now
--store was registered and read nowhere until #753, so the empty-store path was unreachable: every
invocation folded the default store, which on a developed machine always has an index. Fixing the flag made
the state reachable for the first time.
It is not confined to --store. A machine that has installed the suite and not yet deployed anything has no
index either, so writ status fails on a fresh install for the same reason -- the first thing a new user is
likely to run.
Why an absent index is not an error
An index that cannot be read and an index that does not exist are different facts. The first is a store
whose contents disagree with itself, which Health.Findings already reports without failing. The second is
a store where nothing has run, which is the ordinary state of a new one and the honest answer to the
question writ status asks.
The report already has a shape for it -- runs: 0, entries: [] -- and reaches it whenever the index is
present and empty. Only the missing-file case diverges.
Fix
Treat a missing index as an empty one. A read error that is not fs.ErrNotExist stays an error, since a
store that exists and cannot be read is a real failure.
Care is needed in one place: entries currently serializes as null rather than [], because a nil slice
marshals to null. jq '.entries[]' errors on null and yields nothing on [], so the empty case should
produce the latter. packages has the opposite convention -- omitempty, so it disappears entirely --
which is worth settling at the same time: one struct should not carry two meanings of empty.
Verification
writ status --store <fresh>exits 0 and reportsruns: 0with no findings.-o jsongives"entries": [], notnull, sojq '.entries[]'yields nothing rather than failing.- A store whose index exists but cannot be read still fails, and names the path.
- A store whose index references documents that are gone still reports findings rather than failing, as it
does today.
Ruled 2026-09-23 (schedule #916, lane 4, PR B)
Reconcile is valid only after a deployment (#762). Three exit codes, so a script can gate on the answer the way
git diff --exit-code does:
| Answer | Exit |
|---|---|
| never deployed: no record to compare against | not-found -- ExitNoInput (66, EX_NOINPUT), the sysexits code for input that cannot be opened |
| deployed and clean: the system matches the record | ExitOK (0) |
deployed and drifted: any absent, changed, dangling or stale finding (#923) |
ExitError (1): the command ran; the answer is drift |
This issue was filed against the opposite reading (reconcile works on a fresh install); it closes the ruled way.
The code that assigns the three is this lane's; the vocabulary of the findings is #923's.
Activity
Plan: the writ lifecycle surface — reconcile, scopes, and the vocabul…
The end-to-end record says what actually ran
A document rendering, a terminal one, the renderings grouped, and pag…