Merge remote-tracking branch 'origin/master' into xtr/react-loop-simplification

# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-content-block-vocabulary.zh.md
#	.agents/notes/implemented/architecture/2026-06-11-event-sourced-sessions.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-11-microkernel-event-taxonomy.zh.md
#	.agents/notes/implemented/architecture/2026-06-18-agent-lifecycle-and-ownership-seams.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-18-session-surface.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.zh.md
#	.agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-30-event-domain-semantics.zh.md
#	.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-05-reconstructable-requests.zh.md
#	.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-10-after-call-compaction-pressure-and-overflow-recovery.zh.md
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-10-single-file-executable-sdk-runtime-distribution.zh.md
#	.agents/notes/implemented/architecture/2026-07-14-provider-routed-llm-adapters.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-15-replay-token-meter-service.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-16-explicit-turn-cancellation.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-22-unified-send-and-coalesced-user-messages.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-22-unified-send-and-coalesced-user-messages.zh.md
#	.agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-24-separate-context-injection-from-turn-execution.zh.md
#	.agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-25-web-client-session-scope-and-provide-channel.zh.md
#	.agents/notes/implemented/architecture/2026-07-28-identified-immutable-message-values.i18n.yaml
#	.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.i18n.yaml
#	.agents/notes/implemented/bug-fix/2026-07-21-semantic-session-checkpoints.zh.md
#	.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md
#	.agents/notes/implemented/feature/2026-06-24-workspace-context.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-24-workspace-context.zh.md
#	.agents/notes/implemented/feature/2026-06-30-hook-bridges.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-hook-protocol-lib.zh.md
#	.agents/notes/implemented/feature/2026-06-30-interception-seams.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-interception-seams.zh.md
#	.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md
#	.agents/notes/implemented/feature/2026-07-16-durable-per-step-time-context.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-16-durable-per-step-time-context.zh.md
#	.agents/notes/implemented/feature/2026-07-16-harness-level-loop.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-16-harness-level-loop.zh.md
#	.agents/notes/implemented/feature/2026-07-19-human-goal-command.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.zh.md
#	.agents/notes/implemented/feature/2026-07-19-plugin-command-registration.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.zh.md
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-21-cross-session-references.zh.md
#	.agents/notes/implemented/feature/2026-07-27-tmux-location-context.i18n.yaml
#	.agents/notes/implemented/simplification/2026-06-20-public-agent-stop-surface.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-17-one-send-one-turn.zh.md
#	.agents/notes/implemented/simplification/2026-07-20-unwrap-injected-content-envelopes.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-22-plan-specific-collaboration-state.zh.md
#	.agents/notes/implemented/simplification/2026-07-24-agent-loop-observable-state-machine.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-27-request-error-retry-action.i18n.yaml
#	docs/core-data-structures/compaction.i18n.yaml
#	docs/core-data-structures/goal.i18n.yaml
#	docs/core-data-structures/goal.zh.md
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/session.i18n.yaml
#	docs/core-data-structures/session.zh.md
#	docs/core-data-structures/skills.i18n.yaml
#	docs/core-data-structures/skills.zh.md
#	docs/core-data-structures/system-prompt.i18n.yaml
#	docs/defensive-patterns.i18n.yaml
#	docs/defensive-patterns.zh.md
#	docs/user/develop/framework/events.i18n.yaml
#	docs/user/develop/framework/events.zh.md
#	packages/acp/acp/README.i18n.yaml
#	packages/client/ui-goal/README.i18n.yaml
#	packages/compact/compact-basic/README.i18n.yaml
#	packages/compact/compact/README.i18n.yaml
#	packages/context/time-context/README.i18n.yaml
#	packages/context/tmux-context/README.i18n.yaml
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent-loop/README.zh.md
#	packages/core/agent/README.i18n.yaml
#	packages/core/agent/README.zh.md
#	packages/core/session/README.i18n.yaml
#	packages/core/session/README.zh.md
#	packages/core/system-prompt/README.i18n.yaml
#	packages/core/system-prompt/README.zh.md
#	packages/examples/cli-demo/README.i18n.yaml
#	packages/goal/command-goal/README.i18n.yaml
#	packages/goal/goal-session/README.i18n.yaml
#	packages/goal/goal/README.i18n.yaml
#	packages/goal/tool-goal/README.i18n.yaml
#	packages/goal/tool-goal/README.zh.md
#	packages/guard/README.i18n.yaml
#	packages/guard/README.zh.md
#	packages/guard/repeat-tool-guard/README.i18n.yaml
#	packages/hooks/hooks-claude/README.i18n.yaml
#	packages/hooks/hooks-codex/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/README.zh.md
#	packages/llm/llm/README.i18n.yaml
#	packages/plan/plan-mode/README.i18n.yaml
#	packages/plan/plan-mode/README.zh.md
#	packages/sdk/sdk-client/README.i18n.yaml
#	packages/sdk/sdk-client/README.zh.md
#	packages/sdk/sdk-protocol/README.i18n.yaml
#	packages/session-persistence/session-persistence/README.i18n.yaml
#	packages/session-persistence/session-persistence/README.zh.md
#	packages/skill/tool-skill/README.i18n.yaml
#	packages/subagent/subagent-dsh-sdk/README.i18n.yaml
#	packages/subagent/subagent-inprocess/README.i18n.yaml
#	packages/subagent/subagent-inprocess/README.zh.md
#	packages/ui/jsonrpc/README.i18n.yaml
This commit is contained in:
_Kerman
2026-08-05 13:09:53 +08:00
948 changed files with 3046 additions and 2959 deletions

