From ee50adf78c885da3fd9a26c431901eef84399fe3 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Sun, 27 Sep 2026 22:33:18 -0700 Subject: [PATCH] docs: decisions: P23 applied as amended; the M5c design Co-Authored-By: Claude Opus 5.5 (1M context) --- docs/decisions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/decisions.md b/docs/decisions.md index 1cb370b..d646fd1 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -6,6 +6,7 @@ Newest first. A decision that changes `docs/design.md` lands in the same commit | Date | Decision | Reason | |---|---|---| +| 2026-09-27 | M5c design (spec `docs/specs/2026-09-27-m5c-honcho.md`, approved): the owner and other people are observed Honcho peers, the agent's peer is not; every trusted memory write is mirrored as a conclusion at once (a `user.md` entry as the owner's, a `memory.md` entry or note as the agent's), and undo deletes it; a turn without complete speaker information is not synced; `memoryd` records each decision and send in an append-only ledger, `memory/honcho.jsonl`, which is also the outbox; `recall` searches the local index, other agents' trusted workspaces and the fleet, never the agent's own workspaces; `ask_memory` asks each named workspace by workspace chat, `minimal` by default; API keys per workspace from `bxcore::secrets`. M5c is planned and run in two halves, the write path first. | Owner's decisions, 2026-09-27, grounded in `roncho` 1.0.0 (checked against its requirements) and Honcho 3.2.0 (source read at `v3.2.0`, and rift's live metrics). | | 2026-09-27 | M5b settles three open items. An invalid-arguments denial carries its reason (`ToolResponse::Denied.detail`, one line, 300 characters at most). `loopd` neutralises the model's chat-template tags when text from outside is first logged (user messages, tool results after their cap, the memory block), checked against the tokenizer by the self-test in two `/tokenize` requests. The secret store is `bxcore::secrets`, behind the `secrets` feature, for every role but `loopd`. | M5b spec, sections 4, 5 and 8; landed 2026-09-27, device-checked on straylight (review in `docs/implementer-log.md`). The self-test's per-tag requests overran `inferproxy`'s burst on the device and were batched (review finding 10). | | 2026-09-27 | The two driver trials of M5b's run, judged: `RESUME` stays, and now also resumes a session stopped at the time limit, the case where it was needed (task 10); `SLOTS_URL` stays, though it never fired. Sessions run with `opencode run --pure` and `OPENCODE_DISABLE_CLAUDE_CODE=1` by default (`PLUGINS=1` restores both), and the prompt names the log row. | The run's evidence (implementer lessons T47, T48): global plugins rewrote the system prompt mid-session and cost 76 of 111 minutes of prompt processing in tasks 01 to 10; task 10 stopped at the limit with its work uncommitted; task 14's row took its name from the heading. `89a50bc`. | | 2026-09-26 | `proto` becomes `bxcore`, the one shared crate: it keeps everything `proto` held and gains `secrets` (behind a Cargo feature that `loopd` never enables) and `sanitize`; later shared code goes there too. The rule becomes: every role depends on `bxcore` and on no other workspace crate, and `bxcore` depends on no workspace crate. The rename is made by changing the crate and manifests and fixing what the build reports, not by search-and-replace. | Owner's decision (M5b design). A second shared crate for secrets was the alternative; one crate keeps the rule simple. Not `core`, which shadows Rust's own crate (checked). A spike found the four layers the rename touches (compiler, formatting, fixture path strings, the crate-dependency check); M5b spec, section 3. | @@ -111,10 +112,10 @@ Later changes to the brief: | 2026-09-24 | P19, Memory 2 to 8: `recall` over a local FTS5 index (session logs, archive) and Honcho, `ask_memory`; Honcho writes only from clean sessions; per-workspace trust set by the owner; notes, the flush job and the embedding index go; memory text stays on the owner's hosts. | Owner's approval, 2026-09-24; see the row of that date under Decided. | | 2026-09-24 | P20, Milestones: M5 becomes M5a (local memory in `memoryd`), M5b (Honcho) and M5c (the scheduler and the tiering job); the embedding-index M5b goes. | Owner's approval, 2026-09-24; see the row of that date under Decided. | | 2026-09-24 | P21, Memory 1, 2, 6, 7, State and Milestones: memory is identity (`soul.md`, `memory.md`, `user.md`, in the prompt, edited only by clean sessions) and experience (`notes.md` and session logs, recalled with a source tag: `identity`, `memory`, `memory-tainted`); writes need no approval; `note` in any session; an untrusted session's identity `add` becomes a note; a check on every write, a journal and undo; the policy of the memory tools is built in. | Owner's approval, 2026-09-24; see the rows of that date under Decided. | +| 2026-09-27 | P23, as amended by the M5c spec (`docs/specs/2026-09-27-m5c-honcho.md`), Memory 4 and 5: per agent a trusted and an untrusted Honcho workspace for turns (the speaker's message and the final reply); untrusted notes, as messages, to one fleet workspace every agent shares and reads, always untrusted; nothing above `private`, and never a `secret` session; the gate is `brokerd`'s session state, asked over a read-only socket when the turn ends, with `loopd`'s labels as a second check; no rebuild from the logs. | Owner's decisions, 2026-09-25 (P23) and 2026-09-27 (the amendments). The fleet workspace keeps one agent's raw untrusted turns out of the others' dialectic (Honcho cannot delete a message, and its dialectic filters only by session); rebuild is dropped because Honcho accumulates and is corrected by contrary facts. | ## Proposed changes to the design brief | # | Change | Reason | |---|---|---| | P22 | Target environment, Roles and Milestones: Boxmaker becomes a fleet of independent agents, one per host. Each has its own identity (`soul.md`), memory, grants, audit log and credentials (its own Mattermost bot); they share only the fleet's memory, through Honcho (M5c). Each agent's inference is a configured endpoint that speaks llama-server's API: the host's own router, another host's, or a router such as crossbar. A new last milestone, M8, fleet deployment: `nixosModules.boxmaker` (`nix/module.nix`) for the owner's NixOS hosts, used from their system flake; `dist/` units, a config example and `make install` for other Linux hosts (an Omarchy machine); a host's inference measured, as M0 did on straylight, before an agent runs there. The flake itself (packages, the tool image, a dev shell) comes first, without the module. Open for M8: whether the roles run as systemd user units, as Hermes does on straylight (`linger`), or in M7's rootless containers; and what an endpoint must provide (`id_slot` pinning and queueing, `return_progress`, `timings_per_token`, `reasoning_control` and `/v1/chat/completions/control`, `/props`, `/slots`, prefix reuse on one slot), which the owner passes to crossbar's developer. Crossbar's answer (checked against its main, 4c64158, 2026-09-25): it cannot serve Boxmaker as deployed. It routes by the path's first segment or an `X-Crossbar-Route` header, never proxies `/slots` or `/tokenize`, may send `/control`, `/props` and `/slots` to a different host from the stream's, puts `/control` behind its limiter, and answers errors in its own shape. Until then an agent's `inferproxy` points straight at one host's llama-server. Crossbar's minimum for Boxmaker (a v2.3): a default route per listener, every call of a route on one host (a route per agent), side calls outside the limiter, and llama-server's error shape. Still open after that: a request queued in crossbar looks idle on the host's `/slots`, so Boxmaker retries it after 30 s; pinned routes should not queue in crossbar. Two agents on one host need different `[slots] main`. | Owner's direction, 2026-09-25: three agents run on three machines; boxmaker deploys to NixOS nodes from the system config and to an Omarchy machine; dixie gets an agent after its second GPU. | -| P23 | Memory 4 and 5, Milestones (M5c): each agent writes to two Honcho workspaces of its own, a trusted one and an untrusted one. A finished turn is written as two messages, the owner's (or other speaker's) from their peer and the agent's final reply from the agent's peer; tool calls, tool results and intermediate reasoning are not written. A turn is clean when the session is still clean at the turn's end, because the reply is made from the whole context: clean turns go to the trusted workspace, the rest to the untrusted one, which `recall` and `ask_memory` read as `memory-tainted`. The gate is `brokerd`'s session state, asked over a read-only socket query when `memoryd` learns the turn ended; a late answer can only file a clean turn as untrusted, never the reverse. `loopd`'s log labels are a second check. M5c's check "a turn from a tainted session never reaches Honcho" becomes "never reaches the trusted workspace". | Owner's direction and approval, 2026-09-25 (M5b design, now M5c): Honcho holds untrusted memories too, labelled by workspace since conclusions carry no per-entry provenance. Reading `brokerd`'s state file instead was rejected: a wrong path reads as clean (fails open), its modes block other users (M7), and it would make a private file an interface. To be applied to the brief with the M5b spec. |