dsh-plugin-dev-kb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/cordis.patch.yml +12 -0
  4. package/kb/INDEX.md +210 -0
  5. package/kb/README.md +69 -0
  6. package/kb/extra/AGENTS.md +75 -0
  7. package/kb/extra/api-gateway.md +164 -0
  8. package/kb/extra/api-gateway.zh.md +164 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +59 -0
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +59 -0
  11. package/kb/extra/cookbook/maintaining-dsh-code-review.md +64 -0
  12. package/kb/extra/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  13. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  14. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  15. package/kb/extra/defensive-patterns.md +33 -0
  16. package/kb/extra/defensive-patterns.zh.md +33 -0
  17. package/kb/extra/development.md +171 -0
  18. package/kb/extra/development.zh.md +171 -0
  19. package/kb/extra/event-producer-consumer.md +76 -0
  20. package/kb/extra/event-producer-consumer.zh.md +78 -0
  21. package/kb/extra/glossary.md +45 -0
  22. package/kb/extra/glossary.zh.md +45 -0
  23. package/kb/extra/graph-atlas.md +24 -0
  24. package/kb/extra/graph-atlas.zh.md +26 -0
  25. package/kb/extra/i18n/README.md +60 -0
  26. package/kb/extra/i18n/README.zh.md +60 -0
  27. package/kb/extra/i18n/style-samples.md +87 -0
  28. package/kb/extra/i18n/terminology.md +214 -0
  29. package/kb/extra/i18n/translation-prompt.md +263 -0
  30. package/kb/extra/i18n/translation-rules.md +69 -0
  31. package/kb/extra/i18n/translation-rules.zh.md +69 -0
  32. package/kb/extra/module-graph.md +1641 -0
  33. package/kb/extra/module-graph.zh.md +1643 -0
  34. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  35. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  36. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  37. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  38. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  39. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  40. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  41. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  42. package/kb/extra/postmortem/README.md +18 -0
  43. package/kb/extra/postmortem/README.zh.md +18 -0
  44. package/kb/extra/rescope.md +53 -0
  45. package/kb/extra/rescope.zh.md +53 -0
  46. package/kb/extra/subsystems/attachment.md +125 -0
  47. package/kb/extra/subsystems/attachment.zh.md +125 -0
  48. package/kb/extra/subsystems/extensions.md +364 -0
  49. package/kb/extra/subsystems/extensions.zh.md +364 -0
  50. package/kb/extra/subsystems/feedback.md +266 -0
  51. package/kb/extra/subsystems/feedback.zh.md +266 -0
  52. package/kb/extra/testing.md +49 -0
  53. package/kb/extra/testing.zh.md +49 -0
  54. package/kb/extra/web-styling.md +25 -0
  55. package/kb/extra/web-styling.zh.md +25 -0
  56. package/kb/meta/search-index.json +1328 -0
  57. package/kb/meta/site-pages.txt +168 -0
  58. package/kb/meta/source.json +13 -0
  59. package/kb/meta/topics.md +75 -0
  60. package/kb/site/develop/basic/config.md +108 -0
  61. package/kb/site/develop/basic/index.md +146 -0
  62. package/kb/site/develop/basic/publish.md +185 -0
  63. package/kb/site/develop/basic/tool.md +54 -0
  64. package/kb/site/develop/cordis-tutorial/01-first-plugin.md +95 -0
  65. package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  66. package/kb/site/develop/cordis-tutorial/03-services.md +98 -0
  67. package/kb/site/develop/cordis-tutorial/04-events.md +144 -0
  68. package/kb/site/develop/cordis-tutorial/05-config.md +84 -0
  69. package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  70. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  71. package/kb/site/develop/cordis-tutorial/index.md +62 -0
  72. package/kb/site/develop/framework/events.md +145 -0
  73. package/kb/site/develop/framework/index.md +139 -0
  74. package/kb/site/develop/framework/service.md +152 -0
  75. package/kb/site/develop/practice/index.md +157 -0
  76. package/kb/site/develop/practice/llm-adapter.md +190 -0
  77. package/kb/site/en/develop/basic/config.md +108 -0
  78. package/kb/site/en/develop/basic/index.md +146 -0
  79. package/kb/site/en/develop/basic/publish.md +185 -0
  80. package/kb/site/en/develop/basic/tool.md +54 -0
  81. package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +95 -0
  82. package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  83. package/kb/site/en/develop/cordis-tutorial/03-services.md +98 -0
  84. package/kb/site/en/develop/cordis-tutorial/04-events.md +144 -0
  85. package/kb/site/en/develop/cordis-tutorial/05-config.md +84 -0
  86. package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  87. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  88. package/kb/site/en/develop/cordis-tutorial/index.md +60 -0
  89. package/kb/site/en/develop/framework/events.md +145 -0
  90. package/kb/site/en/develop/framework/index.md +139 -0
  91. package/kb/site/en/develop/framework/service.md +150 -0
  92. package/kb/site/en/develop/practice/index.md +157 -0
  93. package/kb/site/en/develop/practice/llm-adapter.md +190 -0
  94. package/kb/site/en/guide/providers-custom-form.png +0 -0
  95. package/kb/site/en/guide/providers-models-page.png +0 -0
  96. package/kb/site/en/guide/providers.md +100 -0
  97. package/kb/site/en/guide/python-sdk.md +106 -0
  98. package/kb/site/en/guide/quickstart.md +32 -0
  99. package/kb/site/en/index.md +8 -0
  100. package/kb/site/en/reference/agent-lifecycle.md +86 -0
  101. package/kb/site/en/reference/capability-seams.md +475 -0
  102. package/kb/site/en/reference/config-catalog.md +3155 -0
  103. package/kb/site/en/reference/cookbook/adding-a-conversation-node.md +235 -0
  104. package/kb/site/en/reference/cookbook/adding-a-package.md +120 -0
  105. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +102 -0
  106. package/kb/site/en/reference/cookbook/adding-a-tool.md +96 -0
  107. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +45 -0
  108. package/kb/site/en/reference/cookbook/extension-cookbook.md +131 -0
  109. package/kb/site/en/reference/cordis-api/context.md +368 -0
  110. package/kb/site/en/reference/cordis-api/events.md +211 -0
  111. package/kb/site/en/reference/cordis-api/fiber.md +379 -0
  112. package/kb/site/en/reference/cordis-api/inherited.md +43 -0
  113. package/kb/site/en/reference/cordis-api/registry.md +156 -0
  114. package/kb/site/en/reference/cordis-api/service.md +106 -0
  115. package/kb/site/en/reference/cordis-primer.md +46 -0
  116. package/kb/site/en/reference/index.md +131 -0
  117. package/kb/site/en/reference/persistence-catalog.md +949 -0
  118. package/kb/site/en/reference/subsystems/approval.md +173 -0
  119. package/kb/site/en/reference/subsystems/client-modules.md +121 -0
  120. package/kb/site/en/reference/subsystems/code-runtime.md +194 -0
  121. package/kb/site/en/reference/subsystems/commands.md +190 -0
  122. package/kb/site/en/reference/subsystems/compaction.md +241 -0
  123. package/kb/site/en/reference/subsystems/core.md +1073 -0
  124. package/kb/site/en/reference/subsystems/credentials.md +136 -0
  125. package/kb/site/en/reference/subsystems/filesystem.md +498 -0
  126. package/kb/site/en/reference/subsystems/goal.md +280 -0
  127. package/kb/site/en/reference/subsystems/index.md +58 -0
  128. package/kb/site/en/reference/subsystems/invariants.md +91 -0
  129. package/kb/site/en/reference/subsystems/jobs.md +293 -0
  130. package/kb/site/en/reference/subsystems/llm-streaming.md +920 -0
  131. package/kb/site/en/reference/subsystems/lsp.md +205 -0
  132. package/kb/site/en/reference/subsystems/permission-presets.md +134 -0
  133. package/kb/site/en/reference/subsystems/persistence.md +388 -0
  134. package/kb/site/en/reference/subsystems/plan.md +90 -0
  135. package/kb/site/en/reference/subsystems/sandbox.md +221 -0
  136. package/kb/site/en/reference/subsystems/schedule.md +189 -0
  137. package/kb/site/en/reference/subsystems/scope.md +62 -0
  138. package/kb/site/en/reference/subsystems/session-projection.md +265 -0
  139. package/kb/site/en/reference/subsystems/session-query.md +498 -0
  140. package/kb/site/en/reference/subsystems/session-reference.md +111 -0
  141. package/kb/site/en/reference/subsystems/session-telemetry.md +197 -0
  142. package/kb/site/en/reference/subsystems/session-title.md +207 -0
  143. package/kb/site/en/reference/subsystems/session.md +852 -0
  144. package/kb/site/en/reference/subsystems/settings.md +313 -0
  145. package/kb/site/en/reference/subsystems/shell.md +306 -0
  146. package/kb/site/en/reference/subsystems/skills.md +334 -0
  147. package/kb/site/en/reference/subsystems/spill.md +120 -0
  148. package/kb/site/en/reference/subsystems/storage.md +232 -0
  149. package/kb/site/en/reference/subsystems/subagent.md +737 -0
  150. package/kb/site/en/reference/subsystems/subprocess.md +327 -0
  151. package/kb/site/en/reference/subsystems/system-prompt.md +210 -0
  152. package/kb/site/en/reference/subsystems/terminal.md +187 -0
  153. package/kb/site/en/reference/subsystems/token-meter.md +93 -0
  154. package/kb/site/en/reference/subsystems/tools.md +723 -0
  155. package/kb/site/en/reference/subsystems/typert.md +339 -0
  156. package/kb/site/en/reference/subsystems/user-questions.md +181 -0
  157. package/kb/site/en/reference/subsystems/web-server.md +111 -0
  158. package/kb/site/en/reference/subsystems/web.md +202 -0
  159. package/kb/site/en/reference/subsystems/workflow.md +281 -0
  160. package/kb/site/en/reference/subsystems/workspace.md +231 -0
  161. package/kb/site/en/reference/tool-catalog.md +1877 -0
  162. package/kb/site/en/reference/tool-execution-pipeline.md +66 -0
  163. package/kb/site/guide/providers-custom-form.zh.png +0 -0
  164. package/kb/site/guide/providers-models-page.zh.png +0 -0
  165. package/kb/site/guide/providers.md +100 -0
  166. package/kb/site/guide/python-sdk.md +106 -0
  167. package/kb/site/guide/quickstart.md +32 -0
  168. package/kb/site/index.md +8 -0
  169. package/kb/site/reference/agent-lifecycle.md +86 -0
  170. package/kb/site/reference/capability-seams.md +475 -0
  171. package/kb/site/reference/config-catalog.md +3154 -0
  172. package/kb/site/reference/cookbook/adding-a-conversation-node.md +235 -0
  173. package/kb/site/reference/cookbook/adding-a-package.md +120 -0
  174. package/kb/site/reference/cookbook/adding-a-settings-card.md +102 -0
  175. package/kb/site/reference/cookbook/adding-a-tool.md +98 -0
  176. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +45 -0
  177. package/kb/site/reference/cookbook/extension-cookbook.md +133 -0
  178. package/kb/site/reference/cordis-api/context.md +368 -0
  179. package/kb/site/reference/cordis-api/events.md +211 -0
  180. package/kb/site/reference/cordis-api/fiber.md +379 -0
  181. package/kb/site/reference/cordis-api/inherited.md +43 -0
  182. package/kb/site/reference/cordis-api/registry.md +156 -0
  183. package/kb/site/reference/cordis-api/service.md +106 -0
  184. package/kb/site/reference/cordis-primer.md +52 -0
  185. package/kb/site/reference/index.md +135 -0
  186. package/kb/site/reference/persistence-catalog.md +949 -0
  187. package/kb/site/reference/subsystems/approval.md +173 -0
  188. package/kb/site/reference/subsystems/client-modules.md +121 -0
  189. package/kb/site/reference/subsystems/code-runtime.md +194 -0
  190. package/kb/site/reference/subsystems/commands.md +190 -0
  191. package/kb/site/reference/subsystems/compaction.md +241 -0
  192. package/kb/site/reference/subsystems/core.md +1081 -0
  193. package/kb/site/reference/subsystems/credentials.md +136 -0
  194. package/kb/site/reference/subsystems/filesystem.md +498 -0
  195. package/kb/site/reference/subsystems/goal.md +280 -0
  196. package/kb/site/reference/subsystems/index.md +58 -0
  197. package/kb/site/reference/subsystems/invariants.md +91 -0
  198. package/kb/site/reference/subsystems/jobs.md +293 -0
  199. package/kb/site/reference/subsystems/llm-streaming.md +926 -0
  200. package/kb/site/reference/subsystems/lsp.md +205 -0
  201. package/kb/site/reference/subsystems/permission-presets.md +134 -0
  202. package/kb/site/reference/subsystems/persistence.md +388 -0
  203. package/kb/site/reference/subsystems/plan.md +90 -0
  204. package/kb/site/reference/subsystems/sandbox.md +221 -0
  205. package/kb/site/reference/subsystems/schedule.md +189 -0
  206. package/kb/site/reference/subsystems/scope.md +62 -0
  207. package/kb/site/reference/subsystems/session-projection.md +265 -0
  208. package/kb/site/reference/subsystems/session-query.md +498 -0
  209. package/kb/site/reference/subsystems/session-reference.md +111 -0
  210. package/kb/site/reference/subsystems/session-telemetry.md +197 -0
  211. package/kb/site/reference/subsystems/session-title.md +207 -0
  212. package/kb/site/reference/subsystems/session.md +854 -0
  213. package/kb/site/reference/subsystems/settings.md +313 -0
  214. package/kb/site/reference/subsystems/shell.md +306 -0
  215. package/kb/site/reference/subsystems/skills.md +334 -0
  216. package/kb/site/reference/subsystems/spill.md +120 -0
  217. package/kb/site/reference/subsystems/storage.md +232 -0
  218. package/kb/site/reference/subsystems/subagent.md +739 -0
  219. package/kb/site/reference/subsystems/subprocess.md +327 -0
  220. package/kb/site/reference/subsystems/system-prompt.md +210 -0
  221. package/kb/site/reference/subsystems/terminal.md +187 -0
  222. package/kb/site/reference/subsystems/token-meter.md +93 -0
  223. package/kb/site/reference/subsystems/tools.md +723 -0
  224. package/kb/site/reference/subsystems/typert.md +339 -0
  225. package/kb/site/reference/subsystems/user-questions.md +181 -0
  226. package/kb/site/reference/subsystems/web-server.md +111 -0
  227. package/kb/site/reference/subsystems/web.md +202 -0
  228. package/kb/site/reference/subsystems/workflow.md +281 -0
  229. package/kb/site/reference/subsystems/workspace.md +231 -0
  230. package/kb/site/reference/tool-catalog.md +1880 -0
  231. package/kb/site/reference/tool-execution-pipeline.md +66 -0
  232. package/package.json +40 -0
  233. package/scripts/rebuild-index.mjs +88 -0
  234. package/skills/dsh-plugin-dev-kb.md +66 -0