View File

@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/session-projection/README.md
README.md: ae80a905705d205adb4a1ee66c72fa28d0d8b6d6
README.zh.md: 97e25dd16caeeb444f5f5309eed3341d422fa1b1
README.zh.md: 3d4a4aa3151cc92a8b887e85c911b7f6b59bf52f

View File

@@ -6,5 +6,5 @@
| 包 | ctx 键 | 职责 |
|---|---|---|
| [`session-projection`](session-projection/README.md) | `sessionProjections` | 接口包(package):merge-extensible 的 `SessionProjectionMap` 类型表、`ProjectionDefinition` 单元契约,以及供载体同步读取的正向驱动注册表 |
| [`session-projection-cache`](session-projection-cache/README.md) | `sessionProjectionCache` | 持久投影缓存:基于域数据形态的按会话单元 checkpoint 持久化、带 turn/end + detach 两个必写点的节流后写,以及冷读阶梯(缓存行 + 持久化尾部重放) |
| [`session-projection`](session-projection/README.md) | `sessionProjections` | 接口包:merge-extensible 的 `SessionProjectionMap` 类型表、`ProjectionDefinition` 单元契约,以及供载体同步读取的主动驱动注册表 |
| [`session-projection-cache`](session-projection-cache/README.md) | `sessionProjectionCache` | 持久投影缓存:基于域数据形态的按会话单元检查点持久化、带 turn/end + detach 两个必写点的节流后写,以及冷读阶梯(缓存行 + 持久化尾部回放) |

View File

@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/session-projection/session-projection-cache/README.md
README.md: 5d4ad07fab6648acdb40c6aa86d32cc78b4c016e
README.zh.md: ab4076df28cfe2b5a8b41d609967039dcacb7ef4
README.zh.md: 827480658b8c69647380a782c1a983b390380108

View File

