Reference build ledger¶
Every claustrum release tracks one specific reference claude-ssh daemon build.
A git SHA identifies the build. Upstream tracking
describes how to find and diff a new build. This page is the running history of
those builds. It records what each build changed on the wire. The reconciliation
trail therefore stays in one place, and not in many commit messages.
scripts/UPSTREAM_SHA
holds the SHA of the build that is pinned now. This ledger gives the reasons
behind each bump.
Builds¶
Newest first, by lineage. 3ef9370e… is a rebuild on top of 4534d86…, so it
sits above it. Its build date (2026-09-03) is earlier than the date 4534d86…
was observed (2026-09-04). A "wire change" is a change to the JSON-RPC
surface that claustrum must match byte-for-byte. A pure rebuild with no wire
change also gets a row. This lets a reader tell a re-published SHA from a real
release.
| Reference SHA | Built (UTC) | Wire changes | Reconciled in |
|---|---|---|---|
89cb6289… |
2026-09-28 (built) | one new method, one new process.spawn param, two new error codes, new -install and -probe-cli output, three new server.capabilities features, the branchKept member and new git.* texts. See below |
PRs 445–455 |
f6010b97… |
2026-09-24 (observed) | several frame changes in git.*, one new process.spawn param and one new server.capabilities feature. See below |
PRs 410–427 |
90fca6e6… |
2026-09-14 (built) | no surface change. claustrum made 7 changes, 3 of them client-visible and 1 of those on a frame. See below | PRs 387–392 |
19f30c46… |
2026-09-11 (observed) | 2 changes + 4 off-wire subsystems + a new CLI mode. See below | PRs 356–371, and the ldd bound under issue 408 |
3ef9370e… |
2026-09-03 (built) | none (off-wire: linux libc probe reordered ldd-first) | PR 345 |
4534d86… |
2026-09-04 (observed) | 3 changes + off-wire lifecycle layer | PRs 314–333, and the sweep age gate under issue 408 |
7d193f89… |
2026-08-25 | 6 changes + off-wire git rewrite. See below | PR 286, and the -cli-zst checksum check under issue 408 |
5db5e4a1… |
2026-07-06 | none (off-wire: daemon.token persistence) |
PR 131 |
7c2f88d1… |
2026-07-02 | 5 changes. See below | PR 120 |
d20a77da… |
2026-06-09 | none (pure rebuild) | PR 97 (pin bump only) |
7cbfa471… |
2026-06-04 | git.info gained root (+ off-wire churn, described below) |
PR 60 |
8de85faa… |
2026-05-21 | baseline (initial clean-room target) | initial implementation |
Each per-build section has three parts. The wire delta is what claustrum must match byte-for-byte. Off-wire churn is any source that moved but never reaches the JSON-RPC surface. How it was bounded gives the measurement that showed that nothing else changed.
89cb6289d0e434f573cfc7267dd0cbb8c56ca298 — 2026-09-28 (built)¶
Pinned by Claude Desktop 2.16120.0 for Windows and macOS. Its -version prints
claude-ssh 89cb6289d0e434f573cfc7267dd0cbb8c56ca298 (built 2026-09-28T17:40:15Z).
Issue 442 tracked the reconciliation. The build carries a go1.25.14 stamp
(go version on the binary), the same as f6010b97.
Wire delta.
- A managed launcher.
launcher.resolveis a new method,process.spawngains thelauncherparam, andserver.capabilitiesgains thelauncher.managedfeature, with two new error codes. WithCLAUDE_SSH_MANAGED_LAUNCHER=1,-installand-probe-clirun the CLI through the launcher.-installgains launcher fields, and-probe-cligains the__CLI_LAUNCHER__output (PR 448). git.worktree_removeand the create rollbacks delete a branch only when another local branch or a remote-tracking ref reaches its tip. Otherwise they keep it and add"branchKept":true.server.capabilitiesgains thegit.worktree_remove.unpushedGuardfeature (PR 446).- The configuration listing is
config -z --list, with a new key-length limit and its text. A straycommondirgets new texts. The listing runs underLC_ALL=CandLANGUAGE=C, so a listing error is in English under a German daemon locale (row L03, PR 450). - A failed listing is answered by its cause.
server.capabilitiesgains thegit.info.discovered_rootfeature. On Linux and macOS,git.infotakes its root withoutrev-parse --show-toplevel(PR 450).
Off-wire churn. Every spawned child loses the two launcher variables
(PR 448). The reap of a child record reads its program key, which f6010b97
does not read (PR 453).
Older gaps closed in the same work. Some fixes are for behavior that
f6010b97 shares with this build. That is all of PR 445, most of PR 447, and
parts of PRs 446, 450, 451, 453, 454 and 455.
PR 445 refuses a worktreeRoot that leads into a checkout of the repository.
Before it, git.worktree_remove with such a root deleted the worktree, its
uncommitted files and its branch. PR 451 stops the direct --version run of
-install, so D11 is retired.
How it was bounded. The slices were measured side by side on Linux, macOS
and Windows VMs. A whole-build check of main 4495db6 against this build then
ran on all three systems. The frame battery was byte-equal on each, apart from
the fields that change per run and the D16 frame on Windows. The D19 junction
rows are not part of the battery. The check
found no new frame difference that a slice had not taken. Issue 429 lists its
other differences. D20, D21, D22, D23 and D24 are new in this work, and D11 is
retired. D2 gained its -install refusal of a home folder (PR 451).
f6010b978a0b0f4ca0dcb7dadda9cc4271a608a1 — 2026-09-24 (observed)¶
Pinned by Claude Desktop 2.9939.2 for Windows and macOS. Linux Desktop 2.7032.0
still pinned 90fca6e6 that day. Issue 408 tracked the reconciliation. The build
carries a go1.25.14 stamp (go version on the binary), the same as 90fca6e6.
Wire delta.
process.spawnpasses the login shell'sSSH_AUTH_SOCKon Linux and macOS when the child env has none. It gains thedisableShellAgentSocketparam, andserver.capabilitiesgains theprocess.spawn.shellAgentSocketfeature (PR 410).- Every
git.*method checks the git directory before git runs and refuses one that is not laid out as git writes it (PR 424). git.worktree_createpasses git the full start commit id. It picksorigin/<sourceBranch>in more cases, such as after a local.claudeor.mcp.jsonchange (PR 419).git.worktree_removeanswers a new reason text withworktreeRoot(PR 424).
Off-wire churn. The .worktreeinclude directory scan (PRs 420, 426) and the
hardened git call shape (PR 425).
Older gaps closed in the same work. PRs 411, 416, 417 and 427, and parts of
PR 419, fix behavior that older builds already had. PR 411 is the
git.worktree_remove refusal of a baseRepo with no repository, which stops a
recursive delete. The rows above name those builds.
How it was bounded. The slices were measured side by side on Linux, macOS
and Windows VMs. A whole-build re-check of main against this build then ran on
all three OSes. It found no new frame difference. It found argv and log
leftovers (PR 426), older -install gaps (PR 427) and a stale D9 example. For
git.status {"baseRepo":[1,2]} both binaries answered the same frame,
{"code":-32602,"message":"Invalid params"}, on Linux, macOS and Windows. D16
is still needed, and its Windows cause is now known. D1, D7 and D14 are
retired, and D18 is new. A later pass matched git.worktree_remove to this build
and closed most of its older gaps. D19, the Windows junction refusal, is new with it.
Another pass matched the git.worktree_create directory modes, parent-step error
texts and checkout refusal for a worktree location to this build on Linux and macOS.
90fca6e6a55c4d4c659e8c6ed511b7969ab17315 — 2026-09-14 (built)¶
Pinned by Claude Desktop for Linux 2.110.0. A small build on top of 19f30c46,
built with the same Go toolchain. It adds nothing to the JSON-RPC surface: no
method, no field, no new error string. The server.capabilities method list and
feature list are unchanged, and the static drift check passes against this build
with no change to its canon. The frame battery, run on the reattach slice, showed
no divergence beyond instanceId and startedAt. Those are per-boot values that
cannot match between two daemons. The slices that landed after it move no frame.
Recorded here anyway, because "the drift check was quiet" is exactly the answer a future triager must not take for "nothing changed". claustrum made seven changes for this build. Items 1, 3 and 4 are measured.
Wire delta. Exactly one item changes the bytes of a frame: item 3, and claustrum had to change its own frames to stay byte-identical. Items 1 and 4 are observable off the frame instead. They show in the connection lifecycle and in the seeded worktree, which is precisely what a frame diff cannot catch.
The seven.
- A reattach closes the connection it replaces.
process.reattachalready transferred the frame stream to the reattaching connection. It now also closes the connection it took the process from. Before, that connection stayed open and never carried another frame for that process, while still answeringserver.ping. That was measured on19f30c46. This is the build's most client-visible change. It is consistent with the Claude Desktop changelog note about messages around a disconnect, which is a correlation, not something this reconciliation established. - claustrum's idle close shares the deliberate-close flag with the supersede, so a superseded connection is not closed and logged a second time. Not probe-measured.
- A reaped process is not running. Inside the bounded exit drain a reattach
answers
running:falseand a fresh-bytes stdin write is refused. - A new worktree no longer inherits Claude runtime state. Nine names under
.claude/are skipped by both seeding passes, matched as whole path components and case-insensitively. - The host cleaner's busy sampler. claustrum now samples for a 3-second window with a two-sample minimum. These are its own values, not probe-measured.
- claustrum's linux orphan reap now treats a
/procprocess whosevsizeis 0 as gone, beside the state letter it already read. claustrum changedchildreap_linux.goand deliberately lefthostclean_linux.go's reader alone. Not probe-measured. - The darwin host cleaner's
lsofrun. claustrum now gives a run 15 s and gives up on a wedged one at 17 s. These are its own values, not probe-measured. This is the one a full re-check found after the first four slices had merged.
How it was bounded. Items 1, 3 and 4 were measured on VMs. Items 2, 5, 6 and 7 are not probe-measured. For 5, 6 and 7 the callers sit behind a 5-minute process age and a 30-day idle age, which makes staging them expensive. The code for each states that its values are claustrum's own.
Item 7 escaped the first pass. A second, full re-check after the first four PRs had merged is what found it.
Reconciled in. PRs 387 through 390 are the four implementation slices. PR 391
corrects claims those four left wrong. PR 392 adds item 7, puts the host cleaner's
listener check first, and carries the one deliberate exception in this build's
reconciliation. On the macOS busy probe claustrum reads an lsof run it gave up on
as busy. The reference side is not probe-measured (DIVERGENCES.md D17).
This bump follows all six.
19f30c46353dde1606cad1fede73d0e9be222140 — 2026-09-11 (observed)¶
Pinned by Claude Desktop for Linux 1.52386.0. The upstream build date is not
published. The date above is the date of capture and pinning. A large
build on top of 3ef9370. This build has two wire changes, both matched
byte-for-byte, plus four off-wire subsystems, one new off-wire CLI mode, and a
startup file-limit raise.
Missed at first. This build also bounds the ldd libc probe at 5 s. That
change was reconciled later, under issue 408.
Wire delta.
plugins.pruneadded. The method count goes from 18 to 19. This is a new method in a newpluginsnamespace. It prunes cached CLI plugin directories under the plugin root and reports what it removed.server.capabilitieslists it inmethods. The page plugins.prune holds the frames.git.worktree_creategainsexistingBranch. A caller passesexistingBranch:"<branch>", naming an existing local branch, to reuse it rather than create one. The result gains abranchfield, andserver.capabilitiesgains the matching feature. An absent or empty value keeps the create-a-branch behavior, which is parity.
Off-wire. These source changes move no client-visible frame. Four are subsystems. One is a CLI mode. One raises the inherited file limit. A closing note covers windows.
-probe-cliCLI mode. A one-shot flag runs a bounded<cli> --versionprobe and exits 0. For a CLI that runs it prints nothing. For one that times out it prints__CLI_HUNG__. For one that is missing or does not run it prints__CLI_BAD__. Claude Desktop drives it out of band to classify a CLI binary.- Exec-child trampoline. The daemon re-execs itself to
stamp a spawned child with
CLAUDE_SSH_RUN_DIRand aCLAUDE_SSH_CHILDidentity. Measured under a run-shaped socket. Other shapes are not measured on this build.f6010b97and89cb6289do it on every shape. Linux and darwin only. - Orphan-child record. The daemon records each spawned child to
<runDir>/children/<pid>.json, written atomically. Linux and darwin only. - Orphan reap. At startup the daemon reaps a child that a since-exited daemon of this run dir left behind. It first makes sure that the live process is that child. Linux and darwin only.
- Host cleaner. A periodic sweep ends orphaned Claude Code process groups under this install's roots. It also retires abandoned daemons and tidies stale run dirs. Linux and darwin only.
- Inherited file limit. At serve startup, claustrum sets its soft RLIMIT_NOFILE to min(hard, 65536), so a process.spawn child inherits that limit when the raise succeeds. A child inherited 65536 in the reference measurement. Linux and darwin only (windows has no RLIMIT_NOFILE).
- Windows. The exec-child, record, reap, and cleaner subsystems are inert on windows. Windows ships no run-dir lock, so the daemon is never the run-dir lock holder there. It records no children, reaps nothing, and stamps no child markers. A windows VM showed this. A windows VM showed again that D16 (git.status of a linked worktree) persists on this build.
How it was bounded. The static drift check passes for 19f30c46. The 19 methods,
the CLI flags, the -version format, and the tracked strings all match. The new
-probe-cli flag appears in both binaries. The two wire changes went through the
frame battery. Claustrum reconciled each off-wire subsystem 1:1. A throwaway VM
checked the destructive paths on linux, darwin, and windows. The forensics stay
outside the committed tree.
Reconciled in. PRs 356 through 371, with later follow-up parity fixes (the plugins.prune sibling-daemon classification and the inherited file-limit raise).
3ef9370ec5b07a0e728ca5de4137d450e95eb2b6 — 2026-09-03¶
Observed in Claude Desktop for Linux 1.49585.0. A near-identical rebuild on top
of 4534d86. No wire change: the JSON-RPC surface, the 18 methods, the CLI flags
and the -version format are byte-identical. One off-wire change, linux only.
Wire delta. None.
Off-wire. The -install libc probe (linux only) was reordered.
Build 4534d86 and earlier consulted the musl loader glob (/lib/ld-musl-*.so.*)
first and ran ldd --version only on a miss. Build 3ef9370 runs ldd on every
call and lets its output decide. A "musl" banner reports musl. Any other output
reports glibc. The loader glob is consulted only after ldd produced no
output. The exit code is not consulted. This value is off the JSON-RPC wire, and it
appears only in the __INSTALL_RESULT__ line. Claustrum still matches it, because
the driver uses libc to choose which CLI build to download. See
DIVERGENCES.md D14 (now retired) and install.go classifyLibc.
How it was bounded. The static drift check passed. A function-inventory diff
across all six platforms found exactly one changed function, the linux libc
probe. The recovered function inventory of darwin and windows is unchanged. Their
binaries differ only by ordinary rebuild churn. String constants, -help,
-install -help and the -version format are unchanged. The reorder was measured
on both reference binaries on a mixed host (glibc ldd plus a musl marker):
4534d86 reports musl, 3ef9370 reports glibc. The forensics stay outside the
committed tree.
4534d8648b686881955c6f13baf46ae72ee72f4c — 2026-09-04 (observed)¶
Observed in Claude Desktop for Linux 1.46388.2. The upstream build date is not
published. The date above is the date of capture and pinning. A
lifecycle-focused build on top of 7d193f89. Three wire changes, all matched
byte-for-byte, plus a large off-wire daemon-lifecycle layer and one new documented
divergence (D16). The RPC method set is unchanged at 18.
Missed at first. This build also added the 10-minute age gate to the install temp sweep. That change was reconciled later, under issue 408.
Wire delta.
server.capabilitiesgains two fields and two features. The result addsinstanceId(32 hex characters, per boot) andstartedAt(Unix milliseconds) betweenmethodsandfeatures.featuresgainsgit.worktree_create.timeoutMs(at index 2 on every OS) andserver.instance_id(last on every OS).git.worktree.external_rootis still dropped on Windows only.- The process exit frame gains
signalandkilledByon the kill path. A process that a client killed now reports the terminatingsignalandkilledBy:"client". claustrum sendskilledBy:"shutdown"for a process the shutdown sweep killed. Theshutdownvalue is not probe-measured. Thesignalis omitted on Windows, which has no SIGTERM machinery. A normal exit is unchanged. git.worktree_creategains a callertimeoutMs. An integer millisecond deadline on the add and checkout. Absent or 0 means no deadline, which is parity. On fire it returnserrorCode:"timeout". It is create-only.
git.status also gained --attr-source=<empty-tree> in this cycle, so the repo's
in-repo .gitattributes no longer runs a clean filter during status. The first
change line's leading space was reconciled here too. 5db5e4a dropped that space,
and 7d193f89 and 4534d86 keep it. Claustrum had carried the stale 5db5e4a trim.
New divergence D16. On Windows the reference's own git.status of a linked worktree
errors -32603 "exit status 128" (measured). Claustrum reproduces the same
temp-gitdir assembly and returns the status. The Windows failure mechanism was not
pinned in this cycle. A later measurement pinned it. See D16. The behavior is byte-identical on Linux and macOS. On
Windows it is a reachable divergence, with claustrum more correct. See
DIVERGENCES.md D16.
Off-wire. A daemon-lifecycle layer that does not move a client-visible frame. It
holds -install download progress plus a 60-second read-idle abort. It also holds a
run-dir lock with an owner record, an orphan-exit self-probe, and session supersede.
It bounds the git.worktree_create post-checkout drain. The macOS run-dir holder
check is the always-on divergence D15.
How it was bounded. Full frame captures against the new binary, plus VM
measurements on Windows and macOS. The three-OS osparity sweep
(scratch/osparity/results/*-4534d86.json) ran as well. Linux and macOS are
byte-identical between claustrum and the reference. Windows is byte-identical apart from two things. One is
the documented D16 divergence (git.status of a linked worktree). The other is the
shared Windows worktree-timeout timing race, which the reference exhibits too.
Reconciled in. PRs 314–333.
7d193f89fc02cf1035a391245312e34ad419f63e — 2026-08-25¶
Pinned by Claude Desktop for Linux 1.37937.1. A large build that rebuilt the
session-worktree surface. Seven wire changes, all matched byte-for-byte. Four are
listed below. The other three are the git.status untracked handling, the
worktree_remove registration prune, and the worktree_remove locked-worktree
refusal. The off-wire git rewrite and VM probes surfaced those three.
Missed at first. This build also checks a supplied -cli-checksum against
the -cli-zst blob. That change was reconciled later, under issue 408.
Wire delta.
server.versionremoved. The method is gone. Calling it now answers-32601 "Unknown method: server.version".server.capabilitiesdrops it frommethods(18 methods now) and adds twofeatures:git.status.baseRepoandgit.worktree.external_root. (The-versionCLI flag is unaffected. It is not the RPC method.)git.statusrequiresbaseRepoand keys off a session worktree. The params are now{path, baseRepo}. An absentbaseRepoanswers-32602 "baseRepo is required". Status is reported for one case only:pathis a linked worktree whose main repository isbaseRepo. A plain path, a plain subdirectory and a nested repository all answer the bare{"isRepo":false,"clean":false}. So do the repository root itself, a worktree of a different repository, and the right worktree named against the wrongbaseRepo. The porcelain shape is otherwise unchanged, except for the first change line's leading space. 7d193f89 stopped trimming it. 5db5e4a returned entry 0 without it, while 7d193f89 and 4534d86 return every line verbatim. That was measured, and claustrum reconciled it in a later fix.git.worktree_createandgit.worktree_removeconfine worktrees to inside the repository. A suppliedworktreeRootis the exception. See theexternal_rootfeature in the off-wire notes below. AworktreePaththat is not absolute, carries a..component, or does not sit strictly underbaseRepois refused with anerrorCode:"unsafe_path"message. The messages are "is a relative path", "contains a \"..\" component", and "is not inside the repository … under<repository>/.claude/worktrees". On create an already-existing target is refused as "already exists … a fresh directory". Both also refuse a path that crosses a symlinked component under the repo (a planted.claude/.claude/worktreeslink) witherrorCode:"symlinked_component"on create. The create therefore cannot escape, and the remove cannot delete through the link out of the repo.worktree_removeapplies the same location checks (noerrorCodefield). The success shapes are unchanged. Create now makes the parent directory beforegit worktree add, so a nested session path succeeds on a fresh repository.files.listfails at the open for a non-directory. A regular file, readable or not, now answersopen <p>: not a directory. An unreadable directory answersopen <p>: permission denied. The build before saidreaddirent <p>: not a directory. On the wire this is one op-name change on the error path.
The empty worktreePath messages ("failed to create parent directory: \"\" does not
name a directory" on create, "failed to remove worktree: \"\" does not name a directory"
on remove) are matched too.
Three of these were found by matching the OFF-wire git-invocation rewrite (below)
and by VM probes, rather than by the frame battery. Those three are the git.status
untracked handling, the worktree_remove registration prune, and the
worktree_remove locked-worktree refusal. The frame battery's top-level-untracked
and non-locked-worktree fixtures did not exercise them.
git.statusuntracked files.--untracked-files=alllists an untracked file inside an untracked directory individually (?? sub/u.txt) rather than as the directory (?? sub/).git.worktree_removerefuses a LOCKED worktree. A locked worktree now answers{"success":false,"error":"refusing to remove worktree: <p> is locked (git worktree lock); unlock it to remove it"}and the directory survives. Pre-7d193f89the reference DELETED it and answered{"success":true}. An unlocked ordinary directory is still deleted. The reference runs nogit worktree removefor either case. Measured on an ephemeral VM against7d193f89. The frame battery never removes a locked worktree.git.worktree_removeregistration prune. A completed removal drops$GIT_DIR/worktrees/<name>, so a re-create at the same path succeeds where it previously failedalready registered.
Off-wire churn. The Go toolchain moved go1.23 → go1.25, which accounts for
most of the size growth. The build also rewrote the entire git layer. Every git
operation now runs under one of two -c hardening profiles. One is a light set. The
other is a heavy set that forbids all transport protocols and clears the credential
and askpass helpers. Each command also carries a config -z --list --name-only
precursor and config-hook pinning (GIT_CONFIG_KEY_0=hook.enabled=false).
git.status and
git.worktree_create are additionally reimplemented as multi-command plumbing in an
isolated temporary gitdir.
claustrum matches the hardening profiles, the precursor,
the base hook pins, and the wire-visible flags across git.status, git.info,
git.list_branches, and git.worktree_create. The isolated-gitdir status assembly and
the read-tree worktree checkout are process-shape that produces identical output. They
are matched for the observable and security behavior, but not reproduced
command-for-command.
git.worktree_remove is an off-wire exception. The reference implements it as a
hardened rev-parse --absolute-git-dir. It also deletes the worktree and its
$GIT_DIR/worktrees/<name> registration directly from the filesystem. It also deletes
the branch with a hardened update-ref. It runs no git worktree remove at all. Claustrum then ran an unhardened
git worktree remove --force with an os.RemoveAll fallback for the worktree itself.
Since the f6010b97 reconciliation, claustrum deletes the tree and the entry itself, as
the reference does. See PROTOCOL.md → git.worktree_remove.
Its branch delete now matches the reference: a raw update-ref --no-deref -d. It was
git branch -D, which also dropped the branch's [branch "<name>"] config section, where
the reference leaves it. Both now spare it, measured against 4534d86. Both yield
byte-identical frames on every probed case (locked refusal, non-worktree delete, stale
re-create, normal removal). The residual difference was the worktree-removal
mechanism, and that difference was off-wire on those cases. On other rows the old
mechanism was wire-visible, for example a partial delete failure and a symbolic-link
leaf. See PROTOCOL.md → git.worktree_remove.
Beyond git, the build adds a daemon-to-daemon reconnect handoff
and idle-connection management (the SSH-reliability items in the Desktop changelog).
It also adds install stale-partial pruning and the git.worktree.external_root
feature. With a client-supplied worktreeRoot on a unix host, the session worktree is
placed OUTSIDE the repository, under <worktreeRoot>/<directory>/<name>. On Windows
the reference gates this capability off. It refuses any
worktreeRoot with "a custom worktree location is not supported on Windows hosts yet".
Containment guards the placement: absolute, no ..,
exactly two levels under the root. An ownership and writability check runs on the
root. The <directory> level must start out empty. A 285-byte
.claude-managed-worktrees marker is written at that <directory> level. A separate
check refuses a baseRepo that itself sits under a managed-worktrees marker
(errorCode:"nested_base_repo"). Both are reproduced and measured byte-for-byte
against 7d193f89 on an ephemeral VM. That VM covered the external-worktree refusals,
the marker body, and the nested-base-repo refusal through a planted marker.
How it was bounded. The cross-binary frame battery reports claustrum ≡
7d193f89 byte-identical across the method suite. Every worktree, status and list edge
shape above was additionally probed per-method against the reference on an ephemeral
VM. Those probes covered the containment ordering and the git.status worktree gate
over six repository shapes. They also covered the files.list open error over a file,
a link and a directory, plus the unreadable
cases.
5db5e4a12f88487e47c2c48259b69a2d630bb3f7 — 2026-07-06¶
Wire delta. None.
Off-wire churn. The daemon now persists its auth token to daemon.token
(mode 0600) in the socket's directory. It writes the file at startup and
unlinks it at graceful shutdown. A client can therefore reconnect to a daemon that
already runs, and authenticate again after the original -token-file was
unlinked or the -token-fd pipe closed. claustrum matches this in
tokenpersist.go, wired through runServe and teardown.
PROTOCOL.md → Token persistence
holds the wire contract.
How it was bounded. The frame battery and differential binary analysis
against 7c2f88d both point to token persistence and to nothing else. No other
method or phase changed. The forensics stay outside the committed tree.
7c2f88d13e5f269762dd4d463aa4eb3102214110 — 2026-07-02¶
Wire delta. Method count 18 → 19. claustrum matches all five changes byte-for-byte (values and timing) against the reference:
process.killAndWaitis a new method, betweenprocess.killandprocess.reattach. The method blocks until the process is gone. It then reports the outcome as a result. Its params aretimeoutMs(grace) andescalate. Its result is{found,died[,alreadyExited][,escalated]}. The page process.killAndWait is canonical for the defaults and the grace clamp.- The
process.stdin.offsetcontract is new. Aprocess.stdinreply now always carriesapplied, the cumulative count of decoded bytes. Anoffsetparam makes stdin idempotent across reconnects. A duplicate becomes aduplicate:trueno-op. An offset ahead of the applied count gives a-32003gap error. A partial overlap applies only the fresh tail. process.reattachgainedstdinApplied, the cumulative counter. A client that reconnects uses it to continue stdin at the correct offset.git.infogainedrepoSlug(owner/repofromremote.origin.url) anddefaultBranch(fromrefs/remotes/origin/HEAD). Both are always present, including on the non-repo body. The slug rule requires the host to begithub.comand applies a charset check to both segments. The rule is not "exactly two path segments". PROTOCOL.md → git.info is authoritative for that rule, and its 42-shape table backs it.server.capabilitiesgained afeaturesarray (["process.stdin.offset"]).
Off-wire churn. git.list_branches switched to --sort=refname, which keeps
the same lexical order. git.worktree_create gained a guard on ref
names. Both changes are measured byte-identical. Three new internal symbols are
not wire methods. server.capabilities is authoritative on the method set.
How it was bounded. The frame battery gates all five changes. Differential
binary analysis showed that the off-wire deltas are real source, and not
compiler noise. The forensics stay outside the committed tree. Provenance: Claude
Desktop for Linux 1.18286.0 (2026-07-02) embeds a manifest that pins this SHA,
and it calls 15 of the 19 methods. The uncalled four include
process.killAndWait, server.version and server.shutdown. The --stop
CLI drives shutdown, and the client reads the version from --version CLI
stdout, not over RPC. A
capture of a real session will therefore not exercise the new method, and the
synthetic battery stays the gate for it. That client also bears on the
-cli-zst checksum path (retired D1): --install carries --cli-checksum on the --cli-url download. A
later argv capture (2026-08-10, two cold starts on one host) shows this
independently. The retired D1 entry records what Desktop
supplies on the --cli-zst SFTP fallback, and the limits of that record.
d20a77da22b7d4822f758654b226299ad7021c22 — 2026-06-09¶
Wire delta. None (pure rebuild).
Off-wire churn. The binary diff showed one changed function, in the
-install bootstrap. That path is off the JSON-RPC wire.
How it was bounded. The full frame battery stayed byte-identical. The pin bump needed no code changes.
7cbfa471529b0dd33a5cc2f69c41c11bfe7fef6f — 2026-06-04¶
Wire delta. git.info gained root, from git rev-parse --show-toplevel.
root gives the top level of the repo. That holds for a path that is a
subdirectory.
Off-wire churn. Two more app-code changes came with this build. A re-audit on 2026-07-02 examined them. claustrum already covers both, and neither is a missed divergence:
- The
-installpath gained an HTTPS download and a SHA-256 verify. claustrum mirrors the substance:install.goverifies SHA-256 withverifyChecksum, unconditionally on the-cli-urlpath, and downloads withfetchToFile, which streams to a temp file. claustrum then uses a plain atomicos.Rename, which POSIX-replaces a target file. The reference handling of an existing target is not probe-measured. It has no wire impact. - Changed code on the
process.spawnfailure path, which is wire-reachable. It was therefore the killAndWait-shaped risk: a change that the happy-path battery never stresses.
How it was bounded. The static drift check passed on this build. Only the
byte-for-byte frame battery caught root. The lesson: the battery is the
authoritative gate, not the static check. A differential probe on 2026-07-02 ran
the spawn refactor across three failure modes and found it byte-identical. The
refactor kept the synchronous -32603 and Go-exec-error-string contract that
claustrum already emits (methods_process.go processSpawn → codeInternal).
Generalized lesson: a one-line ledger entry can under-record a build, because an
off-wire change or a failure-path change never surfaces in the frame battery. The
bump procedure therefore compares more than the wire (see
Upstream tracking). The forensics stay outside the
committed tree.
8de85faaa11694321e937499a18c7ab88f37c76c — 2026-05-21¶
This build is the baseline. The clean-room reimplementation was first built against it.
When you bump the pin¶
Do these three steps after you reconcile a new build. Upstream tracking gives the reconcile step:
- Add a row and a detail section here, newest first.
- Update
scripts/UPSTREAM_SHA. - Document any wire change in
PROTOCOL.md.