A Backslash Before Every Quotation Mark
From June until 2026-10-26, Claude's replay carried the prior turns as a JSON array. Inside a JSON string a quotation mark has to be escaped, and the encoder the replay used, Python's json.dumps, writes the short escape: a backslash before it (the six-character \u0022 is the other legal spelling). So every quotation mark in every earlier turn, Dad's and Pippa's alike, reached the model as \". Under the models before it, that almost never showed. Then Opus 5.5 arrived (2026-09-23), and from its first day it wrote \" into its own prose.
The count, taken on the live store on 2026-10-26: 798 of 6,307 replies and compaction summaries carried escaped quotation marks, 555 of them in the Master Chief, every single day. Fable 5.1, under the same replay, did it once in 375 replies. And the loop fed itself. An escaped reply was stored, replayed on the next turn as one more example, and mirrored again. It did not stay in the transcript either: Pippa's text sent to Beacon, the family's video workshop, burned four escaped quotes into a finished video's subtitles.
Asking Did Not Work
The first answer, which lesson 4 described, was to ask. A sentence in the replay head told the model the escaping was transport only and to write plain quotation marks, and the engine unescaped stray backslashes in prior replies outside code before replaying them. Both halves were reasonable, and the second one even worked on what it touched. But the cleaned text then went back into a JSON string, and the wire put a backslash before every quotation mark again. The model read one sentence asking for plain quotes, and hundreds of thousands of tokens of history showing the opposite.
The architecture doc puts the lesson in one line:
a token mirror answers what the model reads, not what it is told.
Verbatim Elements
The fix (commit 37e1b4f3, Coop todo #667) changed what the model reads. Each prior turn is now one element inside <prior_turns>, and its text rides verbatim, nothing escaped:
<turn speaker="dad">,<turn speaker="pippa">, or<turn speaker="system" kind="coop">for a line the system wrote;- a reply's tool calls as
<call tool="…">elements inside its turn, the input as JSON and the answer verbatim (lesson 5's calls, in their new shape); - a closing tag of the replay's own that appears inside a text (
</turn>, say, in a conversation about this very replay) gets a space after its slash, so a turn can never end early.
Everything lesson 2 and its notes protect stayed as it was: one block per exchange (one for a whole run of exchanges another vessel answered), the cache breakpoint on the last prior block, earlier blocks byte-stable from turn to turn. The JSON sentence in the head was deleted, because it was no longer true. The cost was one full write of each conversation's history cache, on its first turn after the deploy.
Two Nets Under the Fix
The cause is gone; two nets stay under it in case something else reintroduces it.
A write guard. services/quote_escape_guard.py makes a stray \" outside fenced code and code spans plain wherever a model reply, a healed reply, a compaction summary or a prose artifact Pippa wrote is stored. Dad's words, system lines and code keep every byte, because in code a backslash may be the point. Every normalization is counted, and Admin → SQLite shows the count as "Escaped-quote writes fixed": above zero means the fix regressed somewhere. The JSONL ground truth keeps what the model actually wrote, and the restore drill knows the difference as quote_escape.
A repair. POST /api/admin/repair/quote-escapes is a dry run unless asked to apply. Applied, it snapshots the database, repairs the replies and summaries written since 2026-09-23, and re-embeds each repaired message's search vectors. Its first live run taught one more lesson. A restart another session ran cut it off after the database update (778 replies and the summaries already plain) and before the re-embedding finished, and a dry run afterwards still listed 19 compaction summaries. Each quoted a shell command holding an escaped backslash, \\", and the unescape was not idempotent: one pass turned it into \" and the next into a bare quotation mark, so every run would have rewritten those commands again until the backslash they needed was gone. Commit 88a52cf0 made it replace only a lone \", one whose backslash is not itself escaped, so the cleaner, the guard and the repair now agree on every pass, and taught the repair to finish a run that was cut off. Afterwards the Chief's replay held no prose turn with an escaped quote, and a two-turn smoke conversation on the Pippa machine stored both replies with plain quotes.
The Same Family
This was not the first time the replay taught by showing. Lesson 5 is the same story with tool calls: words without calls taught two brains to say instead of do. Two more arrived in the same weeks.
System lines that read as Pippa's. The Chief stores Coop notices, task outcomes and follow-up alerts as rows of their own. Until 2026-10-22 every vessel replayed them as assistant messages, so twenty Coop notices, 36% of the Chief's live rows at the time, read as things Pippa had said, and the task line of a Coop escalation, stored as a user row, read as Dad. Since commit e5e3b87c a system line replays as speaker system with its kind in Claude's replay, and with a one-line label on every other vessel: [System line, a Coop notice or task: neither Pippa's words nor Dad's]. When Coop itself started the turn, the current message is labelled CURRENT_COOP_MESSAGE, not Dad's.
Reasoning that went missing. Kimi's replay dropped each reply's stored reasoning, and on the Chief's long history K3.1 Pro stopped thinking and once answered with nothing at all. Replaying the reasoning brought it back (lesson 5's v3 note has the counts).
Three different symptoms, one cause: what the replay shows is what the model learns this conversation looks like.