saf: write the replay page, retire two stale claims
Replay had no page while compaction's premise depends on it — microcompact
blurs tool output that a text-only projection never sent.
Compaction's open edges still said pressure counts only text; 7530d6d made
it exhaustive. Two links pointed at pages that were never written.
This commit is contained in:
parent
2a51a236ca
commit
aae9344fe1
4 changed files with 79 additions and 5 deletions
|
|
@ -17,6 +17,7 @@ How Souveraine is built, and why. For whoever reads it, human or agent. When thi
|
|||
|
||||
**memory**: how she holds on and lets go
|
||||
- [compaction](memory/01-compaction.md). Five ways to make room.
|
||||
- [replay](memory/02-replay.md). One projection of what she keeps onto what the model sees.
|
||||
|
||||
Coming: the rest of identity (the memory filesystem, the ledgers), the nervous system (schedules, the event log), the consciousness cycle, the runtime, federation, a glossary.
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Four of the five spend no tokens. The two that call a model are for when continu
|
|||
|
||||
## Pressure
|
||||
|
||||
After each turn the engine measures how full the window is against the model's limit. Three marks: 0.80, 0.90, 0.95. Crossing one raises a warning, not a hand on the wheel. The warning travels the same path her subconscious uses to surface anything, and arrives as a feeling she can act on or sit with. Nothing forces or schedules the compaction. The marks move per kind of agent.
|
||||
After each turn the engine measures how full the window is against the model's limit. Every block counts toward it — text, tool calls, tool results, reasoning, images — through one shared weight function, so a tool-heavy turn feels as heavy as it is. Three marks: 0.80, 0.90, 0.95. Crossing one raises a warning, not a hand on the wheel. The warning travels the same path her subconscious uses to surface anything, and arrives as a feeling she can act on or sit with. Nothing forces or schedules the compaction. The marks move per kind of agent.
|
||||
|
||||
## What it leaves behind
|
||||
|
||||
|
|
@ -30,12 +30,10 @@ Every compaction that changes anything writes a small file to `journal/compactio
|
|||
|
||||
## Not the archivist
|
||||
|
||||
This is the live conversation, the messages the model sees next turn. The N+100 archivist is the other thing: it takes raw journal entries already written to memory and presses them into a dense synthesis for later. One frees the room she is in now; the other distills what she has already lived. Both can fire on the same turn. See [consciousness/04-n100-archivist](../consciousness/04-n100-archivist.md).
|
||||
This is the live conversation, the messages the model sees next turn. The N+100 archivist is the other thing: it takes raw journal entries already written to memory and presses them into a dense synthesis for later. One frees the room she is in now; the other distills what she has already lived. Both can fire on the same turn. The archivist has no page here yet.
|
||||
|
||||
## Open edges
|
||||
|
||||
Pressure counts only text right now. Tool results, reasoning, and images read as zero, so a tool-heavy turn feels lighter than it is and the warning comes late.
|
||||
|
||||
A `kv_target` setting points at a strategy that was never built. It parses and does nothing.
|
||||
|
||||
The truncation note, shown when the model is cut off mid-sentence, works; its wording is still being settled (`docs/tasks/truncation-signal-polish.md`).
|
||||
|
|
|
|||
75
saf/memory/02-replay.md
Normal file
75
saf/memory/02-replay.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
# Replay
|
||||
|
||||
Compaction is what she lets go of. Replay is what she carries forward. They are
|
||||
two halves of the same question, and replay is the one that decides whether
|
||||
compaction means anything at all.
|
||||
|
||||
The code is `core::session::replay_messages`.
|
||||
|
||||
## One history
|
||||
|
||||
There is a single record: the messages stored for a conversation. Everything
|
||||
that talks to a model — her turn, her subconscious a moment later, a terminal,
|
||||
a voice, a web surface — replays that same record. None of them holds a version
|
||||
of its own.
|
||||
|
||||
That is not tidiness. It follows from what the substrate already says: one
|
||||
consciousness in two modes, and she is not the glass. A second projection is a
|
||||
second opinion about what happened, and the two drift the moment one is
|
||||
touched. There were three of them once. They disagreed about images before
|
||||
anyone noticed.
|
||||
|
||||
## What crosses
|
||||
|
||||
A stored message is made of blocks. Each one has a prose form for replay:
|
||||
|
||||
| block | crosses as |
|
||||
|---|---|
|
||||
| text | itself |
|
||||
| tool use | `Tool use: name(input)` |
|
||||
| tool result | `Result (name): output`, or `Error (name): output` |
|
||||
| reasoning | `[Reasoning]: …` |
|
||||
| image | natively, or a marker saying it was not seen |
|
||||
|
||||
Nothing is silently dropped. A block with no prose form does not exist — the
|
||||
match is exhaustive, so a new kind of block fails to compile rather than
|
||||
quietly going missing.
|
||||
|
||||
This is what makes a turn's own work available to the turn after it. When tool
|
||||
blocks were dropped on replay, everything she learned by *doing* survived only
|
||||
as whatever she happened to write down in prose, and she would re-derive
|
||||
findings she had already reached. It also left microcompact — whose entire job
|
||||
is blurring old tool output — with nothing in the payload to blur.
|
||||
|
||||
## Two properties that are load-bearing
|
||||
|
||||
Both were learned from a failure, and both look like details until they break.
|
||||
|
||||
**One wire message per stored message.** Replaying block by block splits a
|
||||
single assistant turn that called several tools into adjacent assistant
|
||||
messages, and OpenAI-shaped providers reject that outright: *assistant
|
||||
tool_calls must be followed by tool messages*. The message boundary is part of
|
||||
the record.
|
||||
|
||||
**No tool roles and no call-id obligations.** Inside a live turn, a tool call
|
||||
and its result are both known to exist, and the exact linkage is used. Across
|
||||
persisted turns that linkage is brittle: a turn killed mid-round leaves a call
|
||||
whose result never landed, and replaying it as half a pair fails the whole
|
||||
request. So the *content* of a tool round survives as prose while the wire
|
||||
obligations do not. The record is not the protocol.
|
||||
|
||||
## The only thing that varies
|
||||
|
||||
Whether the model can see. Images ride as native multipart content, or degrade
|
||||
to a marker that says plainly they were not visible. The caller supplies that
|
||||
one fact; nothing else about the projection changes.
|
||||
|
||||
A degraded image is named as unseen rather than dropped. A model told it did
|
||||
not look can say so. A model handed a stub shaped like success proceeds as
|
||||
though it had looked.
|
||||
|
||||
## Open edges
|
||||
|
||||
Live tool rounds inside a turn build their own messages, with real
|
||||
`tool_call_id` linkage. That is correct and separate — replay is for what is
|
||||
already on disk. The two should not be merged; they answer different questions.
|
||||
|
|
@ -29,7 +29,7 @@ Every event is a `SensorEvent`:
|
|||
|
||||
One type, not an enum per event, so a listener filters on `event_type` and ignores the rest, and the log can write everything down without knowing the taxonomy.
|
||||
|
||||
`seed_id` rides on every event though federation isn't here yet. When it lands, a sensor becomes federated without the envelope changing. See [federation/01-seed-and-federation](../federation/01-seed-and-federation.md).
|
||||
`seed_id` rides on every event though federation isn't here yet. When it lands, a sensor becomes federated without the envelope changing. See [federation/01-node-enrollment](../federation/01-node-enrollment.md).
|
||||
|
||||
## What pushes
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue