Answers the NOT CLEAR verdict on #964 (B2 cases C+D, B11), new commit per
the re-verdict terms.
- B2-D (polarity): extras are RECORD-ONLY by default; byte capture for an
extra requires WAKE_PREIMAGE_CAPTURE opt-in. Core set (adapter,
watch-list) stays capture-eligible. Case D is safe by polarity alone —
verified with the content shape list stubbed to always-allow.
- B2-C (both forms): path deny evaluates raw AND realpath-resolved
candidate forms against unresolved AND resolved mosaic-home anchors;
deny runs first in the gate chain, so an allowlisted symlink cannot
smuggle a denied target.
- Content deny is defense-in-depth on the opt-in path only: six scrub
shapes + named-assignment probe; probe errors fail TOWARD refusal
(grep rc>=2 is a deny, not a fall-through).
- B11: absent/empty ledger over non-empty objects/ is a loud non-zero
refusal to re-baseline — that state cannot be a first install.
- Suite: P2 moved to the core adapter; P4/P5/P10 exercise the opt-in
path; new needles P13-P17 mirror every verdict probe (symlinked store,
outside-store copy, live secret no-opt-in/opt-in, record-only
tracking, ledger deletion, allowlist-symlink both halves). Red-first:
pre-fix code fails exactly P13/P14/P15/P16 (14 assertions); fixed
17/17. P17's deny half is green pre-fix (basename rule) — kept as a
guard needle, disclosed in the PR body.
All 10 wake suites green.
Written-by: pepper (sb-it-1-dt)
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NsKce8iZuSuRnu3gVMCBKB
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
Written-by: pepper (sb-it-1-dt)