M5a spec: details settled while building the reference
The memory socket in brokerd.toml is optional, and bxctl's flag is --memory-socket. A note's header carries its class. Built-in grants are kept apart from the owner's, and builtin- ids are reserved. The session state is carried through Decision and RunSpec, labels through run_labelled. loopd's assemble_with and MemorySource. Baseline measured at 881 and 2,432 tokens. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,9 @@ Facts this rests on, checked on 2026-09-24:
|
||||
the bytes it started with. No write asks the owner anything.
|
||||
4. What a session that has seen untrusted content wants to remember becomes a note, labelled
|
||||
untrusted: remembered and found by `recall`, never in the prompt.
|
||||
5. The baseline with the starter `soul.md` stays at 3,000 tokens or less, measured on the device.
|
||||
5. The baseline with the starter `soul.md` stays at 3,000 tokens or less, measured on the device;
|
||||
so does the baseline with every memory file at its limit. (Measured while building the
|
||||
reference, 2026-09-24: 881 and 2,432 tokens with Ornith's tokenizer.)
|
||||
6. A hit from a session that had seen untrusted content comes back marked untrusted.
|
||||
7. The owner can list every write (`bxctl memory log`), and undo the latest one of a file.
|
||||
|
||||
@@ -78,7 +80,7 @@ each item with its own label. Not everything remembered is believed, but it is r
|
||||
**`notes.md`.** Append-only. Each entry starts with one header line saying how it got there:
|
||||
|
||||
```text
|
||||
§ noted 2026-09-24T21:02Z in session mm-dh45qg… · untrusted
|
||||
§ noted 2026-09-24T21:02Z in session mm-dh45qg… · private · untrusted
|
||||
<the entry>
|
||||
§ moved 2026-09-24T20:14Z from memory.md in session mm-y73sxj3popgwumyccptb56p1ah
|
||||
<the entry>
|
||||
@@ -345,24 +347,36 @@ connection, the existing frames (`proto::frame`, `MAX_FRAME`). New message kinds
|
||||
is `recall` or `memory` is a grant problem at load (`grants-invalid`), with the fixed sentence
|
||||
`the policy of recall and memory is built in; remove this grant`. No grant file can turn memory
|
||||
off or put questions in front of it. What protects the prompt is where untrusted sessions'
|
||||
writes go (section 5), which `memoryd` decides from the state `brokerd` sends.
|
||||
writes go (section 5), which `memoryd` decides from the state `brokerd` sends. The built-ins
|
||||
are kept apart from the owner's grants (`GrantSet::grants` lists only the owner's; matching sees
|
||||
both), and grant ids starting `builtin-` are reserved. An invalid `grants/` still denies every
|
||||
call, the memory tools included: that is the fail-closed state `grants-invalid` describes.
|
||||
- **Where a decided call runs.** A composite runtime sends `Recall` and `Memory` specs to
|
||||
`memoryd`'s `brokerd` socket as a `memory_call`, with the session's taint and untrusted flag
|
||||
as `brokerd` holds them when it decides, and everything else to the configured runtime
|
||||
(Podman, or the refusing one). `[memory] socket` in `brokerd.toml` names the socket; without it,
|
||||
memory calls fail with a fixed sentence and a runbook pointer (`memoryd-unreachable`).
|
||||
- **Labels only get stricter.** `RunOutput` gains an optional label. `runner::run` answers with
|
||||
the stricter of the grant's label and the runtime's: the higher class, and untrusted if either
|
||||
is. Container runtimes return none, so nothing changes for them. The audit record and the
|
||||
session's taint use the combined label, as today.
|
||||
(Podman, or the refusing one). The socket is `{home}/run/broker-memory/memory.sock`, or
|
||||
`[memory] socket` in `brokerd.toml`; the section is optional, since the memory tools are always
|
||||
on. When `memoryd` does not answer in 30 seconds, the call fails with a fixed sentence and a
|
||||
runbook pointer (`memoryd-unreachable`). The session's state reaches the runtime through the
|
||||
`Decision` (which `decide` already receives it for) and the `RunSpec`. The Podman runtime
|
||||
refuses a memory tool with a fixed sentence rather than start a container for it.
|
||||
- **Labels only get stricter.** `Runtime` gains `run_labelled`, returning an optional label with
|
||||
the output; its default calls `run` and returns none, so container runtimes and the given test
|
||||
runtimes are unchanged. `runner::run` answers with the stricter of the grant's label and the
|
||||
runtime's: the higher class, and untrusted if either is. The audit record and the session's
|
||||
taint use the combined label, as today.
|
||||
- **Size.** `policy.rs` (498 lines) and `ledger.rs` (487) are at the limit; the plan splits them
|
||||
before anything is added.
|
||||
|
||||
## 9. `loopd`
|
||||
|
||||
- `[memory] socket` in `loopd.toml` (default `{home}/run/loop-memory/memory.sock`).
|
||||
- Baseline: `system.md`, a blank line, then the block from `memoryd`. `memoryd` unreachable, or
|
||||
refusing, fails the new session with the runbook pointer `memory-unavailable`.
|
||||
- Baseline: `system.md`, a blank line, then the block from `memoryd`
|
||||
(`Baseline::assemble_with`; `Baseline::assemble` stays, with no memory, for tests and the
|
||||
self-test). `memoryd` unreachable, or refusing, fails the new session with the runbook pointer
|
||||
`memory-unavailable`. `Context` takes the memory source explicitly (a `MemorySource` trait:
|
||||
`memoryd`'s client in `loopd serve`, `NoMemory` in tests), so `loopd serve` cannot leave it out.
|
||||
`make verify-device` starts `memoryd` beside `loopd serve`.
|
||||
- Registry: `recall` and `memory` are core, with the schemas of section 5. The model sees
|
||||
`clock`, `recall`, `memory`, `find_tool`, `call_tool`.
|
||||
- After a finished turn: `session_updated`, best effort. A failure is one log line; the next
|
||||
@@ -373,11 +387,13 @@ connection, the existing frames (`proto::frame`, `MAX_FRAME`). New message kinds
|
||||
|
||||
## 10. `bxctl`
|
||||
|
||||
- `bxctl reindex [--admin-socket PATH]`: sends `reindex`, waits, and prints `reindexed: 42 logs,
|
||||
- `bxctl reindex [--memory-socket PATH]`: sends `reindex`, waits, and prints `reindexed: 42 logs,
|
||||
1,208 records, 7 notes`. `memoryd` rebuilds into a new file and renames it over the
|
||||
old one, so `recall` keeps working meanwhile.
|
||||
- `bxctl memory log [N]`, `bxctl memory undo <id>`, and with review on, `bxctl memory pending`,
|
||||
`accept <id>`, `reject <id>` (section 5). Entries are printed escaped, as approvals are.
|
||||
`accept <id>`, `reject <id>` (section 5), each with `[--memory-socket PATH]` (default
|
||||
`{home}/run/owner-memory/admin.sock`; `--admin-socket` stays `brokerd`'s). Entries are printed
|
||||
escaped, as approvals are.
|
||||
|
||||
## 11. Configuration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user