From 035cebc97bedc99c2e2106ca4374f73a66a7716d Mon Sep 17 00:00:00 2001 From: "denizirgin@gmail.com" Date: Tue, 8 Sep 2026 01:17:19 +0300 Subject: [PATCH] docs: state what the durable session log actually replays and retains The SSE rules hedged persistence, retention, and replay together as unestablished. Replay mechanics were in fact established by the live coverage that lands with this pin, and retention is established by reading the server: the canon now says both, and hedges only what remains unpinned. Canon carries the mechanics the suite proves. The cursor is an exclusive aggregate sequence; one log.synced marker reports the watermark the replay was captured at, and it is a boundary rather than a durable event, so under follow the events committed while that replay was in flight arrive after it. Sequences are not contiguous, because the server omits types outside its durable manifest, the session union filters further, and a forked session reserves an inherited prefix. A cursor past the tail is accepted rather than refused and then suppresses live delivery until the aggregate overtakes it, so a cursor travels only within one server's lifetime. Canon also carries retention, which turns out to be the absence of a policy: nothing expires, prunes, or caps the log, compaction and revert rewrite projections rather than the log itself, and rows are deleted only with their session. Persistence is a server option that is off unless the server was started with it, which is why a default server answers a replay with the marker alone. The roadmap's open question narrows to the wire behaviour nothing upstream pins: that route has no server-level test there, and upstream has no production caller that passes after at all, so the status a malformed cursor answers and the fate of an idle follow connection are settled only here. The vocabulary entry and the streaming guide follow the same correction. --- CONTEXT.md | 3 ++- docs/ROADMAP.md | 6 +++++- docs/architecture/client-runtime.md | 16 +++++++++++++--- docs/guide/streaming.md | 10 ++++++---- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index 0a9e9dce5..4dc786b81 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -52,7 +52,8 @@ Session; others aggregate elsewhere, such as worktree resolution on its Project. **Durable Session event stream**: One Session Aggregate's durable Event log, read back over SSE. `after` is an exclusive sequence taken from a durable envelope or a sync marker, `follow` continues into live Events, and a single -`log.synced` marker separates replay from live. Retention remains unestablished. +`log.synced` marker separates replay from live. The sequence is not contiguous, the log has no +retention policy, and persistence is a server option that is off by default. _Avoid_: session events (ambiguous with the live stream) **Live event stream**: diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 662f22d12..d2dc51893 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -70,7 +70,11 @@ is revisited at each boundary. The pin therefore stays a deliberate snapshot, refreshed under receipt at milestone boundaries. - **`v2.session.log` resume guarantees** — the pinned document exposes `after` as an optional string, and the generated surface stays faithful to it; ADR-0013 forbids importing the narrower - type upstream's implementation decodes. Retention and replay guarantees are unestablished. + type upstream's implementation decodes. Replay mechanics and retention are established and + carried by canon. What stays open is the wire behaviour nothing upstream pins: no server-level + test covers this route, so the status a malformed `after` answers, and whether an idle `follow` + connection survives an intermediary, are settled only by this repository's own live tests. + Upstream has no production caller that passes `after`, so this SDK is the path's first consumer. - **OpenAPI projection fidelity** — the pinned document loses detail upstream's implementation carries. Confirmed losses are reported upstream ([anomalyco/opencode#44911](https://github.com/anomalyco/opencode/issues/44911), restored by the diff --git a/docs/architecture/client-runtime.md b/docs/architecture/client-runtime.md index 9572f4aee..fd7ead99d 100644 --- a/docs/architecture/client-runtime.md +++ b/docs/architecture/client-runtime.md @@ -270,9 +270,19 @@ local server launcher. Protocol and generated-model rules live in disposes the live response so cancellation interrupts platform response-stream reads that do not observe an async read token; disposal-induced I/O failures remain caller cancellation. - The SDK never auto-reconnects. A live-stream consumer refreshes authoritative state and - resubscribes after failure. Durable continuation is requested explicitly through - `v2.session.log`'s `after` parameter; persistence, retention, and replay guarantees remain - unestablished (research doc 02, `docs/ROADMAP.md`). + resubscribes after failure. +- Durable continuation is requested explicitly through `v2.session.log`'s `after` parameter, an + exclusive aggregate sequence read from a durable envelope or from the sync marker. One + `log.synced` marker reports the watermark the replay was captured at; it is a boundary rather + than a durable event, and under `follow` the events committed while that replay was in flight + arrive after it. Sequences are not contiguous, so a gap is ordinary and no count is derived from + two of them. A cursor past the aggregate's tail is accepted rather than refused and then + suppresses live delivery until the aggregate overtakes it, so a cursor travels only within one + server's lifetime. +- That log has no retention policy: nothing expires, prunes, or caps it, compaction and revert + rewrite projections rather than the log, and rows are deleted only with their session. + Persistence is itself a server option that is off unless the server was started with it, so a + default server answers a replay with the marker alone (`docs/ROADMAP.md`). - The SSE event name is a framing signal. An ordinary payload uses the default `message` name; the operation's declared failure event materializes its cause through generated metadata and throws; any other explicit name is refused. Unknown payload and cause discriminators remain diff --git a/docs/guide/streaming.md b/docs/guide/streaming.md index d13825ef4..22d2c3ca3 100644 --- a/docs/guide/streaming.md +++ b/docs/guide/streaming.md @@ -93,10 +93,12 @@ With `Follow = True`, read through any replayed events until that marker arrives then delivers live events committed after the attachment boundary. The marker is a transition boundary, not a durable event to save as the next `After` value. -> **📎 A note on guarantees**: `after` is a *request*, not a durability promise. How much history -> the server persists or retains, and for how long, is upstream's business and is not something -> this SDK can state on its behalf. The stream does not promise replay after a server restart. -> Treat a returned gap as possible and reconcile with ordinary reads. See the canonical +> **📎 A note on guarantees**: replay depends on the server. Persistence is a server option that is +> off unless the server was started with it, so a default server answers with the marker alone. +> When it is on, nothing expires or prunes the log and entries live until their session is deleted. +> Sequences are not contiguous, so treat a gap as ordinary rather than as loss. Carry a cursor only +> within one server's lifetime: a cursor past the log's tail is accepted rather than refused and +> then suppresses live delivery until the log overtakes it. See the canonical > [server-sent events rules](../architecture/client-runtime.md#server-sent-events). ## 🧩 Unknown events do not break your consumer