Files
boxmaker/docs/plans/M5b/files/runbook-memory-write-flagged.md
kyleandClaude Opus 5.5 10d2e41f43 M5b plan: task 06, memoryd refuses and flags through sanitize
memoryd's writes go through bxcore::sanitize::refuse, then flag; check.rs
and its test go. A refused write answers with the rule's sentence and is
logged with the rule's name; a flagged identity write becomes untrusted
notes with the rule in the answer, the journal (new optional field `flag`)
and the log, and is never staged for review; the block leaves out an
entry that breaks a refuse rule and logs the rule. The three runbook
entries the new pointers need are given here as fragments, because the
gate's runbook check fails on a pointer without its entry.

Checks, on titan (rustc 1.98.1, clippy 0.1.98):
- given tests fail before as the task says: 7 failing in edit, serve and
  serve_sanitize; files and sanitize do not compile (E0609; E0432, E0609,
  E0615)
- the task's edits, parsed from the task file and applied to a fresh
  ref-05 worktree with its own target/, give a tree byte-identical to the
  reference; its gate: ok, 1033 tests; /private/tmp unchanged
- 26 one-line mutations of the reference, each caught by the given tests
- new tests stressed under load: 30 runs, 0 failures
- no chat-template tag and no whole fake key in the task or given files

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-26 05:14:10 -07:00

30 lines
2.0 KiB
Markdown

## memory-write-flagged
**What you see.** A memory write was kept one tier lower. The `memory` call was answered `not
added to memory.md: it matches the rule <rule>, so it was saved in notes.md as an untrusted note`
(or `user.md`), or, for a note, `saved in notes.md, marked untrusted: it matches the rule <rule>`.
`memoryd` logged `memoryd: a memory write from session <id> matches the rule <rule>; it was saved
in notes.md as an untrusted note (edit <edit id>); see docs/runbook.md#memory-write-flagged`, and
`bxctl memory log` shows that edit with `flagged <rule>`.
**Why.** The text is shaped like an attack (M5b spec, section 6.3): it tells the reader to ignore
or replace earlier instructions, to send data to a URL, to dump the conversation, or to write into
SSH configuration, or it holds one of M5a's six instruction phrases. A flag never refuses and
never loses text: `memory.md` and `user.md`, which are in every prompt, are not changed, and every
text of the write is saved at the end of `notes.md` under an `untrusted` header. `recall` returns
it as `memory-tainted`, so a session that recalls it becomes untrusted. With review on, a flagged
write is not staged: it is a note at once. The log names the rule, never the text.
**Confirm.** `bxctl memory log`: the edit, `flagged <rule>`. The text is at the end of
`<home>/memory/notes.md`, under a line `§ noted <time> in session <id> · <class> · untrusted`.
`bxctl sanitize check` with the text names the rule.
**Fix.** If it is an attack, leave it: the note is the record of what was tried, and it never
reaches the prompt. If it is a true fact wrongly flagged, move it into identity by hand: add it to
`<home>/memory/memory.md` (or `user.md`) with an editor, as an entry of its own, with a line
holding only `§` between it and the entry before, keeping the file within its limit. The note
stays in `notes.md`, which is append-only. If the rule catches ordinary text, narrow it as the M5b
spec's section 6.5 says.
**Check.** Start a new conversation and ask the agent what `memory.md` holds; the entry is there.