@@ -2,15 +2,15 @@
[English](README.md) | 中文
持久投影缓存(`ctx.sessionProjectionCache`):把每个已注册投影单元的状态持久化为检查点(checkpoint),基于域数据形态(domain data form)每会话一条记录(`session_projcache` 域——出厂 json 后端将其落在配置的存储根目录下、`workspace.json` 旁边)。设计权威:[session-projection RFC](../../../.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.md)(persisted projection cache 一节)。
持久投影缓存(`ctx.sessionProjectionCache`):把每个已注册投影单元的状态持久化为检查点,基于域数据形态(domain data form)每会话一条记录(`session_projcache` 域——出厂 JSON 后端将其落在配置的存储根目录下、`workspace.json` 旁边)。设计权威:[session-projection RFC](../../../.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.md)(persisted projection cache 一节)。
一条存储行 `(key → {ver, seq, val})` 是折叠捷径,绝不是权威:可能陈旧(`seq` 精确说明陈旧到哪),但绝不会错。实现据此承诺:
- **每次后台写入都 fail-soft。** 持久写失败只记一条警告并保持缓存陈旧;下一次写入或冷读自愈。两次写之间崩溃的代价是更长的尾部重放,绝不是错误的值。
- **每次后台写入都 fail-soft。** 持久写失败只记一条警告并保持缓存陈旧;下一次写入或冷读自愈。两次写之间崩溃的代价是更长的尾部回放,绝不是错误的值。
- **`ver` 与活单元 `stateVersion` 不匹配即丢弃,绝不迁移。** 单元递增版本会在读取时使其行失效;该 key 从日志重新折叠。
- **整记录写入。** 每次写入替换该会话的完整检查点(注册表切面始终是完整的),并经无损 JSON 边界快照——违反纯 JSON 契约的单元状态会大声失败。
- **记录绑定到日志生命周期,而不只是 id。** 每条记录存储其折叠来源的 header 身份(`createdAt`、`cwd`);每次读取先以活 header 或存储 header 为证验证它,再接受任何行——被删后重建的 id、或缓存幸存而持久化存储被换掉时,无关记录被整体丢弃,绝不播种幻影值。
- **日志领先,缓存跟随。** 活会话检查点先把缓冲事件持久 flush,缓存行才落地,因此崩溃只会让缓存落后于日志(更长的尾部重放),绝不领先于它。
- **记录绑定到日志生命周期,而不只是 id。** 每条记录存储其折叠来源的 header 身份(`createdAt`、`cwd`);每次读取先以活 header 或存储 header 为证验证它,再接受任何行——被删后重建的 id、或缓存幸存而持久化存储被换掉时,无关记录被整体丢弃,绝不播种幻影值。
- **日志领先,缓存跟随。** 活会话检查点先把缓冲事件持久 flush,缓存行才落地,因此崩溃只会让缓存落后于日志(更长的尾部回放),绝不领先于它。
## 写策略
@@ -27,11 +27,11 @@
## 列表读(`cachedSnapshot(meta)`)
零 I/O 一档:从身份匹配的存储记录直接 view 全量值(仅版本匹配的 key),以 `{asOfSeq, values}` 切面返回——`asOfSeq` 取所服务行的最低水位,客户端在 higher-seq-wins 规则下播种值仓时,陈旧列表块永远压不过更新的推送帧。无可用记录(未知 id、无关生命周期、无版本匹配行)时返回 `undefined`;api-proxy 列表载体将其转为列缺席。
零 I/O 一档:从身份匹配的存储记录直接 view 全量值(仅版本匹配的 key),以 `{asOfSeq, values}` 切面返回——`asOfSeq` 取所服务行的最低水位,客户端在 higher-seq-wins 规则下播种值存储时,陈旧列表块永远压不过更新的推送帧。无可用记录(未知 id、无关生命周期、无版本匹配行)时返回 `undefined`;api-proxy 列表载体将其转为列缺席。
## 冷读(`coldSnapshot(id, signal?)`)
读取阶梯,快乐路径零全量日志加载:缓存行 → `sessionProjections.restoreFloor`(锚在最低可用水位下一格)→ 持久化 `readFrom(id, floor)` → `sessionProjections.restore` → 刷新行的 fail-soft 写回。这个锚使缩短的日志(崩溃修复截断)可被证明:越界的行恰好触发一次从 seq 0 的全量重读,而不是把幽灵值当现值服务。无已注册单元时直接服务 `{asOfSeq: -1, values: {}}`,不触碰持久化;无持久日志的会话以 seam 的 `not found` 拒绝。
读取阶梯,正常路径无需加载全量日志:缓存行 → `sessionProjections.restoreFloor`(锚定在最低可用水位之前一个事件的位置)→ 持久化 `readFrom(id, floor)` → `sessionProjections.restore` → 刷新行的 fail-soft 写回。这个锚使缩短的日志(崩溃修复截断)可被证明:越界的行恰好触发一次从 seq 0 的全量重读,而不是把幽灵值当现值服务。无已注册单元时直接服务 `{asOfSeq: -1, values: {}}`,不触碰持久化;无持久日志的会话以 seam 的 `not found` 拒绝。
`write(session)` 是两个必写点共用的同步切面检查点;载体可以直接调用(非 fail-soft——由 fail-soft 包装层负责遏制)。
@@ -49,9 +49,9 @@
## 模型体验
无,因为缓存只持久化并恢复 host 侧的、由已入日志会话状态派生的读模型,不触碰任何提示词、消息、schema、流或工具结果。
无,因为缓存只持久化并恢复 host 侧的、由已写入日志的会话状态派生的读模型,不触碰任何提示词、消息、schema、流或工具结果。
#### KV 缓存影响
#### KV Cache 影响
无;缓存从不组装或发送提供方请求。

