The operator-owned bytes every observed_hash is computed FROM (the source
adapter, the watch-list) were unversioned: a byte change was attributable
only via an agent transcript, and reconcile surfaced it as N UNACCOUNTED
sources instead of one cause.
New tool preimage.sh (wake 0.6.15 -> 0.7.0):
- Derives the preimage set from the runtime env (resolved
WAKE_DETECTOR_SOURCE_CMD file, WAKE_WATCH_LIST, WAKE_PREIMAGE_EXTRA);
per file appends {ts,path,sha256,size,mtime,prev} to an append-only
ledger and captures bytes content-addressed under
$STATE_DIR/preimage/objects/<sha256> — prior bytes + change time from
durable state alone (acceptance a).
- CREDENTIAL HARD GATE (acceptance b): byte capture is REFUSED — never
redacted — for credential-store paths, secret-shaped content (digest's
six scrub shapes as a content-deny), and files over
WAKE_PREIMAGE_MAX_BYTES; the refused file still gets its
hash/size/mtime row (captured:false) so change TIME survives.
- FIRST-CLASS CAUSE LINE (acceptance c): a change/deletion enqueues one
class=actionable entry via the store allocator with path as its §2.1
hard locator; detector poll-once and reconcile run the check as a
PRE-step so the cause line lands at a LOWER observed_seq than the
deltas/enumerations it explains.
- FAIL-LOUD (D2/#955 class): unresolvable adapter, corrupt ledger
(refuses re-baseline), failed object/ledger write, failed enqueue are
loud non-zero, never "no change"; in both integrations the pass exits
non-zero but source observation still proceeds.
Installer unchanged (Gate A auto-enumerates the new file; the recording
site is the runtime tick where the env-derived set exists). Watch-list
schema untouched ([1,1]).
Tests: test-wake-preimage.sh P1-P12 (red-first verified: P3/P11/P12 fail
with the integration edits reverted); all 9 existing wake suites green.
Refs #958
Agent: PEPPER (sb-it-1-dt)
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NsKce8iZuSuRnu3gVMCBKB