fix(session-query): qualify persistence revisions by store

This commit is contained in:
Hypatia May
2026-07-15 12:32:18 +08:00
parent f88ca85ffd
commit 35edf2a825
13 changed files with 192 additions and 31 deletions
@@ -12,7 +12,7 @@ The persisted unit IS the existing `SessionEvent` (event-sourced model — the l
| `append(id, events): Promise<void>` | Durably persist a batch (from the `session/flush` drain). Append-only; first event `seq` == stored next-seq after any repair; rejects non-JSON-serializable data naming the offending type. |
| `load(id): Promise<{ meta; events }>` | Reload meta + log. Preserves an interrupted (unclosed) final turn and closes it with synthetic closers — an error `tool/result` per unanswered `tool-call`, then `step/end?`+`turn/end {interrupted}` (a turn can be huge — never truncated); only a torn tail fragment is dropped. Events contiguous (`events[i].seq === i`); rejects a committed-region gap/parse error or unknown `version`. |
| `list(): Promise<SessionHeader[]>` | Lightweight listing from metadata, no full-log parse. A zero-event lazily-materialized session is absent from `list`. |
| `listSnapshots(): Promise<SessionPersistenceSnapshot[]>` | Lightweight metadata plus an opaque branded per-log revision, without loading event logs. A revision stays equal while that log is unchanged and changes after append or mutating load repair. |
| `listSnapshots(): Promise<SessionPersistenceSnapshot[]>` | Lightweight metadata plus an opaque branded per-log revision, without loading event logs. A revision stays equal while that log and its backing store are unchanged, changes after append or mutating load repair, and cannot collide solely because two stores use the same local counter. |
## Invariants every backend must honor
@@ -34,7 +34,7 @@ export { SessionPersistenceRevision } from './revision.ts'
export interface SessionPersistenceSnapshot {
/** Detached metadata for one materialized session. */
header: SessionHeader
/** Opaque token that changes whenever this stored log changes. */
/** Opaque source-qualified token that changes whenever this stored log changes. */
revision: SessionPersistenceRevision
}
@@ -172,6 +172,8 @@ export abstract class SessionPersistence extends Service {
*
* Repeated observations of an unchanged log return the same revision. A
* successful mutating {@link load} repair changes the next listed revision.
* Revisions also distinguish independently backed stores so backend-local
* counters cannot compare equal across different persistence sources.
* @returns one header and opaque revision per materialized session without loading full logs.
*/
abstract listSnapshots(): Promise<SessionPersistenceSnapshot[]>
@@ -2,7 +2,10 @@
import type { Branded } from '@deepseek-ai/dsh-brand'
/** Backend-owned token that changes whenever one persisted session log changes. */
/**
* Backend-owned token that identifies both one storage source and one revision
* of a persisted session log.
*/
export type SessionPersistenceRevision = Branded<'SessionPersistenceRevision'>
/**