Conversation
…hooks (danielmiessler#2079) defaultMode "auto" steers file writes to Bash, and ISASync, CheckpointPerISC, ConfigEvalFire and SystemChangeSurface are registered on Write/Edit/MultiEdit only, so an ISA written by heredoc never reaches work.json, the per-claim commit never fires, the eval suite never runs and the SYSTEM disclosure line stays silent. BashWriteRelay.hook.ts (PostToolUse, matcher Bash) finds files changed under a bounded set of watched roots since its last run for the session and replays the four hooks with a synthesized Write payload carrying file_path. mtime narrows the candidates; a content hash against a shared per-path claims ledger decides, so byte-identical rewrites and sibling sessions' writes are never attributed (first claimer wins, exactly once). Never parses the command. The first Bash call of a session only records a baseline; change sets over 40 files are logged and skipped; every failure path exits 0 with no output. Registered in hooks.json on the existing Bash matcher; documented in HookSystem.md. Verified on a live install: a Bash-only edit to a registered ISA moved its work.json progress and produced the SYSTEM line on the same call; a no-change scan costs 0.02 s wall; four concurrent sessions ran the claims ledger without double attribution. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KdVkxUPGxFm91bsNDxyi5M
|
Thanks for this; #2079 bites here too. I ran the 1.1.0 hook from this PR in a throwaway
Repro, one session, five Bash calls,
For an ISA written once by heredoc, which is the #2079 case, that one write is the one that's lost. The live check in the PR description passed, I'd guess, because that ISA was already in the ledger from an earlier run. One way out: on the baseline call, hash every file under the watched roots into the ledger. Then a later unknown path can only be a new file, and it can be claimed and relayed. The over-reporting fix stays intact, since pre-existing state is recorded before anyone edits it. Cost is one full hash pass per session; the ledger is shared, so later sessions mostly hit known rows. Small thing: the Environment: Linux (WSL2), Bun, Claude Code 2.1.278, LifeOS 7.40.4. Hook run standalone, not registered on a live install. |
|
I ran this PR against the case #2079 started with, and it still drops it. A brand-new ISA written by heredoc has no row in Clean state file, no prior claim row, So detection works ( I think the hash and the shared ledger are right. The problem is that "no prior row" covers two different things: a file that was already there before the ledger saw it (baseline it, fine), and a file that was created during this scan window (that's a change, and it's the whole point of the issue). Every candidate already passed if (!prior) {
let bornInWindow = false;
try { bornInWindow = statSync(p).birthtimeMs > sinceMs; } catch { /* keep false */ }
claims[p] = { hash: h, at: Date.now(), session: sessionId };
if (bornInWindow) mine.push(p);
continue;
}
Pre-existing files still don't get pinned on whoever runs first. If a filesystem doesn't record birthtime, the catch leaves it false and you get today's behavior, not extra noise. Two smaller things from my install, which has drifted from the shipped tree:
|
Fixes #2079.
The problem
permissions.defaultMode: "auto"tells the model to prefer Bash for file writes, and ISASync, CheckpointPerISC, ConfigEvalFire and SystemChangeSurface are registered on Write/Edit/MultiEdit only. A file written by heredoc or a script therefore fires none of them: an ISA never reaches work.json, the per-claim commit never runs, the eval suite never fires, and the SYSTEM disclosure line stays silent. Reproduced on a live install exactly as the issue describes.The change
One new hook and one registration line; the four existing hooks are untouched.
hooks/BashWriteRelay.hook.ts(PostToolUse, matcherBash):file_path, and returns theiradditionalContextconcatenatedRegistered in
hooks/hooks.jsonon the existing Bash matcher. Documented inHookSystem.md.Verification
bun build --no-bundle --target=bunpasses.Known limit
A brand-new project ISA outside MEMORY/WORK written by Bash is invisible until it is first touched by Write or registered; MEMORY/WORK ISAs and already-registered paths are covered.
🤖 Generated with Claude Code
https://claude.ai/code/session_01KdVkxUPGxFm91bsNDxyi5M