Skip to content

v0.10.1

Choose a tag to compare

@wdhwg001 wdhwg001 released this 03 Sep 00:23
· 58 commits to main since this release

The 0.10.0 release matrix ran the Windows test suite green, but the suite never exercised process liveness there, because the pid probe was compiled out on Windows. This release closes that gap the only honest way, by running a real Claude Code 2.1.258 session on a Windows 11 ARM64 machine and pointing csift at it: a Sonnet 5 session that built a Next.js todo app through four subagents and left the dev server running as a background task. Everything below was measured on that session or on the Claude Code binary.

status and wait: the registry's shell status was misread

The harness's session registry has a closed status set: busy, shell, idle and waiting. csift 0.9.0 through 0.10.0 treated shell as a running shape. The binary tells a different story. It computes idle and then relabels it shell while a background shell task is open, so shell means exactly the seventh verdict's situation, an ended turn with a dev server still up. On the Windows session that mistake produced running where idle-background-open was true, and wait --until stop could not fire even when the lens ignored the dev server. busy is now the only registry running signal, shell reads as the idle-with-background-shell shape it is, and the note says whether the background section lists the shell or the lens excluded it.

status and wait: Windows gets a real pid probe

A Windows registry row renders procStart as a FILETIME tick count rather than the asctime string unix writes, so the old parser could not read it and would have skipped the reuse guard silently even if a probe had existed. The probe now reads the owner's start time through PowerShell's Get-Process, falls back to tasklist for liveness alone, and compares instants with the same two-second tolerance as unix. A row whose pidDomain names another domain is never probed, and the verdict says so. Verified against the live session with the start-time guard matched, and after a forced kill of the Claude Code process with a stale-dead verdict on both platforms.

waiting on a human: two more instruments

The registry's waiting status is set by the harness for any blocking dialog, which includes permission prompts, plan approvals and sandbox or worker requests. csift now reads it as waiting-hitl, and the idle-verdict honesty note names the status the row carried instead of calling every permission prompt invisible. The second instrument came from a measurement that overturned an old law: Claude Code 2.1.258 writes a multi-question AskUserQuestion to the transcript at question time, while a single-question one still stays buffered until it is answered. Three single-question trials and two multi-question trials, on macOS and Windows, agreed. An unreturned AskUserQuestion or ExitPlanMode at the main tail is therefore waiting-hitl without the sidecar. The sidecar remains the only instrument for the single-question shape.

child lanes settle when the harness says so

A subagent that finished seconds ago still carries a fresh tail without an end_turn, so the recency rule counted it as live for up to five minutes. A lane whose completion notification already landed in the main transcript is now settled regardless of its tail.

the introspection ledger

csift depends on hundreds of small facts about what Claude Code writes, and those facts drift. This release adds INTROSPECTION.json, a ledger with one entry per claim: the behavior, what csift does with it, the code site with a verbatim snippet, how to re-verify it from scratch, the version it was first pinned against, and a check record per release audit carrying the instrument that ran, what it observed and the counting rule. The ledger was excavated from the specification, the operating manual, the code comments and csift's own development sessions, then every claim was re-verified against the current binary and corpus by a separate agent. A pre-commit gate ties the README's "verified against Claude Code" badge to it. The badge version is admitted only when every claim carries a check at that version, check evidence must be claim-specific, and every cited snippet must still exist in its file, so a refactor that moves code fails the gate instead of orphaning the claim.

The first audit already paid for itself. A verifier reading the binary's settings resolver found that plansDirectory is resolved against the project root through the merged settings scopes, with a containment check that refuses an escaping value, while csift's slug-only plan binding joined a relative value to the config home. csift plan now follows the harness rule, with a test for the project join, the project-local override and the escaping fallback.