View File

@@ -3,4 +3,4 @@
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write packages/session-projection/session-projection/README.md
README.md: f4898b8e567fa5998c18111c5f4e27a8a350a42e
README.zh.md: 385862868df495a5c857d91c32f6503c3ef72025
README.zh.md: 520205e616cdc1421c8f33f00d2013a6e0947d3d

View File

@@ -19,10 +19,10 @@
## 契约
- **框架负责驱动,领域负责计算。** 注册表只订阅一次 `session/event`;每个已提交事件都正向经过每个单元的 `apply`。领域不持有任何订阅。cell(每会话每单元一份 `{state, observedSeq}`,以 WeakMap 为键)惰性构建——在事件流过之后才注册的单元,或读取一个早于该注册的会话,都在首次触达时从 `init` 出发在内存日志上折叠。
- **框架负责驱动,领域负责计算。** 注册表只订阅一次 `session/event`;每个已提交事件都会主动经过每个单元的 `apply`。领域不持有任何订阅。cell(每会话每单元一份 `{state, observedSeq}`,以 WeakMap 为键)惰性构建——在事件流过之后才注册的单元,或读取一个早于该注册的会话,都在首次触达时从 `init` 出发在内存日志上折叠。
- **同引用即无工作。** 对与单元无关的事件,`apply` 必须返回同一个状态引用;驱动以 `Object.is` 把守变更流,因此不匹配的事件只花一次调用,不产生任何下游工作。
- **全量值事件规则(承重)。** 携带状态的日志事件必须携带变更后的完整状态,绝不携带裸增量——这让每次状态转移始终足够廉价,也让每个被供给的值自描述(对消费方即 last-wins)。
- **单元的同步纪律。** `init`/`apply`/`view` 必须是同步的;载体在切出页面切片的同一 tick 内读取 `snapshot()`,`asOfSeq` 之所以是一个一致切面正系于此。误写成异步的 `view` 会返回 Promise,让边界的 `schema.parse` 当场大声失败。
- **单元的同步纪律。**`init`/`apply`/`view` 必须是同步的;载体在切出页面切片的同一 tick 内读取 `snapshot()`,`asOfSeq` 之所以是一个一致切面正系于此。误写成异步的 `view` 会返回 Promise,让边界的 `schema.parse` 当场大声失败。
- **状态是纯 JSON,`stateVersion` 是其失效锚点。** 持久投影缓存(persisted projection cache)存储 `(sessionId, key, ver, seq, val)` 行;状态形状或折叠语义一旦变化就递增 `stateVersion`,使陈旧行被丢弃,而不是被正向 apply 成垃圾。
- **本层没有协议词汇。** 注册表只暴露变更流与快照读取面;载体(api-proxy)据此自铸各自的帧(`session/projection`)与块。
- **可选 seam。** 领域插件在 `ctx.inject(['sessionProjections'], …)` 下注册,因此不带注册表的 headless 组装完全不受影响;载体使用 `ctx.get('sessionProjections')`,注册表缺席时完全省略自己的块与帧。
@@ -39,9 +39,9 @@
无;投影从不组装或发送提供方请求。
## 已知限制与延期工作
## 已知限制与暂缓事项
- **每个尾页携带每个已注册的 key**——尚无逐 key 的 opt-out 或惰性 key 请求形状;在值都是 UI 量级的全量状态(一张 todo 清单、一份 goal 快照)时可以接受,若某领域的值变大再重议。
- **正向驱动(eager drive)逐事件触达每个单元**——按构造开销很低(全量值规则、同引用闸门),但若出现热点路径,可加按单元的事件类型预过滤,契约不变。
- **主动驱动(eager drive)逐事件触达每个单元**——按构造开销很低(全量值规则、同引用闸门),但若出现热点路径,可加按单元的事件类型预过滤,契约不变。
- **注册表 cell 只活在内存里**——重启后首次触达时靠折叠日志重建;挂载了 `dsh-session-projection-cache` 的组合改由持久行播种该折叠。
- **单元同步纪律只有部分可机械把关**——边界 `schema.parse` 能拒绝返回 Promise 的 `view`,但阻塞的 `apply`、或读取撕裂的非会话状态的 `apply`,只能靠评审把关;invariant 配套记载了为何不存在运行时检查。