diff --git a/CLAUDE.md b/CLAUDE.md index 62fce58..c268128 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -46,7 +46,9 @@ device-checked on straylight (child `sub-m6a-live-2` on slot 2; following slot-0 1787 of 1788). M6b (`consult` behind `brokerd`, allowlisted loopback HTTP, Decision `body`; spec `docs/specs/2026-10-04-m6-subagents-consult.md` sections 4, 5, 6, 7 M6b and 8; plan `docs/plans/M6b/`) is done, reviewed in `docs/implementer-log.md`; no finding is open; spec 7 -device check (loopback dummy on straylight, no internet) is later. +device-checked on straylight (clean consult audit body matched the captured loopback POST; +a private untrusted recall still consulted under `max_taint = "private"`, matching spec 4.1's +class gate). P22 (proposed, not applied) makes Boxmaker a fleet of independent agents, one per host, deployed with Nix in a last milestone, M8; `flake.nix` builds every binary, the tool image and a dev shell. Work happens on titan (macOS, no Nix); build and run diff --git a/docs/implementer-lessons.md b/docs/implementer-lessons.md index d580b5d..1ad026b 100644 --- a/docs/implementer-lessons.md +++ b/docs/implementer-lessons.md @@ -198,4 +198,6 @@ which is P9; the immediate next turn held it. M6b was Ornith through the driver, six tasks, first-gate pass in every row, no stop. The product files match the reference in behaviour (import order, const order, two blanks). Task 03 wrote the given tests in place and they `cmp` identical. Task 05's log row says `NOT_CONFIGURED` was -inserted before `SECRET_POINTER`; the file has it after (I17). Device check is later. +inserted before `SECRET_POINTER`; the file has it after (I17). Device check: clean consult body +matched the captured loopback POST; a private untrusted recall still consulted under +`max_taint = "private"` (spec 4.1 class gate; spec 7's device bullet expected refuse). diff --git a/docs/implementer-log.md b/docs/implementer-log.md index d008041..5c59112 100644 --- a/docs/implementer-log.md +++ b/docs/implementer-log.md @@ -1235,13 +1235,30 @@ loopback dummy) sit on the branch and were outside the reference. Spec 7 device No numbered product finding. Task 03's in-place tests and task 05's const-order log line are process notes. `rule_3`'s unknown-tool sentence still names the four container tools. -Device check is owner-side after this review: a loopback OpenAI-compatible dummy the check starts -on straylight; a clean session's audit body matches a captured request; a session that first -recalled an untrusted note is refused. No internet consult. Production daemons stay untouched. - What was good: six tasks, six first-gate passes, no stops, given tests unedited, every review-focus case in the plan is covered by a given test and holds, both consult runbook entries have pointers, no new crate, no vendor names in code. Known M6b limits, left as the README lists them: no internet consult, no HTTPS, cloud-led sessions later. + +Device check, 2026-10-04 UTC, on straylight (`target/debug` of `m6b` at `fa795ed`; Ornith slot 0 +live; slot 1 left empty; slot 3 was processing ~190k of someone else's prompt at the first turn; +a private `$HOME` at `/home/kyle/boxmaker-m6b-check`, production daemons untouched, no `gatewayd`). +Grant `consult.toml` `mode = "auto"` `max_taint = "private"`. `[consult]` pointed at a loopback +dummy the check started on `127.0.0.1:18765` (`model = "dummy-m6b"`, bearer from `CONSULT_TOKEN`). +Heartbeat `every_s = 0`. No `[runner]`. Dummy and daemons stopped from the PID file afterwards. + +`bxctl chat --session m6b-clean --no-thinking`: find_tool then call_tool `consult` with question +"what colour is the sky?". Dummy answered `cerulean dummy`. Then session `m6b-taint`: recall of a +planted private untrusted pewter-spoon note, then the same consult. + +| Check | Result | +|---|---| +| Clean session audit body equals captured POST | `m6b-clean` Decision body is 104 bytes and equals `logs/last-consult-body.bin`; JSON is model `dummy-m6b`, temperature 0.6, one user message, no `tools`. Result `cerulean dummy`, class `private`, `untrusted` true (grant default). Slot 0. | +| Session that first recalled an untrusted note | Recall hit `memory-tainted` / private. Following consult was **allowed** (`taint` private, `untrusted` true). Spec 7's device bullet expected refuse. Spec 4.1's class gate is `max_taint`; the session stayed `private` and the grant allows that class. The given deny test is a `secret` session. Audit body still equalled the captured POST. | + +Requests used `id_slot` 0 only (`consult` is `brokerd` HTTP, no child). Slot 1 stayed empty. No +internet consult. No numbered product finding against section 4 or the given tests. The spec 7 +wording "recalled an untrusted note is refused" did not hold for a private untrusted session +under a `private` grant.