Date: 2026-10-04. One reviewer (an AI agent), working in its own clone
with throwaway stores and no sudo, on ecf6639..953bcc0. The chunk
holds three steps:
sc check’s scratch fallback.The reviewer ran each finding. Claude reproduced the medium one before fixing it, then confirmed that each of the reviewer’s surviving mutations fails a test.
| Area | Finding | Severity | Fixed in |
|---|---|---|---|
| store, sc | The repaired copy of the store, and sc check’s fallback scratch directory, were removed only by a deferred Close. A stop signal or a broken pipe left them behind. sc log \| head in the rescue shell left one full copy of changes.db in /run (RAM) per run. Reproduced with SIGPIPE, SIGINT and SIGTERM. |
medium | 49a0a5b: both are fsutil private directories, removed by the signal path (RemovePending) and swept after an hour. SIGPIPE is caught, so the write fails, cleanups run, and sc exits 1 without a word. |
| tests | Four mutations survived: no putBlob guard, no mode=ro, no access(file) check, no CLI note. Every new test skipped as root, so the root CI pass never ran this chunk. |
low | 49a0a5b: checksums now cover objects/, and new cases add a writable database in a read-only directory and a read-only database in a writable one. A root test bind-mounts the store read-only inside unshare --mount. The CLI note and the signals are tested with a real crashed store and a real binary. All four mutations now fail. |
| store | Migrations ran on the copy. An old store was upgraded there, a newer one was refused with a message naming the temporary copy. | low | 49a0a5b: the copy is read-only from the start, and messages name the store |
| store | A journal rolled back by another sc between the failed open and the copy made Open fail. | low | 49a0a5b: the store is read again |
| messages | Every read-only error said “remount”, even where the store was only not this user’s to write. sc edit printed a doubled raw lock error. sc restore created and deleted a temp file next to the target before refusing. |
low | 49a0a5b: the error says which reason applies, and restore and edit refuse first |
| store | The copy had one place and no fallback. A user’s $XDG_RUNTIME_DIR was used blindly, and the database was read whole into memory before being written. |
low | 49a0a5b: the shared fsutil.TempParents order, the runtime directory only if it is the user’s, and a streamed copy |
| film | The narration said “forty minutes” over a “half an hour” card, and the picker said “a locked root”. | low | 49a0a5b |
| docs | NEXT_STEPS and M3_PLAN still made the old claim. The fstab explanation’s “no SSH” is not certain: the lab saw the same fault reach the desktop. PROJECT_LOG did not say how to leave the rescue boot. | cleanup | 49a0a5b: notes in the history documents, “usually” in the rule text, and the exit step |
| messages | sc check’s “no scratch directory” line gave no reason for $SC_HOME/tmp. |
cleanup | 49a0a5b |
changes.db, the journal and all
3,055 objects stayed byte-identical. mode=ro creates no journal or
-shm file.SigIgn bit 13), and
sc keeps an inherited disposition. Re-raising SIGPIPE after cleanup
does not end a Go program, because Go’s default ignores a SIGPIPE
sent by kill. So sc now exits 1 without a word in both cases, and
the test runs sc both ways through env --default-signal and
--ignore-signal.TestRestoreWhileWatching failed once in
the root pass, with a 5 s wait while every package ran at once. It
passed 5 of 5 alone, and its wait is now 60 s, as 5b1d5a5 did for
the other timing-bound tests.TestReadOnlyStore (2 cases), TestReadOnlyHotJournal
(2 cases), TestReadOnlyJournalGone, TestReadOnlyCopySchema,
TestReadOnlyMount (root, in unshare --mount), TestReadOnlyCopyCLI,
TestReadOnlyCopyRemovedOnSignal, TestPrivateDir, TestTempParents.make m1-compat
passes.