Skip to content

v0.10.3

Choose a tag to compare

@wdhwg001 wdhwg001 released this 04 Sep 03:58
· 35 commits to main since this release

A patch release built around one question: for each Claude Code behavior csift depends on, how completely has that behavior been attributed? The introspection ledger now answers it claim by claim, with the producing code traced in the shipped binary and re-read by an independent verifier, the README carries the tally as a table the gate regenerates, and the five defects the tracing found in csift are fixed.

What the tracing found in csift

The freeform AskUserQuestion answer. Claude Code 2.1.258 synthesizes the result of an AskUserQuestion from five branches. When the answerer writes the freeform response field instead of choosing an option, the record carries an empty answers map and the text The user responded: <text>. csift required a non-empty answers map and knew no such prefix, so that record classified as a plain tool result and opened no turn. A present, non-blank response is now a second structured signal beside answers. The AUQ unit renders the questions asked and a response: line. The TUI dialog never writes response (a typed "Other" lands in answers, and "Chat about this" is a rejection). The answerer that writes it is recorded in the ledger as an open leg, not as a guess.

A blocked background task. Claude Code's remote-agent notifier writes a fifth terminal status, blocked. csift mapped every status outside failed, killed and stopped to completed, so a blocked agent, or any value a future build adds, was booked as a clean completion. status and wait now count blocked and N with an unknown status as their own buckets, in text and in JSON.

A notification in a child lane. wait --until notification watched the main transcript only, on the belief that a pulse never lands in a child lane. csift's own classifier counts 2906 delivered pulse records across all lanes against 2904 in top-level transcripts: a pulse addressed to the owning agent lands in that agent's lane. The condition now fires in every watched lane.

A read cut by its token budget. The Read tool marks a read it cut at its token budget with truncatedByTokenCap. On a file whose lines are too long to paginate the harness recounts numLines from the cut slice, so it can equal totalLines, and csift's full-read test replayed truncated content as the whole file. A flagged read is never a full snapshot now. Its whole lines still anchor as a partial read.

An image in a queued prompt. A prompt queued and then edited or recalled before dispatch never becomes a user record. Its pasted images survive only in the queued_command attachment. csift image read user records and tool results only, so 45 of 52 such images in the reference corpus were invisible. The attachment is the third carrier the walker reads.

Attribution in the ledger

Every claim carries two legs. The producer leg records whether the producing code was traced in the shipped binary. A complete trace is three hops quoted verbatim at byte offsets: the trigger, the gate that selects the fact, and the writer or template, each excerpt re-read within 400 bytes of its offset by an independent verifier whose batch carried a planted fake. A partial trace found a template or field without its trigger and gate, and none means nothing was traced. The specimen leg records whether the behavior was observed on disk or in a live trial. The attribution follows from the pair. A claim that is not end-to-end lists the instrument that would close each open leg, and an end-to-end claim carries none.

Three rules kept the round honest. A negative such as "nothing else writes this" closes only by an enumeration of every site in the binary, each read and listed. A claim whose text a traced hop refuted was rewritten by a scribe and re-read against the chain, never annotated around. Version floors were checked against historical native builds fetched by version, bisected on string literals: the file-history delta line dates to 2.1.208, the five-way AskUserQuestion synthesis to 2.1.216, the isMeta-less compaction boundary to the engine route that shipped in 2.1.193.

The tally at this release (the same table the README carries):

attribution claims share meaning
end-to-end 382 73.2% the writer, its gate and its trigger read in the shipped binary, and a specimen observed on disk or live
of which chain traced and adversarially re-read 382 73.2% the three hops quoted at byte offsets in producer_chain, every excerpt re-read by an independent verifier
of which audit-graded, chain not yet traced 0 0.0% graded end-to-end from the release-audit checks (writer offsets cited there) before the three-hop tracing existed, the next audit traces them
specimen-only 105 20.1% observed on disk or live, the writer not traced (or traced only in part) (92 of them with a partly traced writer)
producer-only 33 6.3% the writer traced in full, no specimen exists in the corpus or could be produced here
partial-producer 2 0.4% a template or field located without its gate and trigger, no specimen
by-elimination 0 0.0% neither leg, attributed by exclusion or from csift's own design
total 522 100.0% one claim per Claude Code behavior csift depends on, verified at Claude Code 2.1.258

Every end-to-end claim carries its chain: the three hops at byte offsets in producer_chain, a negative's enumeration of every site, and a residue list for the notes that are not gaps. A claim below end-to-end names, in open_legs, the instrument that would close it: fourteen of them cannot be closed on this host at all (a Windows result, a remote agent reaching blocked, an MCP elicitation, a held permission prompt, an armed local garbage collection) and say so.

The gate derives the attribution from the legs and refuses a disagreement, refuses a holds verdict on a by-elimination claim, refuses an end-to-end claim with an open leg, and requires the README table to equal the ledger's counts, so the table is regenerated, never typed.

Verification

The test suite runs 1040 unit tests and 548 end-to-end tests on every commit through the pre-commit gate, which also runs the ledger gate by name. Line coverage measured 95.78 percent (888 of 21048 lines missed), above the 0.10.2 baseline of 95.70. A scoped mutation run over the six files the fixes touched tested 306 mutants: 261 caught, 24 killed by timeout, 12 unviable, 9 survived, and every one of the 9 sits in a previously classified equivalent zone (the base64 decoder's bit-or, the marker parser's guard, the condition's perf widening, the render's mtime and lane co-variance, the adaptive poll cadence). Every mutant in the new code was killed. The crate-wide mutation badge stays at the 0.10.1 census.

The ledger gate holds eight rules on the 522 claims, and the release audit for this version was the tracing itself: three rounds of tracer and verifier fleets, each verify batch qualified by a planted fake that every verifier caught, followed by three scribe passes for the refuted texts (174 rewrites accepted, 55 rejected, each rejection leaving its claim below end-to-end). Two live trials on Claude Code 2.1.259 back two claims: a persistent Monitor ran 150 minutes without a completion record, and a /rewind restore left the transcript byte-identical, the resubmitted draft appending after it.

Eight targets were built at the tag and ran the full suite on their own platform. The four Linux lanes (glibc and musl, x86_64 and arm64) ran in the official rust:1.89 containers, 1040 unit and 548 end-to-end tests each. The two Windows lanes (arm64 native, x64 emulated) ran on a Windows 11 ARM64 guest, 1040 and 547, the one missing test being the unix-only pid probe. The two macOS binaries were built with path remapping and smoke-tested. Every artifact was audited for machine-path strings and the Windows executables for a dynamic C runtime, all clean. The packaged documentation is byte-equal to the tag.