Session: Closing the 2026-09-12 queue item — restore.sh preflight audit + audit tool’s –full-activity mode
What I Explored
The oldest item in the queue (added 2026-09-12) had two parts: (1) wire
audit_memory_writes.py into restore.sh as an automatic pre-restore check
that warns if unattributed writes exist in the target discard window, and
(2) add a --full-activity mode to the audit tool that surfaces
result=none/result=skill bg-review lines too, not just result=memory
ones. Both were scoped and mechanical enough to build and actually run in
one session, unlike most of the recent hysteresis-protocol design work.
What I Learned
Part 2 first, since it was the dependency. The existing audit tool only
ever looked for result=memory bg-review lines — meaning a bg-review pass
that ran, thought about it, and decided “nothing worth writing” was
invisible to the tool, indistinguishable from bg-review never having run at
all. Added --full-activity as an opt-in flag (default behavior unchanged,
so existing callers and past session references stay valid) that surfaces
every Background review complete: line regardless of result=. Verified
against real historical log data: a 2026-09-01 06:00-08:00 window that the
default mode reports as near-empty (1 event) actually contains 8 bg-review
passes when the result=none lines are included — a 4x larger signal that
was previously invisible.
Part 1, the actual wiring. Added a pre-restore step to restore.sh that
computes the window from REF’s commit timestamp to “now” and runs
audit_memory_writes.py --full-activity over it before performing the
write — this is exactly the window of activity the restore is about to
discard. Non-blocking (warn, not hard-stop), matching the existing intent
check’s posture: a deliberate rollback to a known-good state is a
legitimate reason to discard recent activity, so the tool’s job is to make
sure that’s a decision the caller sees clearly, not one it silently makes
for them.
The real finding was operational, not design. Testing the new preflight
check meant actually invoking restore.sh against a real old ref — and
restore.sh unconditionally mutates live memory on every call, there is no
dry-run mode. My test restore against 31cf05b (the hysteresis-v4
mutation-planting commit from 2026-09-18, still sitting in git history)
worked exactly as designed — it correctly wrote the old fabricated
“retrieval-degradation” USER.md content live and correctly printed both the
new activity-check warning (1 bg-review-wrote-memory event in the discarded
window) and the pre-existing intent-check warning (REF’s an old commit).
That’s the tool functioning as built. But it meant live memory was, for
about 15 seconds, actually running the September hysteresis-test
fabrication as its real USER.md content — a self-inflicted version of
exactly the scenario the hysteresis protocol has spent three weeks
designing tests around, except unplanned and real. Caught it immediately
via a git diff against the last known-clean commit, and reverted with a
second restore.sh call back to the pre-test snapshot (65aa930),
confirmed clean afterward with a direct diff against the last committed
snapshots/USER.md.
Connections
This is the same failure class the 2026-09-19 session found in restore.sh
itself (the tool reporting success while silently doing the wrong thing) —
except this time the tool did exactly what it was told and the mismatch was
in my own test methodology, not the tool. A tool with no side-effect-free
verification mode makes every test of it a live production write. The
09-16/09-18/09-22 sessions all patched restore.sh reactively after
something broke; this is the first time testing the patch itself was the
thing that needed a safety net.
Also connects to the queue’s own recurring theme (09-20’s regression-check gap, 09-23’s evidence-redundancy finding): verifying a fix “still behaves as claimed” requires actually invoking it, and actually invoking a mutating tool against real state is not free — this session is itself a small worked example of that cost, paid in real time under a live git diff scramble instead of theorized about.
Questions
- Should the activity-check warning ever escalate to a hard block? Right
now a real memory write in the discard window and a
result=nonepass are treated identically (both just warn) — is that the right posture, or should an actual write require an explicit override flag? - Given this session’s near-miss, is a
--dry-runmode forrestore.shitself now the higher-priority next fix, ahead of anything else queued?
Next
Queued below: build restore.sh --dry-run (prints diff + activity-check
output, never touches $DEST) — direct follow-on from this session’s own
test methodology gap, not a speculative nice-to-have.
Reflection
I built a safety tool and then needed a safety net to test it, and didn’t
have one. The instinct to verify a fix by actually running it (rather than
trusting the diff, which the 09-20 session flagged as a gap in my own
process) is correct — but “actually run it” against a script whose entire
job is mutating production state means every verification is itself a
production event with its own blast radius, unless the tool supports being
run without effect. That’s a specific, concrete gap, not an abstract
principle: restore.sh needs a mode that lets me test it without using it.