fix(session-persistence): address preparation review feedback

This commit is contained in:
imccyu
2026-08-06 02:53:48 +08:00
parent 466390c1af
commit feb2c35cef
35 changed files with 364 additions and 124 deletions

View File

@@ -1199,14 +1199,17 @@ async prepare(id: SessionId, signal?: AbortSignal): Promise<SessionPreparation>
abstract load(id: SessionId): Promise<SessionInspection>
/**
* Inspect an immutable balanced logical session without committing recovery
* or publishing it. A complete interrupted turn receives synthetic closers
* in memory and a torn physical tail remains untouched. Coordinator-backed
* implementations retain the exact unpublished Session for bounded reuse by
* a later {@link prepare}; callers borrow only its immutable header and log.
* Inspect an immutable logical session without committing recovery or
* publishing it. A cold complete interrupted turn receives synthetic closers
* in memory and a torn physical tail remains untouched. An already-live
* Session instead yields its current immutable snapshot, which may contain an
* open turn and its `session/end-seed` boundary. Coordinator-backed
* implementations retain the exact cold unpublished Session for bounded
* reuse by a later {@link prepare}; callers borrow only its immutable header
* and log.
* @param id - the persisted session to inspect.
* @param signal - optional cancellation for queued and backend read work.
* @returns the validated header and balanced logical event log.
* @returns the validated header and current logical event log.
*/
abstract inspect(id: SessionId, signal?: AbortSignal): Promise<SessionInspection>
@@ -1252,7 +1255,7 @@ abstract listSnapshots(signal?: AbortSignal): Promise<SessionPersistenceSnapshot
Types: [SessionEvent](../core-data-structures/core.md) · [SessionHeader](../core-data-structures/persistence.md) · [SessionId](../core-data-structures/core.md) · [SessionInspection](../core-data-structures/persistence.md) · [SessionLocation](../core-data-structures/persistence.md) · [SessionPersistenceSnapshot](../core-data-structures/persistence.md) · [SessionPreparation](../core-data-structures/persistence.md)
Source: [`packages/session-persistence/session-persistence/src/index.ts:66`](../../packages/session-persistence/session-persistence/src/index.ts)
Source: [`packages/session-persistence/session-persistence/src/index.ts:70`](../../packages/session-persistence/session-persistence/src/index.ts)
## `ctx.sessionProjectionCache` — `SessionProjectionCache`
@@ -1589,7 +1592,11 @@ Persistence is intentionally not implemented here — persistence plugins subscr
* `dsh-agent-loop`'s creation transaction).
*
* @param id - the session id; omitted, the store mints `session-<n>`.
* @param options - seed events and/or creation metadata for the header.
* @param options - seed events and/or creation metadata for the header. With
* `seedSource: 'persistence'`, metadata and events must be fresh detached
* graphs whose ownership transfers to this call: they are validated and
* frozen in place through {@link Session.fromRestore}, so the caller must
* retain no mutable aliases.
* @returns the live session, already entered and announced.
* @throws if a session with `id` already exists, metadata is not a plain
* lossless-JSON record with valid scalar fields, or `meta.cwd` is a

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/core-data-structures/persistence.md
persistence.md: 4b4b1ed0c0809bb277cd0118bb14f893faa4d821
persistence.zh.md: 226dbd03c514d2c76838d7ee64ecc699a7852cba
persistence.md: 0968496201defa869d94925e8e5ae3c5da1bbd37
persistence.zh.md: efb01427b4355e531fb9b86922223cf27d3b3db0

View File

