Skip to content

sinks: _write_lock stops at the process boundary — say so where it is promised#13

Merged
Nik7A merged 1 commit into
mainfrom
sink-lock-honesty
Jul 17, 2026
Merged

sinks: _write_lock stops at the process boundary — say so where it is promised#13
Nik7A merged 1 commit into
mainfrom
sink-lock-honesty

Conversation

@Nik7A

@Nik7A Nik7A commented Jul 17, 2026

Copy link
Copy Markdown
Owner

_DailyFileState warns that interleaved appends corrupt the rolling hash, then reassures the caller:

Callers must not let two appends interleave — LocalFileSink guarantees that with _write_lock, which is why append_line does no locking of its own.

It is a threading.Lock (local_file.py:181). It guarantees nothing across processes. A caller reading the sink's own docstring to decide whether they need their own locking gets the wrong answer.

emit.py:75 states the truth in the same codebase — "What is NOT guaranteed: ... two processes appending to the same log" — so the library knows. It documented the limit accurately in one file and promised the opposite in another.

It already fired

Two bosun workers appending to one chain produced 7 forked chains across 5825 records (forensics, 2026-07-17). All 28 fork points sit at the one node whose LLM call blocks the writer — the only interleaving window.

Worth being precise about the harm: nothing was corrupted. 0 dangling prev_hash, 4927/4927 resolvable signatures verified. The chain branched. verify reported CHAIN_BREAK over evidence that was in fact intact — which is worse than a clean failure, because it teaches the operator to disregard the verifier.

What changes

Docstring only, plus a guard. The promise now names its boundary and points at the one piece of cross-process serialisation that does exist: the flock in the chiplog hook-record subprocess, which covers the Claude Code hook path and nothing else.

What this deliberately is not

Making appends actually cross-process safe. That is a real change to the write path — an OS lock around [read head → sign → append → publish manifest] — and it lands directly on top of the manifest's per-record rewrite, which is its own open question. Doing both at once would re-entangle two concerns in one file. This closes the misleading half; the lock is worth its own decision.

On the guard

The first draft passed against the lying docstring. The text says "previous process wrote to it today" further up, and a whole-docstring search for "process" found that instead of the claim. It now anchors to the paragraph that makes the promise — which is the only reason the false green surfaced at all.

Reported from the bosun migration, 2026-07-17.

… promised

_DailyFileState warns that interleaved appends corrupt the rolling hash, then
reassures the caller that "LocalFileSink guarantees that with _write_lock,
which is why append_line does no locking of its own". It is a threading.Lock.
It guarantees nothing across processes, and a caller reading that docstring to
decide whether they need their own locking gets the wrong answer.

emit.py already states the truth — "What is NOT guaranteed: ... two processes
appending to the same log" — so the library knows. It documented the limit
accurately in one file and promised the opposite in another.

Two bosun workers appending to one chain produced 7 forked chains across 5825
records. Worth being precise about the harm: nothing was corrupted. 0 dangling
prev_hash, 4927/4927 resolvable signatures verified. The chain branched, and
verify reported CHAIN_BREAK over intact evidence — which is worse than a clean
failure, because it teaches the operator to disregard the verifier.

The promise now names its boundary and points at the one piece of cross-process
serialisation that does exist (the flock in hook-record, Claude Code path only).

Not this commit: making appends actually cross-process safe. That is a real
change to the write path — an OS lock around [read head, sign, append, publish
manifest] — and it lands on top of the manifest's per-record rewrite, which is
its own open question. Doing both at once would re-entangle two concerns in one
file. This closes the misleading half.

The first draft of the guard passed against the lying docstring, because the
text says "previous process wrote to it today" elsewhere and a whole-docstring
search found that. It now anchors to the paragraph that makes the claim.
@Nik7A
Nik7A merged commit ea67956 into main Jul 17, 2026
1 check passed
@Nik7A
Nik7A deleted the sink-lock-honesty branch July 17, 2026 11:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant