Skip to content

Add the doctor's runtime host checks - #237

Merged
crenshawdev merged 18 commits into
mainfrom
calvin
Oct 8, 2026
Merged

crenshawdev merged 18 commits into
mainfrom
calvin

Conversation

@crenshawdev

Copy link
Copy Markdown
Owner

Build 3 T13. baley doctor now prints a host section after every line it printed before. The section comes from a new public host_doctor module, split into observe, judge and report so T17's installed doctor can take the same API. The doctor gets no flag, so the CLI hands it a placement map with every artifact unknown, and every expected artifact prints as not installed at exit 0 until T15 supplies real placements. Given a placement map, it compares placed stubs byte for byte with what Baley renders, judges the registration by composition's rule, runs T11's coverage judge unchanged over the settings and hook documents, checks that the guard covers all nine tools in the hook matcher (and that disableAllHooks isn't on), finds bwrap and socat on PATH on Linux, and checks the executable is there and runnable. Every coverage verdict is worded as configuration of the document it came from, never as proof, with Grep and Glob labelled best-effort. From the ledger it reports the last recorded server call's CLAUDE_PROJECT_DIR and working directory, a ledger written by a newer Baley as read-only for this binary, that the server's startup quick_check fence isn't visible from the command line, the home and config folders, and guard records that were behind at the doctor's start, with baley rebuild user as the fix. The existing lines keep their text, order and exit codes, a host gap raises the exit to 1, nothing raises it to 2 or 3, and the host checks write nothing to the ledger or to Claude Code's settings. Designs 0001, 0003, 0010 and 0012 describe the runtime doctor with T17's installed checks as planned, and the roadmap shows T13 in progress.

Each of the ten acceptance checks failed before its behaviour existed and passes now. nextest 3437 of 3437, clippy with -D warnings, cargo fmt --check and cargo deny pass, baley-core and baley-store still don't depend on rusqlite, no manifest or lock file changed, and the one diagram touched, the roadmap's Figure 4, parses. The diff reviews found six problems, all fixed here: the nine-tool check ignored disableAllHooks, an executable with no execute bit passed, the no-write test missed a ledger row changed in place and then tripped on SQLite's -shm file, a newer server call on a later ledger page was untested, and design 0012 claimed the whole doctor writes no file when only the host checks don't.

Left open: designs 0001 and 0012 list the exit-1 executable gaps without a dangling link or an unreadable executable, which the code also reports at 1. No test drives newer guard views through the report line. Nothing here has run against a live Claude Code host or a real installed placement, that waits on T15.

…cement is known

The host doctor module takes an observation, judges it into findings and
reports lines and a code, so the doctor can print a host section before
any placement is read.
…ady printed

The doctor builds an all-unknown placement map for the running binary
and appends the host report, taking the larger of the two exit codes so
a host gap never turns a damaged store into a 2.
… wrong with each

A placed file that is missing, not a regular file, unreadable or not a
JSON object, and an executable that is missing or not a regular file,
are host gaps. An unreadable document is never judged as an empty one,
which would invent coverage gaps.
…on by composition's rule

A stub that differs is reported with both digests so the owner can see
which side changed. The registration is judged by the same command and
arguments rule composition uses, so alwaysLoad never counts as a
difference.
…ent it was read from

The coverage judge runs once over the settings and hook documents, and
each verdict names the document its mechanism lives in, since the sandbox
and the guard hook can sit in two files. Grep and Glob stay best-effort,
and the report says outright that the verdicts are not proof of
enforcement.
… guard for

The coverage judge credits Bash, Monitor and PowerShell to the sandbox
and never asks whether the guard runs before them, so the nine tools
get their own check. A matcher in one item never borrows the guard of
another, and a look-alike command does not count.
…e sandbox verdicts without them

On Linux a missing bwrap or socat is named with its package and marks
the sandbox unsupported for the coverage judge. macOS needs nothing, and
any other platform is reported as one where the sandbox does not run.
…oks is true

The nine-tool check read only the hook items, so a hook document with the
disabling setting still reported the guard running for every tool, and with
the settings placement unknown the coverage judge never ran to say
otherwise. The check now names the document that sets it and the report
raises the code.
The executable check looked only at the file type, so a regular file at
mode 0644 passed while the hook and the registration fail to start it. It
now keeps the mode and uses the rule the sandbox programs already use: any
execute bit counts.
…e last recorded server call

The ledger already records both on every server write. Judging them with the
server's own rule keeps the doctor and the server from disagreeing, and
reading no environment avoids a false missing-project finding from a plain
terminal.
…ich folders it lives in

A ledger at a newer epoch opens read-only, so the owner needs to hear that
this binary can only read it. The server's startup quick_check does not run
from the command line, so the line says the integrity rows stand in for it.
…ehind at the doctor's start

The store's doctor reads the user project's view stamps before it verifies
the views, and verifying brings an old project current. Judging the raw
stamps shows the state the guard saw, so the line can name baley rebuild
user while it still matters.
The guard and host designs still gave the doctor's host checks to T13. They
now list what the doctor reports, what it cannot see, and keep the checks of
the installed result as T17's planned work.
…e ledger and config designs

The ledger design now lists what the doctor's host section adds and which
findings raise the exit status, and says the startup quick_check is not
observed from the command line. The roadmap marks T13 in progress.
The no-write check compared project names and head sequences, so a lease
renewal or any other in-place row change slipped past it. It now compares
the ledger home's bytes before and after, with an open claim in the fixture.
The test only fed later pages that held no server call, so an
implementation that kept the first answer passed it. A third page with a
newer server call now has to replace the kept one.
The store's doctor runs first and can bring stale views current, which
writes the database. The exit-status lists also named only a missing or
non-regular executable, but one with no execute bit and a true
disableAllHooks raise the code too.
A plain read may update SQLite's -shm file, which holds no durable row. The database and -wal stay in, so a changed row still shows.
@crenshawdev
crenshawdev merged commit e3ddd48 into main Oct 8, 2026
5 checks passed
@crenshawdev
crenshawdev deleted the calvin branch October 8, 2026 23:46
@crenshawdev crenshawdev mentioned this pull request Oct 9, 2026
13 of 17 tasks
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