From cff3cb6dcd18edd96f55203457d28cdb5d710970 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Thu, 23 Jul 2026 20:52:40 +0800 Subject: [PATCH] docs(i18n): refresh persistence Agent Notes --- ...-06-18-shared-persistence-write-coordinator.i18n.yaml | 4 ++-- ...2026-06-18-shared-persistence-write-coordinator.zh.md | 9 ++++----- .../2026-06-20-prune-dead-seam-methods.i18n.yaml | 4 ++-- .../2026-06-20-prune-dead-seam-methods.zh.md | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml b/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml index 8d572c486f..3e805481ad 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.i18n.yaml @@ -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 -2026-06-18-shared-persistence-write-coordinator.md: 12800b118bd2fd1189319d0edf37cace3d916a9c -2026-06-18-shared-persistence-write-coordinator.zh.md: 23d6c66989880369c4e26c38145559c198ea1033 +2026-06-18-shared-persistence-write-coordinator.md: 2349c50735045ae99e70bb5594b69f4252994b91 +2026-06-18-shared-persistence-write-coordinator.zh.md: c68cbd984197bf68415d1f2bb68f297f51548bc3 diff --git a/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.zh.md b/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.zh.md index 23d6c66989..c68cbd9841 100644 --- a/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.zh.md +++ b/.agents/notes/implemented/architecture/2026-06-18-shared-persistence-write-coordinator.zh.md @@ -18,11 +18,10 @@ Status: implemented ### 钩子接口(`PersistenceBackend`) -六个方法(五个必需 + 一个可选的生命周期钩子)——协调器与存储之间唯一的 seam: +五个必需成员加一个可选的生命周期钩子,构成协调器与存储之间唯一的边界: - `name`——后端标签,用于 dispose 失败时的 `AggregateError`。 -- `loadStored(id)`——按 id 读取已存储的前缀,扫描任何存储范围(JSONL 的每个 cwd bucket;SQLite 的 id 全局唯一)。用于恢复/加载,以及通过 `!== undefined` 进行创建碰撞探测。 -- `loadLive(id, cwd)`——读取限定于 `cwd` 的已存储前缀。**与 `loadStored` 有意区分**:HMR live-adoption 只能接管与存活会话处于同一 cwd 的持久化日志;同 id 但不同 cwd 的日志是碰撞而非恢复。合并二者会重新引入跨 cwd 接管 bug。SQLite 忽略 `cwd`。 +- `loadStored(id)`——按 id 跨所有存储范围读取一个已存储前缀(JSONL 的所有 cwd bucket;SQLite 的 id 全局唯一)。恢复/加载、存活会话接管与创建碰撞探测共用此查找。协调器会断言返回的 id,并在修复或发布状态之前拒绝已存储记录与存活会话的 cwd 不匹配。 - `appendBatch(meta, events, isMaterialized)`——持久追加一个连续批次,在尚未物化时原子地惰性物化会话(物化写入与首批事件必须一起提交——崩溃不得留下一个已物化但为空的会话;这就是为什么没有单独的 `materialize` 钩子)。 - `commitRepair(meta, tornMarker, closers)`——使崩溃修复持久化:截断损坏的尾部(当且仅当 `tornMarker !== undefined`)并追加 `closers`。**不要求原子性**——JSONL 合理地分两步 fsync(先截断再追加),SQLite 在一个事务中完成 DELETE+INSERT。用于 `load`(截断 + 合成 closers)和 live-adoption(仅截断,`closers = []`)。 - `list()`——列出所有已存储的元数据。 @@ -39,8 +38,8 @@ Status: implemented ## 曾考虑的替代方案 - **后端继承的基类**——否决,改用组合:后端只暴露钩子,无法触及协调器的私有编排状态,且第三方后端仍可完全不使用协调器、直接实现抽象服务。 -- **更宽的钩子面**——每个候选钩子都被折叠掉:没有单独的 `materialize` 钩子(物化写入必须在 `appendBatch` 内与首批事件原子提交);没有单独的创建碰撞探测(即 `loadStored(id) !== undefined`);`list()` 也不经由协调器透传(列举不需要任何编排)。 +- **更宽的钩子面**——每个候选钩子都被折叠掉:没有限定存储范围的实时查找,因为 `loadStored` 加上协调器的 cwd 检查即可维持碰撞边界;没有存储定位器泛型,因为经验证的 JSONL 元数据可还原其路径,而 SQLite 已按 id 绑定;没有单独的 `materialize` 钩子,因为首批事件必须与物化原子提交;没有单独的创建碰撞探测,因为它就是 `loadStored(id) !== undefined`;`list()` 也不经由协调器透传,因为列举不需要任何编排。 ## 后果 -协调器增加了一层间接、一个不透明的 torn marker 和脱离会话生命周期的退役任务,但将此前每个后端重复的、对正确性要求很高的编排逻辑集中到一处。会话 dispose 仍是仅观察事件,因此会话所有者不会等待持久化退役;协调器会收容失败、保留未提交的缓冲区,并以后端 teardown 为静止状态边界。其钩子面保持窄小:碰撞检查复用 `loadStored`,物化保持在 `appendBatch` 内原子完成,列举绕过协调器。新后端只需实现存储原语,而无需复制事件-缓冲区-flush 生命周期。 +协调器增加了一层间接、一个不透明的 torn marker 和脱离会话生命周期的退役任务,但将此前每个后端重复的、对正确性要求很高的编排逻辑集中到一处。会话 dispose 仍是仅观察事件,因此会话所有者不会等待持久化退役;协调器会收容失败、保留未提交的缓冲区,并以后端 teardown 为静止状态边界。其钩子面保持窄小:标识校验、接管与碰撞检查复用 `loadStored`;物化保持在 `appendBatch` 内原子完成;列举绕过协调器。新后端只需实现存储原语,而无需复制事件-缓冲区-flush 生命周期。 diff --git a/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.i18n.yaml b/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.i18n.yaml index 91b82dcd75..bcca5a0490 100644 --- a/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.i18n.yaml +++ b/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.i18n.yaml @@ -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 -2026-06-20-prune-dead-seam-methods.md: bb91194ed0483ca4c43acdde8370e7152ac876ea -2026-06-20-prune-dead-seam-methods.zh.md: f441ac0d91b4f673cbbbd4148c9183cc1185a54f +2026-06-20-prune-dead-seam-methods.md: 70596d908bb1d7559e876d93bce0e25874ce1ff0 +2026-06-20-prune-dead-seam-methods.zh.md: 0953eaa57dc9b490a7399a412338fc21a06a0ad2 diff --git a/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.zh.md b/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.zh.md index f441ac0d91..0953eaa57d 100644 --- a/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.zh.md +++ b/.agents/notes/implemented/simplification/2026-06-20-prune-dead-seam-methods.zh.md @@ -14,7 +14,7 @@ Status: implemented 该抽象服务在 create/append 之外声明了更多操作:`load`、`list`、`has`、`delete`。`ctx.sessionPersistence` 的生产消费方只用了两个:agent loop(智能体循环)的恢复路径调用 `load()`([packages/core/agent-loop/src/index.ts:176](../../../../packages/core/agent-loop/src/index.ts)),ACP(Agent Client Protocol)桥接层为 `session/list` 调用 `list()`([packages/ui/acp/src/index.ts:494](../../../../packages/ui/acp/src/index.ts))。在 `packages/*/src` 和 `examples/` 中 grep 所有 `sessionPersistence.*` / `persistence.*` 的使用,找不到对该服务的 `has(` 或 `delete(` 调用。`packages/ui/acp/src/index.ts` 中的 `.has(`/`.delete(` 调用作用于内存中的 `SessionStore` 和一个本地的 loading id `Set`,而非 persistence。`has`/`delete` 的唯一调用者是契约测试套件和各后端的 spec。 -`has()` 不仅没有被使用——它还是共享协调器中最复杂的分支:带有多行理由说明的“已跟踪/未跟踪”双重探测(对实时跟踪的 session 使用 `loadLive(id, cwd)`,对未跟踪 session 使用 `loadStored(id)`)。`delete()` 则拖入每个后端都必须实现的 `deleteStored` 后端 hook。这属于[删除可变 session summary](2026-06-19-drop-mutable-session-summary.md) 的同类模式:契约测试覆盖了两者,但已发布代码从不会询问“这个 session 是否已持久化?”或删除某个 session。 +`has()` 不仅未被使用:在 `loadStored(id)` 已负责持久化存在性检查的情况下,它仍增加了协调器的已跟踪/未跟踪探测和一个契约分支。`delete()` 则拖入每个后端都必须实现的 `deleteStored` 后端 hook。这属于[删除可变 session summary](2026-06-19-drop-mutable-session-summary.md) 的同类模式:契约测试覆盖了两者,但已发布代码从不会询问“这个 session 是否已持久化?”或删除某个 session。 ## 决策