Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3da5828
feat(12-1): build the disposable tree the live run starts from
crenshawdev Oct 8, 2026
871debb
feat(12-1): build the projects the sessions work in
crenshawdev Oct 8, 2026
6e97537
feat(12-1): render the guard side from the binary and time every call
crenshawdev Oct 8, 2026
d21da6b
feat(12-1): render the server side and print every session's launch
crenshawdev Oct 8, 2026
6750187
feat(12-1): write the observation sheet with a stable id on every row
crenshawdev Oct 8, 2026
d50e33b
feat(12-1): read the run back out of the ledger and the results folder
crenshawdev Oct 8, 2026
06b3dbe
docs(12-1): write the procedure the owner runs by hand
crenshawdev Oct 8, 2026
386e7a6
fix(12-1): decompress a stored capture body before hashing it
crenshawdev Oct 8, 2026
2b76922
fix(12-1): end the setup script with a line that says it finished
crenshawdev Oct 8, 2026
0c42adc
docs(12-1): correct the procedure where the first live run found it w…
crenshawdev Oct 8, 2026
a30d99b
fix(12-1): word the sheet rows for what Claude Code 2.1.294 does
crenshawdev Oct 8, 2026
9bf5551
docs(12-1): say why the overlap capture has its own request id
crenshawdev Oct 8, 2026
25386bf
fix(12-1): fence the live scripts' writes and give the procedure chec…
crenshawdev Oct 8, 2026
76f3b11
docs(12-2): keep the first live run as a dated sheet with every row c…
crenshawdev Oct 8, 2026
3675864
Merge remote-tracking branch 'origin/main' into daneel
crenshawdev Oct 8, 2026
a8eaa9e
docs(12-2): keep the rerun against the merged fixes as its own dated …
crenshawdev Oct 8, 2026
5e2362a
docs(12-2): record both live runs in the host-matrix readme
crenshawdev Oct 8, 2026
d8f519d
docs(12-2): state what the live runs showed for the host matrix
crenshawdev Oct 8, 2026
ca55c24
docs(12-2): say what the live runs showed for the guard rows
crenshawdev Oct 8, 2026
bf42912
docs(12-2): record what the live runs showed for parts and the always…
crenshawdev Oct 8, 2026
bbe52b3
docs(12-2): name the live run and its open items in the roadmap
crenshawdev Oct 8, 2026
db6c152
docs(12-2): correct four claims the sheets do not support
crenshawdev Oct 8, 2026
e908dfa
docs(host-matrix): say the agent saved the reads
crenshawdev Oct 8, 2026
3f771d7
feat(12-3): keep the updater off the launcher and refuse a root that …
crenshawdev Oct 8, 2026
420ca0f
feat(12-3): catch a moved launcher in the post-run reads
crenshawdev Oct 8, 2026
108c8e1
feat(12-3): send the grep and glob rows through a launch that offers …
crenshawdev Oct 8, 2026
669136a
docs(12-3): make the isolated login the owner's own step before sessi…
crenshawdev Oct 8, 2026
29d82dd
feat(12-3): check the rendered skill in both placements
crenshawdev Oct 8, 2026
25529a9
feat(12-3): report a restore on the disposable ledger
crenshawdev Oct 8, 2026
7c8ca4c
docs(12-3): leave keys and detection unavailable and out of the owner…
crenshawdev Oct 8, 2026
fcef576
fix(12-3): clear every inherited git variable before the scripts run git
crenshawdev Oct 8, 2026
b8653dc
fix(12-3): keep ps from cutting the process list to COLUMNS before th…
crenshawdev Oct 8, 2026
793a350
docs(12-4): keep the re-run against the fixed procedure as its own da…
crenshawdev Oct 8, 2026
8f87e78
docs(12-4): say what the third live run showed and mark it the final one
crenshawdev Oct 8, 2026
216c248
docs(12-4): state what the third live run showed in designs 0001, 001…
crenshawdev Oct 8, 2026
8cb4ece
docs(12-4): name every live acceptance still open in the roadmap's T1…
crenshawdev Oct 8, 2026
f05b52c
docs(12-4): cite a sheet row that does not exist in the roadmap
crenshawdev Oct 8, 2026
a336e61
docs(12-4): revert the deliberate AC6 break in the roadmap
crenshawdev Oct 8, 2026
b947826
docs(12-4): say the two prompts were sent at once, not the two sessio…
crenshawdev Oct 8, 2026
163c041
docs(roadmap): mark build 3 t12 merged
crenshawdev Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions docs/design/0001-evidence-ledger.md

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions docs/design/0010-guard.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/design/0012-host-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ The library holds the per-session server (`crates/baley/src/mcp/`), and `baley s
| HST-R2, HST-R3 | Withdrawn | Nothing to build: each session starts its own stdio server (ADR 0034) |
| HST-R4 | Built | The 2025 decoder reads `initialize` and the 2026 decoder reads the request's `_meta` (`crates/baley/src/mcp/client.rs:24-40`). The host is selected per call (`crates/baley/src/mcp/client.rs:95-126`, `crates/baley/src/mcp/handler.rs:97-122, 190-198, 227`), and a missing or unsupported client is answered `failed` `unknown-host` before the queue (`crates/baley/src/mcp/gate.rs:71-110, 162-178`). The supported hosts are `Host::ALL` (`crates/baley-core/src/policy/schema.rs:134-140`) |
| HST-R5 | Built | Three tools in a fixed order (`crates/baley/src/mcp/tools.rs:83-120`), append-only operation names, with `instruction` appended last to the query baseline (`crates/baley/src/mcp/operations.rs:127`), held by the expected spellings and the test that checks both baselines against them (`crates/baley/src/mcp/operations.rs:479-592, 605-609`), a flat schema that types each served operation's arguments from the request shapes `schema` serves, with no combinator at the top (`crates/baley/src/mcp/tools.rs:122-227`, held by the tests at `crates/baley/src/mcp/tools.rs:303-477`), plus the `schema` operation, which serves each served operation's request shape, the `capture` and `document` shapes included (`crates/baley/src/mcp/operations.rs:290-327, 404-474`, `crates/baley/src/mcp/capture.rs:43-61`, `crates/baley/src/mcp/document.rs:26-49`), and `failed` as its own arm of the envelope (`crates/baley/src/envelope.rs:82-153`). The gate raises a protocol error only for an unknown tool (`crates/baley/src/mcp/gate.rs:77, 153-160`) |
| HST-R6 | Partly built | `help`, `schema`, `instruction` and `document` answer whole, or in parts of at most 24,576 body bytes, through one helper (`crates/baley/src/mcp/parts.rs:5-57`) in the four answers (`crates/baley/src/mcp/operations.rs:335-358, 360-402, 404-474`, `crates/baley/src/mcp/document.rs:125-161`). Instructions are read by identity through `instruction`, and the tools carry a fixed order and cache hints (`crates/baley/src/mcp/tools.rs:70-81`). `document` serves captures by identity, and every part carries the identity and the capture's metadata (`crates/baley/src/mcp/document.rs:39-49, 125-161, 212-323`). A purged capture answers with its own project's tombstone reason, re-reading that view when the body lookup observes a later purge (`crates/baley/src/mcp/document.rs:91-104, 258-287, 306-323`). Its other identity kinds are their builds', and `document-search` answers `operation-unavailable` until Build 8 (`crates/baley/src/mcp/operations.rs:101, 276-288`). Whether Claude Code delivers a full part whole, given that each answer travels as text and as structured content (about twice the body on the wire), is T12's live measurement |
| HST-R6 | Partly built | `help`, `schema`, `instruction` and `document` answer whole, or in parts of at most 24,576 body bytes, through one helper (`crates/baley/src/mcp/parts.rs:5-57`) in the four answers (`crates/baley/src/mcp/operations.rs:335-358, 360-402, 404-474`, `crates/baley/src/mcp/document.rs:125-161`). Instructions are read by identity through `instruction`, and the tools carry a fixed order and cache hints (`crates/baley/src/mcp/tools.rs:70-81`). `document` serves captures by identity, and every part carries the identity and the capture's metadata (`crates/baley/src/mcp/document.rs:39-49, 125-161, 212-323`). A purged capture answers with its own project's tombstone reason, re-reading that view when the body lookup observes a later purge (`crates/baley/src/mcp/document.rs:91-104, 258-287, 306-323`). Its other identity kinds are their builds', and `document-search` answers `operation-unavailable` until Build 8 (`crates/baley/src/mcp/operations.rs:101, 276-288`). In the 2026-10-08 runs part 1 of a 33,000-byte capture arrived as 24,576 bytes naming part 2 as next, byte-identical to the first 24,576 bytes of the fixture, in the main session and in a subagent (`claude-live-2026-10-08-run2.md#hand.parts.document-main`, `#hand.parts.document-subagent`). The first run's `document` calls had failed because Claude Code sent the nested identity as JSON text (`claude-live-2026-10-08-run1.md#hand.parts.document-main`, issue #232, fixed in bug pull request #234), and the second run was made against a commit that holds the fix. `help` (4,819 bytes) and `instruction` (1,366 bytes) arrived whole as one answer (`claude-live-2026-10-08-run2.md#hand.parts.help`, `#hand.parts.instruction`). Only part 1 was read, so the arrival of later parts is unverified, and the bytes on the wire were not measured, though each answer travels as text and as structured content (about twice the body) |
| HST-R7 | Partly built | The session context is gathered once and judged (`crates/baley/src/mcp/context.rs:20-50, 127-167`), each call's context and caller are formed (`crates/baley/src/mcp/context.rs:222-246, 295-323`), and decisions run one at a time on the worker behind one queue (`crates/baley/src/mcp/queue.rs:15-93`, `crates/baley/src/mcp/worker.rs:91-238`, `crates/baley/src/mcp/admission.rs:28-59`). The worker publishes a completed drain only when the queue is empty and the last answer has been sent, including on close or abandon (`crates/baley/src/mcp/worker.rs:50-71, 164-191, 226-237`). The port holds the caller value (`crates/baley-store/src/caller.rs:569-576`), `Work::push` stamps the command's caller on every event it appends (`crates/baley-store-sqlite/src/transact.rs:854-888`) and the `event.caller` column stores it (`crates/baley-store-sqlite/src/schema.rs:51`). Preparation finds the project afresh from the caller's project directory and checks that the ledger lists it, and a write goes on to the replay lookup, the settings, checkout admission and the policy step in that order. The plan is pure and the entry performs each step it asks for (`crates/baley/src/mcp/prepare.rs:263-415, 426-548`). Checkout admission and the step take the call's caller and the server's time and record as Baley (`crates/baley/src/checkout/admit.rs:52-93, 212-243`, `crates/baley/src/checkout/mod.rs:77-101`, `crates/baley/src/policy_step/mod.rs:16-46`, `crates/baley/src/policy_step/record.rs:24-66, 129-160`), and `run_decision` hands the operation the ledger, the host, the caller and the server's time (`crates/baley/src/mcp/handler.rs:58-71, 125-152`). `capture` and `document` carry `needs_project: true` (`crates/baley/src/mcp/operations.rs:100, 168, 200-208`) and reach preparation from their arms in `handler::operate` (`crates/baley/src/mcp/handler.rs:154-179`): each judges its arguments first, then `capture` prepares a write and `document` a read (`crates/baley/src/mcp/capture.rs:277-322`, `crates/baley/src/mcp/document.rs:174-207`). The capture entry selects the caller with instruction evidence before invoking preparation, so checkout admission, the policy step and the capture command all record that evidence (`crates/baley/src/mcp/capture.rs:169-210, 292-304`). The guard hook fills the hook form on every record it makes in `user` (`crates/baley/src/guard_hook/unrecordable.rs:12-41`, `crates/baley/src/guard_hook/record.rs:203-213`) |
| HST-R8 | Not built | Only the parked engine runs a suite inside one call (`crates/baley/src/execution_service.rs:275-287`, `crates/baley/src/execution/runner.rs:972-1005`). The session server answers the execution operations as unavailable (`crates/baley/src/mcp/operations.rs:131-198`) until Build 5, so no call it serves runs a suite |
| HST-R9, HST-R10 | Not built | The parked engine holds owner questions as gate records answered by `execution-authorize` with any non-blank owner and time (`crates/baley/src/execution_service.rs:364-500`). The session server answers that operation as unavailable (`crates/baley/src/mcp/operations.rs:131-198`) until Build 5 |
Expand All @@ -530,7 +530,7 @@ The library holds the per-session server (`crates/baley/src/mcp/`), and `baley s
| HST-R17 | Not built | `hooks/hooks.json:3-14` holds a hand-written nine-tool `PreToolUse` entry with a 10-second timeout. No installer, `baley install`, updater or install record is built. Delivery is decided by ADR 0038; T14 to T17 implement and qualify it with unsigned development artifacts only. T14 adds the detached updater, daily claims and update outcome events; #14 supplies and qualifies both verifiers at `verify_download` before any release. T16 owns the unbuilt provider choice, typed acknowledgement, installation-writer API-host allowances and separate global reviewer-list write before the settings `config set`. The registration, the hook, the sandbox and deny-rule proposal, its composition into an existing settings document and the coverage judge are rendered in the library (`crates/baley/src/host_artifacts/registration.rs:12-26`, `crates/baley/src/host_artifacts/hook.rs:21-37`, `crates/baley/src/host_artifacts/security.rs:142-199`, `crates/baley/src/host_artifacts/compose.rs:98-126`, `crates/baley/src/host_artifacts/coverage.rs:281-356`), and the placement projection carries the installed executable path (`crates/baley/src/host_artifacts/placement.rs:271-296`). T15 writes them and passes the projection to the guard. T14 defines and adds the staged-version folder, which is planned, not built. `hooks/hooks.json` stays hand-written, and a test holds its matcher and timeout to the renderer's (`crates/baley/src/host_artifacts/hook.rs:104-118`) until T15 writes the hook from the renderer. Removal of the built key paths belongs to Build 4 (#25). |
| HST-R18 | Built | The `failed` answer is built: a code, a place, `recorded: false` and `retryable`, returned as a successful tool result (`crates/baley/src/envelope.rs:82-153`, `crates/baley/src/mcp/gate.rs:66-69`). The server uses it for `unknown-host` (`crates/baley/src/mcp/gate.rs:162-178`), `server-overloaded` (`crates/baley/src/mcp/admission.rs:50-59`) and the project and caller faults (`crates/baley/src/mcp/gate.rs:112-151`). Only `server-overloaded` and `ledger-busy` are retryable (`crates/baley/src/envelope.rs:105-114`). Preparation answers each fault as `failed`: its codes and places (`crates/baley/src/mcp/prepare.rs:34-56`, `crates/baley-core/src/policy/parse.rs:16`, `crates/baley-core/src/checkout/judge.rs:12`), the answers a store failure, a git fault and a fork get (`crates/baley/src/mcp/prepare.rs:217-261`, `crates/baley/src/checkout/mod.rs:22-63`) and where the plan raises each (`crates/baley/src/mcp/prepare.rs:263-415`). A ledger that could not be opened at start answers `ledger-unavailable` (`crates/baley/src/mcp/serve.rs:70-97`). Checkout admission and the policy step are separate transactions, so a checkout admission recorded before a later step failed stays recorded (`crates/baley/src/mcp/prepare.rs:1-13`). `capture` answers a store fault `failed`, `ledger-busy` as retryable and any other as `ledger-unavailable`, answers bytes that were purged before `failed` `text-purged`, not retryable, and answers `request-id-reuse` as a refusal that records nothing (`crates/baley/src/mcp/capture.rs:324-378`). `document` maps its read faults the same way (`crates/baley/src/mcp/document.rs:215-323`). A capture's argument refusals are answered before preparation and record nothing (`crates/baley/src/mcp/capture.rs:87-167, 283-287`), and a named phase is refused `no-such-phase` inside the capture's transaction and recorded as a refused `command.completed` (`crates/baley/src/mcp/capture.rs:230-245`) |
| HST-R19 | Partly built | The decoder bounds a whole frame at 4 MiB and its depth at 128 (`crates/baley/src/mcp/frame.rs:14-18, 153, 246`). A frame over a bound or not JSON is discarded to its newline and answered with a JSON-RPC error while reading goes on (`crates/baley/src/mcp/frame.rs:470-493`, `crates/baley/src/mcp/transport.rs:52-73, 218-247`). Hook input is bounded (`crates/baley/src/hook_input/mod.rs:19-21`, `crates/baley/src/guard_hook/mod.rs:50-61`). Every git child runs with a deadline that `validate_launch` enforces (`crates/baley/src/process.rs:233-274`, `crates/baley/src/git_process.rs:49-99`): a caller outside the guard only at its exact registered deadline, and the guard's two callers, for the branch and for HEAD's copy of `baley.toml`, only at the timeout a budget grant gave the launch, above zero and at most 5 seconds, in their own process group. Only a grant sets that timeout, so one set by hand is refused (`crates/baley/src/process.rs:128-138`, `crates/baley/src/guard_budget.rs:33-115`). The suite runner's `sh -c` (`crates/baley/src/execution/runner.rs`) runs with none, owned by Build 5, and the still-built `baley exec --key` has no deadline. Its removal belongs to Build 4 (#25) under ADR 0039. |
| HST-R20 | Built | Each descriptor carries the marker (`crates/baley/src/mcp/tools.rs:83-120`, asserted at `crates/baley/src/mcp/tools.rs:272-282`). The registration renders the server-level `alwaysLoad: true` only when asked (`crates/baley/src/host_artifacts/registration.rs:20-26`), and T12 proves Claude Code accepts both forms |
| HST-R20 | Built | Each descriptor carries the marker (`crates/baley/src/mcp/tools.rs:83-120`, asserted at `crates/baley/src/mcp/tools.rs:272-282`). The registration renders the server-level `alwaysLoad: true` only when asked (`crates/baley/src/host_artifacts/registration.rs:20-26`), and the 2026-10-08 runs tried the plain form: with a registration that has no `alwaysLoad`, all three tools were callable without a tool search in the main session and in a subagent, in a session that does defer other tools, so the tool-level marker works alone (`claude-live-2026-10-08-run1.md#hand.tools.explicit-main`, `#hand.tools.explicit-subagent`, and again `claude-live-2026-10-08-run2.md#hand.tools.explicit-main`, `#hand.tools.explicit-subagent`). The first two runs had no login into the isolated configuration, so they could not start a session with the `alwaysLoad` form. The third run did, after the owner's login: `claude mcp add-json --scope user` stored a registration with `alwaysLoad: true`, a running session listed `baley` with 3 tools from the user scope, and in that session, which defers other servers' tools, all three tools were callable without a tool search in the main session and in a subagent, whose capture carries the session's `baley_session`. Claude Code accepted the `alwaysLoad` form (`claude-live-2026-10-08-run3.md#ses.b.registered`, `#hand.tools.user-main`, `#hand.tools.user-subagent`) |

## 12. Open questions

Expand Down
Loading
Loading