From afd48df9b69868fa7084e625414ecb505cc138a8 Mon Sep 17 00:00:00 2001 From: MongLong0214 Date: Sat, 8 Aug 2026 15:51:14 +0900 Subject: [PATCH] Say what a read-only run actually does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Section 8.2 promised zero writes. Writing section 11's read-only test strictly is what found the promise false: a plain run touches `index.db-shm`, and `--fix` creates that and `-wal`. Those are SQLite's bookkeeping for a WAL database, created by opening one at all, for readers as much as writers, and they hold no committed data. Two ways to close the gap. Making the run literally write-free means opening the index outside WAL for doctor, which trades a documentation problem for the concurrency one #420 was about. So the document moves instead, and states the invariant that carries the meaning: `index.db` is byte-identical after a plain run, including under failure, and nothing else in the repository changes but those two sidecars. The acceptance row moves with it. A table that still said "zero writes" while the test asserted something narrower would leave the next reader to discover which one to believe. Limit: the exception is named for SQLite specifically, so a future dependency that touches the filesystem on open would need its own line rather than being covered by this one Ruled-out: opening the index outside WAL so the promise becomes literally true | it reintroduces the concurrency failure #420 fixed, to make a sentence accurate Ruled-out: leaving §8.2 and scoping only the test | the document is what a reader checks the code against, and a test quietly narrower than the promise it implements is the arrangement this milestone exists to remove Warn: `--fix` creates the `-wal` file that a plain run does not, so the two paths differ in what they leave behind even though neither writes data Blast: local Undo: easy Certainty: firm Verified: the three read-only invariant cases pass against the amended wording, asserting `index.db` equality and a filtered inventory rather than an unqualified zero Provenance: authored Record-Id: r-prdwrites --- docs/DOCTOR-PRD.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/docs/DOCTOR-PRD.md b/docs/DOCTOR-PRD.md index 9806266..207cd52 100644 --- a/docs/DOCTOR-PRD.md +++ b/docs/DOCTOR-PRD.md @@ -506,9 +506,20 @@ Node-only by decision (ADR-0026) and has no brew channel. exit `0`. The first revision said "No network. No socket, ever" — false against the shipping command, a review finding, corrected here rather than narrowed silently. -2. **No writes without `--fix`.** A plain run is read-only including under - failure; `--fix` applies only reversible local config and reports every - change via `fixed: true` on the row it fixed. +2. **No writes without `--fix`, with one measured exception.** A plain run + modifies no repository content and no CommitLore state: `index.db` is + byte-identical after it, including under failure. `--fix` applies only + reversible local config and reports every change via `fixed: true` on the + row it fixed. + + The exception is SQLite's own bookkeeping. Opening a WAL database creates + or touches `index.db-shm`, and `--fix` creates `-wal` alongside it — for + readers as much as writers, and they hold no committed data. The first + revision of this section said "zero writes" without it, and writing the + §11 read-only test strictly is what found the wording false (#473). + Removing the exception would mean opening the index outside WAL for + doctor, which trades a documentation problem for the concurrency one #420 + was about. 3. **No claim it cannot evidence.** Every row carries the observation that produced it, `ok` included (§1.3.1) — the first revision required evidence only for non-ok rows, and the review showed `ok` with `{}` @@ -607,7 +618,7 @@ Every line is a command or a test that decides the answer. | release gate unchanged | `dist/commitlore.mjs doctor` on a fresh clone | exit 0, no `fail` (RELEASE-GATE §4 row still passes) | | no non-git network | full run with Node socket APIs stubbed to throw | all checks complete | | offline honesty | full run with every remote pointed at an unreachable host | run completes, exit 0; transport rows `warn` "could not verify" | -| read-only | full run without `--fix` under a watched fs | zero writes | +| read-only | full run without `--fix` under a watched fs | `index.db` byte-identical; nothing else changes but SQLite's `-shm`/`-wal` sidecars (§8.2) | | partial honesty | `doctor --only cli-runtime --json` | `selection` present; headline prefixed `1 of 15 checks run` | | summary invariant | property test over fixtures | counts sum to `total == checks.length`; per-check `durationMs` sums to ≤ `summary.durationMs` | | budget | timed run per §10.1 | `summary.durationMs` within the recorded budget |