@@ -0,0 +1,265 @@
1
+ ---
2
+ editSource: "docs/subsystems/session-projection.zh.md"
3
+ outline: [2,3]
4
+ ---
5
+
6
+ # 会话投影
7
+
8
+ 会话投影 seam 是一项[能力 seam](../capability-seams.md):领域 host 插件经由它向客户端载体供给按会话的日志派生状态的当前全量值;三方分别是 Service Definition 与注册表([dsh-session-projection](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-projection),`ctx.sessionProjections`)、领域贡献方(每个领域注册一个纯单元)与载体([dsh-host-apiproxy](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/host/apiproxy) 的历史尾页与 `session/projection` 推送帧)。它是一项可选能力,不属于 agent loop(智能体循环)主干。框架负责驱动,领域负责计算:注册表只订阅一次 `session/event`,并把每个已提交事件折叠进每个单元;领域不持有任何订阅,客户端也从不折叠领域事件——它们收到的是成品值。设计权威:[session-projection RFC](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/proposed/architecture/2026-07-27-session-projection-and-command-log.md);驱动、缓存与变更流约定:[包 README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/README.md)。
9
+
10
+ 源码:[`packages/session/session-projection/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
11
+
12
+ ## 投影单元
13
+
14
+ `SessionProjectionMap` 是整条链路(host 侧单元、协议块、客户端钩子)的 merge-extensible 类型表;值是协议层 JSON 全量值,渲染归 slot 体系管,永远不归本层。领域为每个 key 贡献一个 `ProjectionDefinition`:
15
+
16
+ ```ts type-equiv
17
+ /**
18
+ * One domain's state-driven computation unit: three pure synchronous
19
+ * functions plus declarations — never an opaque getter. The framework drives
20
+ * `apply` on every committed session event; the domain holds no
21
+ * subscriptions and owns only the mathematics. All three functions MUST be
22
+ * synchronous (an async unit would tear the carriers' consistency cut) and
23
+ * `state` MUST be plain JSON (the persisted-cache precondition).
24
+ */
25
+ interface ProjectionDefinition<K extends keyof SessionProjectionMap, S> {
26
+ /** The projection key this unit owns (its `SessionProjectionMap` entry). */
27
+ key: K
28
+ /** Validates the wire payload (`view` output) before it leaves the host. */
29
+ schema: ZodType<SessionProjectionMap[K]>
30
+ /**
31
+ * State for the empty log.
32
+ * @returns the initial state.
33
+ */
34
+ init(): S
35
+ /**
36
+ * Pure transition: previous state + one committed event → next state. A
37
+ * unit uninterested in an event MUST return the same state reference — an
38
+ * unchanged reference (`Object.is`) produces zero downstream work.
39
+ * @param state - the state covering all prior events.
40
+ * @param event - the next committed session event.
41
+ * @returns the next state (same reference when the event is not the unit's).
42
+ */
43
+ apply(state: S, event: SessionEvent): S
44
+ /**
45
+ * State → wire payload (the read-side projection).
46
+ * @param state - the current state.
47
+ * @returns the whole current value for this unit's key.
48
+ */
49
+ view(state: S): SessionProjectionMap[K]
50
+ /**
51
+ * Persisted-cache invalidation version: bump whenever the serialized state fields or the
52
+ * fold semantics change, so persisted `(sessionId, key, ver, seq, val)`
53
+ * rows from an older unit are discarded instead of being forward-applied
54
+ * into garbage. Non-negative integer.
55
+ */
56
+ stateVersion: number
57
+ }
58
+ ```
59
+
60
+ 全量值事件规则是承重结构:携带状态的日志事件携带的是变更后的完整状态,绝不是裸增量——这让每次状态转移始终足够廉价,也让每个被供给的值自描述(对消费方即 last-wins)。
61
+
62
+ ## 快照与变更流
63
+
64
+ ```ts type-equiv
65
+ /**
66
+ * One consistent read cut over every registered unit for one session.
67
+ * `asOfSeq` is the shared watermark — the seq of the last event every value
68
+ * reflects (`-1` for an empty log, mirroring `session/subscribed.lastSeq`).
69
+ */
70
+ interface ProjectionSnapshot {
71
+ /** Seq of the last event the values reflect; -1 for an empty log. */
72
+ asOfSeq: number
73
+ /** Whole current value per registered key. */
74
+ values: Partial<SessionProjectionMap>
75
+ }
76
+ ```
77
+
78
+ ```ts type-equiv
79
+ /**
80
+ * Change-feed listener: one unit's value changed for one session. `value` is
81
+ * the schema-validated `view` output; `seq` is the unit's watermark at
82
+ * emission (the seq of the event that caused the change).
83
+ */
84
+ type ProjectionChangeListener = (
85
+ session: Session,
86
+ key: Extract<keyof SessionProjectionMap, string>,
87
+ value: unknown,
88
+ seq: number,
89
+ ) => void
90
+ ```
91
+
92
+ `snapshot(session)` 完全同步:载体在切出页面切片的同一 tick 内读取它,因此 `asOfSeq` 使两次读取使用同一个序号。每个值在返回前都会通过其单元的 schema 校验;如果 `view` 被误写为异步函数,它会返回 Promise,schema 校验将拒绝该值。对于每个已提交事件,变更流会为每个状态*引用*已变化的单元触发一次;状态未变时,`apply` 必须返回同一引用。
93
+
94
+ ## 注册表:`ctx.sessionProjections`
95
+
96
+ `SessionProjectionRegistry`([签名](#ctxsessionprojections--sessionprojectionregistry))拥有驱动权:一份 `session/event` 订阅、对每个已注册单元即时调用 `apply`,以及每会话每单元的水位线(watermark)cell。cell 惰性构建:在事件流过之后才注册的单元,或比注册表更早的会话,都在首次触达(事件或读取)时从 `init` 出发在内存日志上折叠。注册是一个 effect,其 disposer 随调用方 fiber 走:领域插件卸载后,其 key(连同缓存的 cell)从后续驱动与快照中消失,客户端将其读作能力缺失;key 重复直接 throw。领域插件在 `ctx.inject(['sessionProjections'], …)` 下注册,因此不带注册表的 headless 组装完全不受影响。
97
+
98
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
99
+
100
+ <a id="cordis-surface"></a>
101
+
102
+ ## Cordis API
103
+
104
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
105
+
106
+ <a id="ctxsessionprojectioncache--sessionprojectioncache"></a>
107
+
108
+ ### `ctx.sessionProjectionCache` — `SessionProjectionCache`
109
+
110
+ The persisted projection cache service. Opens the `session_projcache` domain at init, checkpoints live sessions on a throttled write-behind (count/interval triggers from Config) plus two mandatory points — `turn/end` and session disposal (the live-to-cold moment) — and serves the cold-read ladder: cached row, persistence `readFrom` tail, registry `restore`, durable write-back. Every durable write is fail-soft: failures log a warning and the cache self-heals on the next write or cold read.
111
+
112
+ ```ts cordis-catalog
113
+ /**
114
+ * The zero-I/O listing read: whole values viewed straight from the stored
115
+ * rows (version-matching keys only), each cut carried with its watermark
116
+ * so a client value store can seed under its higher-seq-wins rule — as
117
+ * stale as the last durable checkpoint but never wrong, and never from an
118
+ * unrelated log (the caller's header is the identity witness). Fresher
119
+ * paths (the history tail baseline, {@link coldSnapshot}) supersede these
120
+ * values whenever a session is actually opened.
121
+ * @param meta - the listed session's header (identity witness; no log read).
122
+ * @returns the cut (`asOfSeq` = lowest served-row watermark), or
123
+ * `undefined` when no usable row exists for this lifecycle.
124
+ */
125
+ cachedSnapshot(meta: SessionHeader): ProjectionSnapshot | undefined
126
+
127
+ /**
128
+ * Durably checkpoint one live session NOW (both mandatory points call
129
+ * this; tests and carriers may too). The registry cut is snapshotted at
130
+ * this boundary (states are live references), then the whole record is
131
+ * replaced. NOT fail-soft — callers on the fail-soft paths contain it.
132
+ * @param session - the live session to checkpoint.
133
+ * @returns resolution after durability and event emission.
134
+ */
135
+ async write(session: Session): Promise<void>
136
+
137
+ /**
138
+ * Cold-read one persisted session's projections with zero full-log load:
139
+ * cached rows + a persistence `readFrom` tail from the registry's restore
140
+ * floor, refolded by the registry and written back (fail-soft) so the next
141
+ * cold read starts closer. A cache row invalidated by a shrunk log
142
+ * (crash-repair truncation) triggers one full re-read from seq 0 — the
143
+ * ladder's slow rung, still no crash. Rejects when the session has no
144
+ * persisted log (`not found` from the persistence seam).
145
+ * @param id - the persisted session to read.
146
+ * @param signal - optional cancellation for the persistence reads.
147
+ * @returns the snapshot cut at the stored log end.
148
+ */
149
+ async coldSnapshot(id: SessionId, signal?: AbortSignal): Promise<ProjectionSnapshot>
150
+ ```
151
+
152
+ Types: [Session](./session.md) · [SessionHeader](./persistence.md) · [SessionId](./core.md)
153
+
154
+ Source: [`packages/session/session-projection-cache/src/index.ts:71`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection-cache/src/index.ts)
155
+
156
+ <a id="ctxsessionprojections--sessionprojectionregistry"></a>
157
+
158
+ ### `ctx.sessionProjections` — `SessionProjectionRegistry`
159
+
160
+ `ctx.sessionProjections`: the projection unit table and its drive. The service subscribes to `session/event` once; every committed event passes every registered unit's `apply` (eager drive), and a changed state reference notifies the change feed with the schema-validated view. Cells build lazily — a unit registered after events flowed, or a session older than the registry, folds `init` over the in-memory log on first touch (event or read). Registration is an effect (disposer rides the calling fiber): an unloaded domain plugin's key disappears from snapshots and clients read it as capability absence. Domain plugins register under `ctx.inject(['sessionProjections'], …)` so headless assemblies without the registry stay unaffected. Registrants sharing a key share one unit and are counted: the same tool package mounted in N agent presets registers N times, and the key survives until the last one unloads.
161
+
162
+ ```ts cordis-catalog
163
+ /**
164
+ * Register one domain's unit. The registration is an effect on the calling
165
+ * context's fiber: disposing the fiber (or calling the returned disposer)
166
+ * removes the key — and the unit's cached cells — from subsequent drives
167
+ * and snapshots.
168
+ * @param definition - key, state schema, pure unit functions, and stateVersion.
169
+ * @returns the exact disposer that unregisters this unit.
170
+ */
171
+ register<K extends keyof SessionProjectionMap, S>(definition: ProjectionDefinition<K, S>): () => void
172
+
173
+ /**
174
+ * Subscribe to the change feed. The registration is an effect on the
175
+ * calling context's fiber.
176
+ * @param listener - called once per unit whose state reference changed, per committed event.
177
+ * @returns the exact disposer that unsubscribes.
178
+ */
179
+ onChanged(listener: ProjectionChangeListener): () => void
180
+
181
+ /**
182
+ * One consistent cut over every registered unit for one session, read from
183
+ * the watermark cache (missing cells fold lazily over the in-memory log).
184
+ * Fully synchronous — every value and `asOfSeq` reflect the same log
185
+ * position. Each value passes its unit's schema before leaving.
186
+ * @param session - the session whose projection values are read.
187
+ * @returns the snapshot; `values` is empty when no unit is registered.
188
+ */
189
+ snapshot(session: Session): ProjectionSnapshot
190
+
191
+ /**
192
+ * State-level checkpoint of every registered unit for one session, read
193
+ * from the watermark cache (missing cells fold lazily over the in-memory
194
+ * log). This is the write side of the persisted projection cache: the
195
+ * returned rows are the `(key → {ver, seq, val})` part of the durable
196
+ * `(sessionId, key, ver, seq, val)`
197
+ * rows. Every `val` is a DETACHED structured clone — never the live
198
+ * cell reference: the watermark cache is this registry's authoritative
199
+ * mutable state, and a caller reaching the live reference could corrupt
200
+ * every subsequent snapshot and frame through it (plain JSON by the unit
201
+ * contract, so the clone is total).
202
+ * @param session - the session whose unit states are checkpointed.
203
+ * @returns one row per registered key; empty when no unit is registered.
204
+ */
205
+ checkpoint(session: Session): ProjectionCheckpoint
206
+
207
+ /**
208
+ * The stored seq a {@link restore} tail read over `checkpoint` must start
209
+ * at: one event BELOW the lowest usable watermark (a row is usable when
210
+ * its `ver` matches the live unit's `stateVersion`; an absent or mismatched row
211
+ * pulls the floor to `0` — that key must refold the full log). The
212
+ * one-below anchor is load-bearing: the tail then proves how far the
213
+ * stored log still extends, so {@link restore} can detect a log that
214
+ * shrank below a row's watermark (crash-repair truncation) instead of
215
+ * serving the stale row as current — an empty tail read from the anchor
216
+ * yields an end below every watermark and the restore rejects for a full
217
+ * re-read.
218
+ * @param checkpoint - persisted rows for one session (possibly stale or empty).
219
+ * @returns the seq to hand the persistence `readFrom`, or `undefined`
220
+ * when no unit is registered (no read needed — {@link restore} would
221
+ * serve empty values regardless).
222
+ */
223
+ restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined
224
+
225
+ /**
226
+ * View a checkpoint's rows without any log read: for every registered
227
+ * unit whose row's `ver` matches, serve the schema-validated
228
+ * `view` of the stored state; mismatched or absent rows leave their key
229
+ * absent (a cold or listing consumer treats it as not-yet-available and a
230
+ * fuller read path refolds it). The zero-I/O rung of the read ladder —
231
+ * values are as stale as their rows, never wrong.
232
+ * @param checkpoint - persisted rows for one session (possibly stale or empty).
233
+ * @returns whole values per key with a usable row; empty when none.
234
+ */
235
+ viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>
236
+
237
+ /**
238
+ * Cold read: fold every registered unit over a stored log suffix, seeding
239
+ * each from its checkpoint row when usable — the one read recipe (cached
240
+ * state + forward tail replay + `view`) applied without a live `Session`.
241
+ * Call with the events returned by a persistence
242
+ * `readFrom(id, restoreFloor(checkpoint))` and that same floor as
243
+ * `baseSeq`; the floor's one-below anchor makes the supplied end honest,
244
+ * so a shrunk log is detected here. A row is usable iff its
245
+ * `ver` matches the live unit's `stateVersion`, it does not predate `baseSeq`
246
+ * (`seq >= baseSeq - 1`), and it does not claim events past the
247
+ * supplied end (`seq <= endSeq`); an unusable row is discarded
248
+ * and its key refolds from `init` — which is only sound over the full
249
+ * log, so a discarded row with `baseSeq > 0` throws (the caller re-reads
250
+ * from seq 0, e.g. after a crash-repair truncation shrank the log below
251
+ * a row's watermark).
252
+ * @param checkpoint - persisted rows for one session (possibly stale or empty).
253
+ * @param events - the stored events with `seq >= baseSeq`, in seq order.
254
+ * @param baseSeq - the seq `events` starts at (its first event's seq when non-empty).
255
+ * @returns the snapshot cut at the supplied log end (`asOfSeq` is the last
256
+ * supplied event's seq, `baseSeq - 1` for an empty tail) plus the
257
+ * refreshed checkpoint rows at that cut, ready for a durable write-back.
258
+ */
259
+ restore(checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
260
+ ```
261
+
262
+ Types: [Session](./session.md) · [SessionEvent](./session.md)
263
+
264
+ Source: [`packages/session/session-projection/src/index.ts:171`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
265
+ <!-- END GENERATED cordis-surface -->