Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
M5c-2 implementation plan: Honcho, the read path
For the implementer: each task file is one closed task for one fresh session. Read
AGENTS.md, then the task file, and do exactly that task. The driver istools/run-plan.sh.
Goal: the agent reads what the fleet knows. recall searches the other agents' trusted
workspaces and the fleet workspace alongside the local index, each source on its own limit, and
a new core tool, ask_memory, asks Honcho's dialectic about one or two workspaces. What comes back
is labelled, and taints the session, as a local recall hit does.
Architecture: bxcore gains ask_memory's arguments; brokerd runs it as a built-in memory
tool with its own wait; loopd declares it as a core tool with its own wait; memoryd gains
read-only Honcho clients, turns Honcho's messages and conclusions into recall items, runs its
Honcho sources and chats outside its state lock, and answers ask_memory.
Tech stack: Rust 1.98.1, edition 2024; roncho 1.0.0 (already a dependency of memoryd,
features = ["tls"]); no new crate.
Spec: docs/specs/2026-09-27-m5c-honcho.md, sections 3, 8, 9, 10 and 13, as amended on
2026-09-28 (8e56261).
The owner's decisions (2026-09-28)
- Queries from any session.
recallsearches Honcho, andask_memoryasks it, from a session of any class,secretincluded: Honcho stores no query, and on rift a query reaches only the owner's hosts. It is an assumption about rift's configuration, written into the spec (section 8) anddocs/egress.md. A query holding a known-prefix secret is refused before anything is sent. - Two workspaces per
ask_memorycall, both asked at once, so both answer insidebrokerd's wait; the model asks again for more. - New recordings from rift for the fake server (task 00), in a throwaway workspace deleted
afterwards, as in M5c-1. They changed two things (spec,
891f413):ask_memoryalways asks atminimal, since alowchat on rift returned raw tool-call markup; and a Honcho hit is kept only when it shares a term with the query, since search has no relevance cutoff.
What the code already has, and what it lacks
- A session keeps the tools array it was created with (
loopd's baseline is saved at the start and sent on every request):ask_memoryappears in sessions started after deployment, and no epoch code is needed. brokerdwaits 30 s for any memory tool (memory_port.rs,MEMORY_WAIT), andloopd120 s for any tool ([broker] timeout_ms). Neither has a per-tool wait;ask_memoryneeds 170 s and 180 s (spec 9).memorydholds its one state lock for the whole of arecall. Honcho searches (5 s) and chats (150 s) must run outside it, or everymemorycall waits behind them.- M5c-1's
Clientsare the sync worker's, for writes, and move into its thread. Reading needs its own clients: one per[[honcho.read]]workspace, the fleet, and the agent's own two (forask_memory). roncho's blocking client has what is needed:search_workspace,query_conclusions(it requires the observer and the observed) andworkspace_chat.
Global constraints
- Roles depend on
bxcoreonly;memorydalso onroncho. Nounsafe, no async runtime. - Every
ronchoclient is built with.without_config_file(); keys come frombxcore::secretsand are never logged; errors are logged by kind and status only. - Text from Honcho is neutralised on arrival and capped like a local
recallsnippet (600 characters); a result's labels raise the session as a local hit's do. - No Honcho call runs under
memoryd's state lock. - Without a
[honcho]section,recallis exactly M5b's andask_memoryanswers that Honcho is not configured. - No file the implementer reads holds a chat-template tag whole (T33), nor a fake key whole.
- Every path a given test creates is removed by a guard (T44); every process a test starts has a deadline.
- Each task gives its baseline and its gate count with what the count includes (T50, T53); the
branch line is a check, never
git switch(T51); import changes are single added lines (T54); whitespace-checked literals are marked on every edit (T55); the task's table ofroncho's API is complete, and the Cargo registry is off limits (T56).
Tasks (outline, for the owner's review)
| # | Delivers | Crates |
|---|---|---|
| 00 | (done by the design model, 718e66d) recordings from rift: workspace search with a limit and with no match, conclusion queries for two peers, and what a missing workspace answers |
memoryd fixtures |
| 01 | Wire: AskMemoryArgs { question, workspaces }, its name and its checks (question at most 2,000 characters; one or two workspace names, no repeats); fixtures |
bxcore |
| 02 | brokerd: ask_memory as a built-in memory tool (grant, parsing, routing to memoryd); a per-tool wait on memoryd, 170 s for ask_memory and 30 s for the others |
brokerd |
| 03 | loopd: ask_memory's schema as a core tool in a new registry; a per-tool wait on brokerd, 180 s for ask_memory and [broker] timeout_ms for the others; the system prompt's line on memory tools |
loopd |
| 04 | memoryd: read clients, one per [[honcho.read]] workspace, the fleet and the agent's own two, with a 5 s limit for searches and 150 s for chat |
memoryd |
| 05 | memoryd, pure: Honcho messages and conclusions as recall items (tag, source name, class, neutralised, capped), kept only when they share a term with the query, interleaved with the local hits to k, the local index first |
memoryd |
| 06 | memoryd: recall's Honcho sources, each on its own thread with its own limit, after the local search and outside the lock; <source>: unavailable; a query holding a secret sends nothing |
memoryd |
| 07 | memoryd: ask_memory: workspace names checked against [honcho], both chats at once, each answer tagged and capped, labels, <workspace>: unavailable; a question holding a secret sends nothing |
memoryd |
| 08 | memoryd serves ask_memory beside recall and memory, outside the lock; bxctl's usage and the runbook where a new message needs a pointer |
memoryd, bxctl |
After task 08, the design model runs the M5c-2 device check (spec 13) on straylight, rift and the
owner's Mattermost: a second memoryd under its own name writes a fleet note that recall finds,
tagged memory-tainted, turning the session untrusted; ask_memory answers from the agent's own
trusted workspace within its limit; with rift down, recall answers from the local index with
unavailable lines. The baseline is measured again against the 3,000-token budget
(make verify-device).
Before hand-over
Every task is worked through docs/plans/CHECKLIST.md with a reference in a scratch worktree
with its own build directory, replayed from its task text; mutations; /tmp compared around a
gate run; scratch files in the worktree's .state/; the whole workspace stressed under load
(T52); the reference moved to straylight as a bundle before the run. Task files name their log
row (T47). For every class or trust rule, each path that reads from Honcho gets a test at the
forbidden label (T58).
Running it
git switch -c m5c2 master
OPENCODE_MODEL=straylight/ornith-1.5-35b-a3b RESUME=1 \
SLOTS_URL='http://straylight:11434/slots?model=ornith-1.5-35b-a3b' \
tools/run-plan.sh docs/plans/M5c2 01