A second verifier explained a number that had puzzled an earlier round: forked lanes reporting depth 65. A /fork child's transcript is a clone of its parent's, so it carries the spawning tool call itself, and csift's spawn join made every forked lane its own parent until the depth walk hit its cycle cap. csift now reads the parentAgentId the harness writes into the child's meta file and never accepts a node as its own parent. Two smaller corrections came from the same pass: the parent's record of a subagent return carries an appended continuation footer rather than a truncation, and recover's Bash read anchors already reach built-in and teammate lanes, since only workflow lanes lack the result echo.

The audit's largest correctness catch was silent. Claude Code relays a peer message under three preambles, and csift recognised only the first, so an inbound message relayed while the session was mid-turn carried no label at all: 29 of the 47 peer messages in the reference corpus were invisible to every census and selector. All three preambles are boundaries now, and the corpus-wide inbox count moves from 8721 to 8750. Two smaller ones ride along: the third phrasing Claude Code uses to write an AskUserQuestion answer is recognised as an answer, and the registry reader accepts the procStartFt key the harness now carries beside procStart.

search: the 34th label

The harness writes a handful of type:"system" records for its own screen that never reach the model, and csift had no name for them. One appeared during this release when an account switch in another session disconnected Remote Control: a system record with subtype informational, level warning, and the notice as its content. harness.meta.system now covers that whole family, including api_error, the model-refusal fallbacks, agents_killed, local_command and scheduled_task_fire, and whatever a later build adds, rendered as [<subtype> <level>] <content>. It is gated like the other promoted leaves, so a bare scan never pays for it, and show --line renders it without --raw. The claim behind it names the record shape and the counting rule in the ledger.

README

Highlight 8 is laid out as short lines. Two badges join the header: the Claude Code version the ledger was verified against, and the crate-wide mutation score from a fresh census.

Verification

The suite at the release commit is 1036 unit tests and 540 end-to-end tests, green on all eight targets of the release matrix (539 on the two Windows targets, where one unix-only process probe is compiled out). Line coverage is 95.68 percent, up from 95.58 at 0.10.0.

The mutation badge comes from a fresh census of the whole crate with cargo-mutants: 5858 mutants, of which 215 could not be built. Of the 5643 viable ones the suite caught 4647 outright, 498 hung the suite and were killed by the 30 second timeout, and 498 survived. The badge counts a hang as a kill, which gives 91.2 percent. The caught-only floor is 82.4 percent and the timeout share is 8.8 percent. The census ran under a heavy machine load, so every timed-out and surviving mutant was queued for a second pass at a 45 second timeout on a quiet machine. The first 131 of that pass, 47 timeouts and 84 survivors, reproduced the census verdict in every case (the timeouts are loop-counter mutants such as i *= 1), and the pass was stopped there as evidence enough. The survivors in the code this release touched were read one by one. Four new pins landed: a literal per-platform pin for the pid domain, whose old test had asserted the function against itself, the returned-set rule through the whole status join, the shell note's absence on a busy row, and a two-agent end-to-end run where one completion pulse has landed and the other has not. Reading them also removed a duplicated background scan that the status join ran twice. The rest are the documented equivalent classes: Windows-only probe arms that do not compile on the census host, arithmetic in loop guards that only widens a prefilter, and comparisons on values the domain never produces.

The introspection ledger holds 521 claims. Every claim carries a check at Claude Code 2.1.258 with the instrument that ran, what it observed and the counting rule. Of those, 153 held as written, 344 were refined, 19 had drifted (all fixed in this release or recorded as ledger corrections), and 5 could not be verified on this host. The pre-commit gate passed on every commit of the release.

The Windows verification is the session described at the top: Claude Code 2.1.258 on Windows 11 ARM64, Sonnet 5, four subagents, a dev server open as a background task. Against it, status reported idle-background-open with the process start-time guard matched, --ignore-background npm turned that into idle-eot, wait --until stop fired in under a second under that lens and timed out with exit code 124 without it, and a forced kill of the Claude Code process produced stale-dead. The same kill on macOS produced stale-dead under SIGKILL and an honest idle-eot with no registry row under SIGHUP, where Claude Code deletes its own row.