@@ -16,7 +16,7 @@ A backend that reloads a log crashed mid-turn finds an open `turn/start` with no
Repair applies only to cold sessions. For a live id, `SessionPersistence.load(id)` waits until the authoritative in-memory snapshot is durable and returns it only when balanced; an open live turn rejects rather than receiving synthetic interruption boundaries. HMR adopts a live prefix without closing its active turn.
`SessionPersistence.inspect(id)` constructs an immutable balanced logical Session without publishing it or writing recovery. Torn physical tails remain untouched, and synthetic interruption closers exist only in memory. Coordinator-backed implementations retain that exact unpublished Session in a bounded LRU, so repeated history reads and a later `prepare(id)` share one read, decompression, validation, freeze, and Session construction. `prepare(id)` reserves the Session, commits pending repair, and returns a disposable publication handle; `load(id)` uses the same machinery to commit repair without publication. The [Session preparation decision](../../.agents/notes/implemented/architecture/2026-08-05-session-preparation.md) owns this lifecycle.
`SessionPersistence.inspect(id)` constructs an immutable logical Session without publishing it or writing recovery. Cold inspection balances an interrupted turn in memory while leaving torn physical tails untouched; inspection of an already-live Session borrows its current immutable snapshot and may therefore contain an open turn. Coordinator-backed implementations retain the exact cold unpublished Session in a bounded LRU, so repeated history reads and a later `prepare(id)` share one read, decompression, validation, freeze, and Session construction. `prepare(id)` reserves the Session, commits pending repair, and returns a disposable publication handle; `load(id)` uses the same machinery to commit repair without publication. The [Session preparation decision](../../.agents/notes/implemented/architecture/2026-08-05-session-preparation.md) owns this lifecycle.
## `SessionLocation` — optional per-session artifact target

View File

@@ -16,7 +16,7 @@
修复仅适用于冷会话。对于活跃 id`SessionPersistence.load(id)` 会等待权威内存快照完成持久化并且只在日志平衡时返回若活跃轮次仍未闭合则拒绝操作而不是添加合成的中断边界。HMR 会接管活跃前缀,而不会关闭其中正在进行的轮次。
`SessionPersistence.inspect(id)` 会构造一个不可变且已配平的逻辑 Session但不发布它也不写入恢复内容。撕裂的物理尾部保持不变,合成的中断 closer 只存在于内存中。使用协调器的实现会在有界 LRU 中保留这个精确的未发布 Session因此重复历史读取与后续 `prepare(id)` 可复用同一次读取、解压、验证、冻结及 Session 构造。`prepare(id)` 会预留该 Session、提交待处理修复并返回可 dispose 的发布句柄;`load(id)` 使用相同机制提交修复,但不会发布 Session。该生命周期由 [Session 准备阶段决策](../../.agents/notes/implemented/architecture/2026-08-05-session-preparation.md)定义。
`SessionPersistence.inspect(id)` 会构造一个不可变的逻辑 Session但不发布它也不写入恢复内容。冷检查会在内存中配平中断的 turn同时保持撕裂的物理尾部不变检查已经实时存在的 Session 则借用其当前不可变快照,因此可能包含打开的 turn。使用协调器的实现会在有界 LRU 中保留这个精确的未发布 Session因此重复历史读取与后续 `prepare(id)` 可复用同一次读取、解压、验证、冻结及 Session 构造。`prepare(id)` 会预留该 Session、提交待处理修复并返回可 dispose 的发布句柄;`load(id)` 使用相同机制提交修复,但不会发布 Session。该生命周期由 [Session 准备阶段决策](../../.agents/notes/implemented/architecture/2026-08-05-session-preparation.md)定义。
## `SessionLocation`——可选的逐会话产物目标

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/core-data-structures/session-query.md
session-query.md: d92af4bac34f7d41457e9e193111c3a53fe8022e
session-query.zh.md: 8070dfda61a2945fca554939f65ae0f8b85078db
session-query.md: e7514dd6c3bc20a07395663bff40ce65e1363b78
session-query.zh.md: 4c3dd4d435dbd8a20fbd4db5da1a7d649c2e6d0b

View File

@@ -338,6 +338,7 @@ The closed code union distinguishes request validation, missing targets, malform
/** Stable machine-routable failure taxonomy for session reads, traces, and search. */
type SessionQueryErrorCode =
| 'SESSION_QUERY_ABORTED'
| 'SESSION_QUERY_CORRUPT_SESSION'
| 'SESSION_QUERY_EVENT_NOT_FOUND'
| 'SESSION_QUERY_INDEX_FAILED'
| 'SESSION_QUERY_INVALID_CONFIG'

View File

@@ -338,6 +338,7 @@ interface SessionEventTraceObservation extends SessionEventTrace {
/** Stable machine-routable failure taxonomy for session reads, traces, and search. */
type SessionQueryErrorCode =
| 'SESSION_QUERY_ABORTED'
| 'SESSION_QUERY_CORRUPT_SESSION'
| 'SESSION_QUERY_EVENT_NOT_FOUND'
| 'SESSION_QUERY_INDEX_FAILED'
| 'SESSION_QUERY_INVALID_CONFIG'