dsh-plugin-dev-kb 1.0.8 → 1.1.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 (188) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.en.md +6 -6
  3. package/README.md +6 -6
  4. package/kb/INDEX.md +21 -5
  5. package/kb/README.md +11 -10
  6. package/kb/extra/AGENTS.md +4 -4
  7. package/kb/extra/cookbook/adding-a-remote-api.md +197 -0
  8. package/kb/extra/cookbook/adding-a-remote-api.zh.md +197 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +2 -2
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +2 -2
  11. package/kb/extra/deepseek-llm-api-wire-extensions.md +163 -0
  12. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +163 -0
  13. package/kb/extra/development.md +8 -14
  14. package/kb/extra/development.zh.md +8 -14
  15. package/kb/extra/event-producer-consumer.md +55 -48
  16. package/kb/extra/event-producer-consumer.zh.md +58 -51
  17. package/kb/extra/glossary.md +1 -1
  18. package/kb/extra/glossary.zh.md +1 -1
  19. package/kb/extra/graph-atlas.md +0 -2
  20. package/kb/extra/graph-atlas.zh.md +0 -2
  21. package/kb/extra/i18n/README.md +4 -4
  22. package/kb/extra/i18n/README.zh.md +4 -4
  23. package/kb/extra/i18n/style-samples.md +2 -2
  24. package/kb/extra/module-graph.md +646 -926
  25. package/kb/extra/module-graph.zh.md +648 -928
  26. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +2 -2
  27. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +2 -2
  28. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
  29. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
  30. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
  31. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
  32. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
  33. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +1 -1
  34. package/kb/extra/rescope.md +2 -2
  35. package/kb/extra/rescope.zh.md +2 -2
  36. package/kb/extra/subsystems/agent-team.md +28 -4
  37. package/kb/extra/subsystems/agent-team.zh.md +28 -4
  38. package/kb/extra/subsystems/attachment.md +168 -7
  39. package/kb/extra/subsystems/attachment.zh.md +168 -7
  40. package/kb/extra/subsystems/extensions.md +18 -0
  41. package/kb/extra/subsystems/extensions.zh.md +18 -0
  42. package/kb/extra/subsystems/feedback.md +4 -4
  43. package/kb/extra/subsystems/feedback.zh.md +4 -4
  44. package/kb/extra/subsystems/todo.md +32 -0
  45. package/kb/extra/subsystems/todo.zh.md +32 -0
  46. package/kb/extra/subsystems/webhook.md +70 -0
  47. package/kb/extra/subsystems/webhook.zh.md +70 -0
  48. package/kb/extra/testing.md +15 -10
  49. package/kb/extra/testing.zh.md +13 -8
  50. package/kb/extra/web-styling.md +4 -0
  51. package/kb/extra/web-styling.zh.md +4 -0
  52. package/kb/meta/search-index.json +309 -177
  53. package/kb/meta/site-pages.txt +183 -167
  54. package/kb/meta/source.json +5 -5
  55. package/kb/meta/topics.md +14 -6
  56. package/kb/site/develop/basic/publish.md +2 -2
  57. package/kb/site/develop/basic/tool.md +1 -1
  58. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  59. package/kb/site/develop/framework/events.md +1 -1
  60. package/kb/site/develop/practice/dynamic-cordis.md +17 -0
  61. package/kb/site/develop/practice/llm-adapter.md +4 -3
  62. package/kb/site/en/develop/basic/publish.md +2 -2
  63. package/kb/site/en/develop/basic/tool.md +1 -1
  64. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +5 -4
  65. package/kb/site/en/develop/framework/events.md +1 -1
  66. package/kb/site/en/develop/practice/dynamic-cordis.md +17 -0
  67. package/kb/site/en/develop/practice/llm-adapter.md +4 -3
  68. package/kb/site/en/guide/github-review.md +104 -0
  69. package/kb/site/en/guide/mcp-memory.md +103 -0
  70. package/kb/site/en/guide/network-proxy.md +87 -0
  71. package/kb/site/en/guide/providers.md +70 -17
  72. package/kb/site/en/guide/python-sdk.md +80 -34
  73. package/kb/site/en/guide/schedule.md +23 -0
  74. package/kb/site/en/reference/agent-lifecycle.md +6 -4
  75. package/kb/{extra → site/en/reference}/api-gateway.md +12 -10
  76. package/kb/site/en/reference/capability-seams.md +128 -73
  77. package/kb/site/en/reference/config-catalog.md +481 -360
  78. package/kb/site/en/reference/cookbook/adding-a-package.md +3 -4
  79. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +12 -10
  80. package/kb/site/en/reference/cookbook/adding-a-tool.md +11 -4
  81. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -1
  82. package/kb/site/en/reference/cookbook/extension-cookbook.md +20 -17
  83. package/kb/site/en/reference/cordis-api/inherited.md +1 -1
  84. package/kb/site/en/reference/cordis-primer.md +2 -1
  85. package/kb/site/en/reference/index.md +30 -11
  86. package/kb/site/en/reference/persistence-catalog.md +148 -80
  87. package/kb/site/en/reference/subsystems/approval.md +10 -10
  88. package/kb/site/en/reference/subsystems/client-modules.md +58 -16
  89. package/kb/site/en/reference/subsystems/code-runtime.md +10 -6
  90. package/kb/site/en/reference/subsystems/commands.md +25 -16
  91. package/kb/site/en/reference/subsystems/compaction.md +11 -11
  92. package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
  93. package/kb/site/en/reference/subsystems/core.md +156 -17
  94. package/kb/site/en/reference/subsystems/credentials.md +44 -3
  95. package/kb/site/en/reference/subsystems/filesystem.md +12 -2
  96. package/kb/site/en/reference/subsystems/goal.md +1 -1
  97. package/kb/site/en/reference/subsystems/index.md +7 -2
  98. package/kb/site/en/reference/subsystems/jobs.md +1 -1
  99. package/kb/site/en/reference/subsystems/llm-streaming.md +154 -12
  100. package/kb/site/en/reference/subsystems/permission-presets.md +6 -6
  101. package/kb/site/en/reference/subsystems/persistence.md +185 -175
  102. package/kb/site/en/reference/subsystems/plan.md +2 -2
  103. package/kb/site/en/reference/subsystems/sandbox.md +2 -0
  104. package/kb/site/en/reference/subsystems/schedule.md +9 -3
  105. package/kb/site/en/reference/subsystems/session-projection.md +115 -48
  106. package/kb/site/en/reference/subsystems/session-query.md +28 -14
  107. package/kb/site/en/reference/subsystems/session-reference.md +53 -8
  108. package/kb/site/en/reference/subsystems/session-telemetry.md +8 -8
  109. package/kb/site/en/reference/subsystems/session-title.md +6 -6
  110. package/kb/site/en/reference/subsystems/session.md +401 -99
  111. package/kb/site/en/reference/subsystems/settings.md +101 -6
  112. package/kb/site/en/reference/subsystems/skills.md +23 -0
  113. package/kb/site/en/reference/subsystems/slots.md +178 -0
  114. package/kb/site/en/reference/subsystems/spill.md +2 -2
  115. package/kb/site/en/reference/subsystems/storage.md +34 -3
  116. package/kb/site/en/reference/subsystems/subagent.md +122 -109
  117. package/kb/site/en/reference/subsystems/system-prompt.md +17 -4
  118. package/kb/site/en/reference/subsystems/token-meter.md +27 -12
  119. package/kb/site/en/reference/subsystems/tools.md +39 -39
  120. package/kb/site/en/reference/subsystems/typert.md +62 -55
  121. package/kb/site/en/reference/subsystems/user-questions.md +33 -33
  122. package/kb/site/en/reference/subsystems/web-client.md +98 -0
  123. package/kb/site/en/reference/subsystems/web-server.md +11 -5
  124. package/kb/site/en/reference/subsystems/web.md +7 -1
  125. package/kb/site/en/reference/subsystems/workspace.md +102 -9
  126. package/kb/site/en/reference/tool-catalog.md +86 -82
  127. package/kb/site/en/reference/tool-execution-pipeline.md +1 -1
  128. package/kb/site/guide/github-review.md +104 -0
  129. package/kb/site/guide/mcp-memory.md +103 -0
  130. package/kb/site/guide/network-proxy.md +87 -0
  131. package/kb/site/guide/providers.md +70 -17
  132. package/kb/site/guide/python-sdk.md +87 -41
  133. package/kb/site/guide/schedule.md +23 -0
  134. package/kb/site/reference/agent-lifecycle.md +6 -4
  135. package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +12 -10
  136. package/kb/site/reference/capability-seams.md +128 -73
  137. package/kb/site/reference/config-catalog.md +481 -360
  138. package/kb/site/reference/cookbook/adding-a-package.md +3 -4
  139. package/kb/site/reference/cookbook/adding-a-settings-card.md +12 -10
  140. package/kb/site/reference/cookbook/adding-a-tool.md +11 -4
  141. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -1
  142. package/kb/site/reference/cookbook/extension-cookbook.md +20 -17
  143. package/kb/site/reference/cordis-api/inherited.md +1 -1
  144. package/kb/site/reference/cordis-primer.md +2 -1
  145. package/kb/site/reference/index.md +30 -11
  146. package/kb/site/reference/persistence-catalog.md +148 -80
  147. package/kb/site/reference/subsystems/approval.md +10 -10
  148. package/kb/site/reference/subsystems/client-modules.md +58 -16
  149. package/kb/site/reference/subsystems/code-runtime.md +10 -6
  150. package/kb/site/reference/subsystems/commands.md +25 -16
  151. package/kb/site/reference/subsystems/compaction.md +11 -11
  152. package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +50 -24
  153. package/kb/site/reference/subsystems/core.md +156 -17
  154. package/kb/site/reference/subsystems/credentials.md +44 -3
  155. package/kb/site/reference/subsystems/filesystem.md +12 -2
  156. package/kb/site/reference/subsystems/goal.md +1 -1
  157. package/kb/site/reference/subsystems/index.md +7 -2
  158. package/kb/site/reference/subsystems/jobs.md +1 -1
  159. package/kb/site/reference/subsystems/llm-streaming.md +154 -12
  160. package/kb/site/reference/subsystems/permission-presets.md +5 -5
  161. package/kb/site/reference/subsystems/persistence.md +184 -174
  162. package/kb/site/reference/subsystems/plan.md +2 -2
  163. package/kb/site/reference/subsystems/schedule.md +9 -3
  164. package/kb/site/reference/subsystems/session-projection.md +115 -48
  165. package/kb/site/reference/subsystems/session-query.md +28 -14
  166. package/kb/site/reference/subsystems/session-reference.md +53 -8
  167. package/kb/site/reference/subsystems/session-telemetry.md +8 -8
  168. package/kb/site/reference/subsystems/session-title.md +6 -6
  169. package/kb/site/reference/subsystems/session.md +401 -99
  170. package/kb/site/reference/subsystems/settings.md +101 -6
  171. package/kb/site/reference/subsystems/skills.md +23 -0
  172. package/kb/site/reference/subsystems/slots.md +178 -0
  173. package/kb/site/reference/subsystems/spill.md +2 -2
  174. package/kb/site/reference/subsystems/storage.md +34 -3
  175. package/kb/site/reference/subsystems/subagent.md +122 -109
  176. package/kb/site/reference/subsystems/system-prompt.md +17 -4
  177. package/kb/site/reference/subsystems/token-meter.md +27 -12
  178. package/kb/site/reference/subsystems/tools.md +39 -39
  179. package/kb/site/reference/subsystems/typert.md +62 -55
  180. package/kb/site/reference/subsystems/user-questions.md +33 -33
  181. package/kb/site/reference/subsystems/web-client.md +98 -0
  182. package/kb/site/reference/subsystems/web-server.md +11 -5
  183. package/kb/site/reference/subsystems/web.md +7 -1
  184. package/kb/site/reference/subsystems/workspace.md +102 -9
  185. package/kb/site/reference/tool-catalog.md +85 -81
  186. package/kb/site/reference/tool-execution-pipeline.md +1 -1
  187. package/package.json +2 -2
  188. package/skills/dsh-plugin-dev-kb.md +8 -6
@@ -5,7 +5,7 @@ outline: [2,3]
5
5
 
6
6
  # 会话投影
7
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.zh.md);驱动、缓存与变更流约定:[包 README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/README.zh.md)。
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-session-controller](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/api/session-controller) 的历史尾页与 `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.zh.md);驱动、缓存与变更流约定:[包 README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/README.zh.md)。
9
9
 
10
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
11
 
@@ -31,10 +31,12 @@ interface ProjectionDefinition<
31
31
  /** Validates persisted state before it seeds a fold. */
32
32
  stateSchema: ZodType<S>
33
33
  /**
34
- * State for the empty log.
34
+ * State for the empty log and its immutable Session metadata.
35
+ * @param header - immutable metadata for the Session being projected.
36
+ * @param inheritedEventCount - exact fork-inherited prefix length.
35
37
  * @returns the initial state.
36
38
  */
37
- init(): NoInfer<S>
39
+ init(header: SessionHeader, inheritedEventCount: SessionLogOffset): NoInfer<S>
38
40
  /**
39
41
  * Pure transition: previous state + one committed event → next state. A
40
42
  * unit uninterested in an event MUST return the same state reference — an
@@ -49,7 +51,10 @@ interface ProjectionDefinition<
49
51
  /** Validates the wire payload before it leaves the host. */
50
52
  viewSchema: ZodType<SessionProjectionMap[K]>
51
53
  /**
52
- * State → wire payload (the read-side projection).
54
+ * State → wire payload (the read-side projection). The live drive keeps
55
+ * the two latest raw results and compares them with `Object.is`; an
56
+ * object-valued view must reuse its reference to suppress publication
57
+ * across internal-only state changes.
53
58
  * @param state - the current state.
54
59
  * @returns the whole current value for this unit's key.
55
60
  */
@@ -73,11 +78,11 @@ interface ProjectionDefinition<
73
78
  /**
74
79
  * One consistent read cut over every registered client-visible unit for one session.
75
80
  * `asOfSeq` is the shared watermark — the seq of the last event every value
76
- * reflects (`-1` for an empty log, mirroring `session/subscribed.lastSeq`).
81
+ * reflects (`-1` for an empty log).
77
82
  */
78
83
  interface ProjectionSnapshot {
79
84
  /** Seq of the last event the values reflect; -1 for an empty log. */
80
- asOfSeq: number
85
+ asOfSeq: SessionSeqCursor
81
86
  /** Whole current client value per registered key. */
82
87
  values: Partial<SessionProjectionMap>
83
88
  }
@@ -85,23 +90,23 @@ interface ProjectionSnapshot {
85
90
 
86
91
  ```ts type-equiv
87
92
  /**
88
- * Change-feed listener: one unit's value changed for one session. `value` is
89
- * the schema-validated `view` output; `seq` is the unit's watermark at
90
- * emission (the seq of the event that caused the change).
93
+ * Change-feed listener: one unit's raw `view` result changed by `Object.is`
94
+ * for one session. `value` is the schema-validated output; `seq` is the
95
+ * unit's watermark at emission (the seq of the event that caused the change).
91
96
  */
92
97
  type ProjectionChangeListener = (
93
98
  session: Session,
94
99
  key: Extract<keyof SessionProjectionMap, string>,
95
100
  value: unknown,
96
- seq: number,
101
+ seq: SessionSeq,
97
102
  ) => void
98
103
  ```
99
104
 
100
- `snapshot(session)` 完全同步:载体在切出页面切片的同一 tick 内读取它,因此 `asOfSeq` 使两次读取使用同一个序号。它只返回客户端视图,并在返回前通过各单元的 `viewSchema` 校验。`stateOf(session, key)` 可在不计算无关视图的情况下读取一份实时 host 状态;调用方不得修改这一借用引用。对于每个已提交事件,变更流会为每个状态*引用*已变化的客户端可见单元触发一次;状态未变时,`apply` 必须返回同一引用。
105
+ `snapshot(session)` 完全同步:载体在切出页面切片的同一 tick 内读取它,因此 `asOfSeq` 使两次读取使用同一个序号。它只返回客户端视图,并在返回前通过各单元的 `viewSchema` 校验。`stateOf(session, key)` 可在不计算无关视图的情况下读取一份实时 host 状态;调用方不得修改这一借用引用。state 引用变化时,注册表计算并缓存一次原始 view;只有该结果通过 `Object.is` 判定为变化时才触发变更流,对象 view 若要在仅内部 state 变化时抑制发布就必须保留引用。
101
106
 
102
107
  ## 注册表:`ctx.sessionProjections`
103
108
 
104
- `SessionProjectionRegistry`([签名](#ctxsessionprojections--sessionprojectionregistry))拥有驱动权:一份 `session/event` 订阅、对每个已注册单元即时调用 `apply`,以及每会话每单元的水位线(watermark)cell。cell 惰性构建:在事件流过之后才注册的单元,或比注册表更早的会话,都在首次触达(事件或读取)时从 `init` 出发在内存日志上折叠。注册是一个 effect,其 disposer 随调用方 fiber 走:领域插件卸载后,其 key(连同缓存的 cell)从后续驱动与快照中消失,客户端将其读作能力缺失;key 重复直接 throw。领域插件在 `ctx.inject(['sessionProjections'], …)` 下注册,因此不带注册表的 headless 组装完全不受影响。
109
+ `SessionProjectionRegistry`([签名](#ctxsessionprojections--sessionprojectionregistry))拥有驱动权:一份 `session/event` 订阅、对每个已注册单元即时调用 `apply`,以及每会话每单元的水位线(watermark)cell。cell 惰性构建:在事件流过之后才注册的单元,或比注册表更早的会话,都在首次触达(事件或读取)时从 `init` 出发在内存日志上折叠。注册是一个 effect,其 disposer 随调用方 fiber 走:领域插件卸载后,其 key(连同缓存的 cell)从后续驱动与快照中消失,客户端将其读作能力缺失;key 以不同 `stateVersion` 重复时直接 throw,同版本注册方则共享一个单元并被计数。领域插件在 `ctx.inject(['sessionProjections'], …)` 下注册,因此不带注册表的 headless 组装完全不受影响。
105
110
 
106
111
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
107
112
 
@@ -115,49 +120,84 @@ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnp
115
120
 
116
121
  ### `ctx.sessionProjectionCache` — `SessionProjectionCache`
117
122
 
118
- 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.
123
+ 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 three mandatory points — session creation, `turn/end`, and session disposal (the live-to-cold moment) — and serves the cached rows for a session header. Every durable write is fail-soft: failures log a warning and the cache self-heals on the next write.
119
124
 
120
125
  ```ts cordis-catalog
121
126
  /**
122
127
  * The zero-I/O listing read: whole values viewed straight from the stored
123
- * rows (version-matching keys only), each cut carried with its watermark
124
- * so a client value store can seed under its higher-seq-wins rule — as
125
- * stale as the last durable checkpoint but never wrong, and never from an
128
+ * rows (version-matching keys only), each cut carried with its watermark so
129
+ * a client value store can seed under its higher-seq-wins rule — as stale
130
+ * as the last durable checkpoint but never wrong, and never from an
126
131
  * unrelated log (the caller's header is the identity witness). Fresher
127
- * paths (the history tail baseline, {@link coldSnapshot}) supersede these
128
- * values whenever a session is actually opened.
132
+ * paths (the history tail baseline) supersede these values whenever a
133
+ * session is actually opened.
129
134
  * @param meta - the listed session's header (identity witness; no log read).
135
+ * @param inheritedEventCount - exact inherited prefix length that completes
136
+ * the checkpoint identity.
137
+ * @param keys - optional projection keys required by the caller's audience.
130
138
  * @returns the cut (`asOfSeq` = lowest served-row watermark), or
131
139
  * `undefined` when no usable row exists for this lifecycle.
132
140
  */
133
- cachedSnapshot(meta: SessionHeader): ProjectionSnapshot | undefined
141
+ cachedSnapshot( meta: SessionHeader, inheritedEventCount: SessionLogOffset, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
134
142
 
135
143
  /**
136
- * Durably checkpoint one live session NOW (both mandatory points call
144
+ * Read only a predecessor checkpoint's title as a zero-I/O listing hint.
145
+ *
146
+ * The authoritative Session header supplies the lifecycle identity. A cache
147
+ * checkpoint can lag that log but cannot lead it because writes flush the
148
+ * log first, so a matching predecessor title is a genuine (possibly stale)
149
+ * fact from this Session. The registry still requires the current title
150
+ * projection's row version and schema. No other predecessor projection is
151
+ * exposed: format normalization can change their current meaning, and the
152
+ * strict {@link cachedSnapshot} / hydration paths continue to reject them.
153
+ * @param meta - authoritative listed Session header.
154
+ * @param inheritedEventCount - exact inherited cut completing the lifecycle identity.
155
+ * @returns a title-only checkpoint view with `asOfSeq: -1`, or `undefined`
156
+ * when the record is current, newer, unrelated, missing, or incompatible
157
+ * with the title unit. The sentinel avoids reusing a sequence that a
158
+ * cardinality-changing Session migration may have remapped.
159
+ */
160
+ cachedPredecessorTitle( meta: SessionHeader, inheritedEventCount: SessionLogOffset, ): ProjectionSnapshot | undefined
161
+
162
+ /**
163
+ * Hydrate projection cells for an already-prepared Session without another
164
+ * persistence read. The cache seeds matching rows; the supplied exact log
165
+ * advances every unit to the observation cut. No checkpoint is written
166
+ * because the logical observation may contain recovery events not yet durable.
167
+ * @param session - exact unpublished Session retained by persistence.
168
+ * @param events - exact logical event prefix represented by the observation.
169
+ * @returns all projection values at the event cut.
170
+ */
171
+ hydratePrepared( session: Session, events: readonly SessionEvent[], ): ProjectionSnapshot
172
+
173
+ /**
174
+ * Durably checkpoint one live session NOW (all mandatory points call
137
175
  * this; tests and carriers may too). The registry cut is snapshotted at
138
- * this boundary (states are live references), then the whole record is
139
- * replaced. NOT fail-soft — callers on the fail-soft paths contain it.
176
+ * this boundary (states are live references), then the session's record is
177
+ * replaced on the domain's write chain. NOT fail-soft — callers on the
178
+ * fail-soft paths contain it.
140
179
  * @param session - the live session to checkpoint.
141
180
  * @returns resolution after durability and event emission.
142
181
  */
143
182
  async write(session: Session): Promise<void>
144
183
 
145
184
  /**
146
- * Cold-read one persisted session's projections with zero full-log load:
147
- * cached rows + a persistence `readFrom` tail from the registry's restore
148
- * floor, refolded by the registry and written back (fail-soft) so the next
149
- * cold read starts closer. A cache row invalidated by a shrunk log
150
- * (crash-repair truncation) triggers one full re-read from seq 0 the
151
- * ladder's slow rung, still no crash. Rejects when the session has no
152
- * persisted log (`not found` from the persistence seam).
153
- * @param id - the persisted session to read.
154
- * @param signal - optional cancellation for the persistence reads.
155
- * @returns the snapshot cut at the stored log end.
185
+ * Cold-read one session's projections from its complete log. Each unit is
186
+ * seeded from the identity-checked cached rows the registry skips `apply`
187
+ * for the already-folded prefix (events at or below the row's `seq`) and
188
+ * the refreshed checkpoint is written back (fail-soft, fire-and-forget), so
189
+ * the first cold read creates the cache row and later ones seed from it.
190
+ * The caller supplies the complete log in seq order: this service never
191
+ * consults the persistence layer.
192
+ * @param meta - the stored session header (identity witness).
193
+ * @param inheritedEventCount - exact inherited prefix length for projection initialization and identity.
194
+ * @param events - the session's complete log, in seq order.
195
+ * @returns the projection cut at the log end.
156
196
  */
157
- async coldSnapshot(id: SessionId, signal?: AbortSignal): Promise<ProjectionSnapshot>
197
+ coldSnapshot( meta: SessionHeader, inheritedEventCount: SessionLogOffset, events: readonly SessionEvent[], ): ProjectionSnapshot
158
198
  ```
159
199
 
160
- Types: [Session](./session.md) · [SessionHeader](./persistence.md) · [SessionId](./core.md)
200
+ Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md) · [SessionLogOffset](./session.md)
161
201
 
162
202
  Source: [`packages/session/session-projection-cache/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection-cache/src/index.ts)
163
203
 
@@ -165,7 +205,7 @@ Source: [`packages/session/session-projection-cache/src/index.ts`](https://githu
165
205
 
166
206
  ### `ctx.sessionProjections` — `SessionProjectionRegistry`
167
207
 
168
- `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 in a client-visible unit 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.
208
+ `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). A changed state reference computes the next client view; the change feed is notified only when its raw result changes by `Object.is`. 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. A host reader either declares `sessionProjections` in its plugin `inject` or fails explicitly when the registry or required key is absent. Contributors may preserve optional registration through `ctx.inject(['sessionProjections'], ...)`. 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.
169
209
 
170
210
  ```ts cordis-catalog
171
211
  /**
@@ -189,13 +229,14 @@ register< K extends Exclude<keyof SessionProjectionStateMap, keyof SessionProjec
189
229
  /**
190
230
  * Subscribe to the change feed. The registration is an effect on the
191
231
  * calling context's fiber.
192
- * @param listener - called once per client-visible unit whose state reference changed, per committed event.
232
+ * @param listener - called once per client-visible unit whose raw view changed by `Object.is`, per committed event.
193
233
  * @returns the exact disposer that unsubscribes.
194
234
  */
195
235
  onChanged(listener: ProjectionChangeListener): () => void
196
236
 
197
237
  /**
198
- * Read one unit's current host state without computing unrelated views.
238
+ * Read one unit's current host state after materializing every registered
239
+ * unit at the Session cursor. Unrelated wire views are not produced.
199
240
  * The returned value is live; callers must not mutate it.
200
241
  * @param session - the session whose state is read.
201
242
  * @param key - the registered unit key.
@@ -209,9 +250,20 @@ stateOf<K extends keyof SessionProjectionStateMap>( session: Session, key: K, ):
209
250
  * Fully synchronous — every value and `asOfSeq` reflect the same log
210
251
  * position. Each value passes its unit's `viewSchema` before leaving.
211
252
  * @param session - the session whose projection values are read.
212
- * @returns the snapshot; `values` is empty when no client-visible unit is registered.
253
+ * @param keys - optional client-visible outputs; state materialization remains complete.
254
+ * @returns the snapshot; `values` is empty when no selected client-visible unit is registered.
213
255
  */
214
- snapshot(session: Session): ProjectionSnapshot
256
+ snapshot( session: Session, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot
257
+
258
+ /**
259
+ * Read only already-materialized client-visible cells without folding history.
260
+ * Values may trail the live Session and are therefore hints, not a complete
261
+ * baseline. Missing cells are omitted.
262
+ * @param session - attached Session whose cached cells are inspected.
263
+ * @param keys - optional wire keys to view.
264
+ * @returns the lowest common cached cut, or `undefined` when no wire cell exists.
265
+ */
266
+ cachedSnapshot( session: Session, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): ProjectionSnapshot | undefined
215
267
 
216
268
  /**
217
269
  * State-level checkpoint of every persisted unit for one session, read
@@ -241,11 +293,11 @@ checkpoint(session: Session): ProjectionCheckpoint
241
293
  * yields an end below every watermark and the restore rejects for a full
242
294
  * re-read.
243
295
  * @param checkpoint - persisted rows for one session (possibly stale or empty).
244
- * @returns the seq to hand the persistence `readFrom`, or `undefined`
245
- * when no unit is registered (no read needed — {@link restore} would
246
- * serve empty values regardless).
296
+ * @returns the offset for the stored-log suffix read (`SessionHandle.read`),
297
+ * or `undefined` when no unit is registered (no read needed —
298
+ * {@link restore} would serve empty values regardless).
247
299
  */
248
- restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined
300
+ restoreFloor(checkpoint: ProjectionCheckpoint): SessionLogOffset | undefined
249
301
 
250
302
  /**
251
303
  * View a checkpoint's rows without any log read: for every registered
@@ -255,16 +307,17 @@ restoreFloor(checkpoint: ProjectionCheckpoint): number | undefined
255
307
  * fuller read path refolds it). The zero-I/O rung of the read ladder —
256
308
  * values are as stale as their rows, never wrong.
257
309
  * @param checkpoint - persisted rows for one session (possibly stale or empty).
310
+ * @param keys - optional wire keys to view.
258
311
  * @returns whole values per key with a usable row; empty when none.
259
312
  */
260
- viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>
313
+ viewCheckpoint( checkpoint: ProjectionCheckpoint, keys?: readonly Extract<keyof SessionProjectionMap, string>[], ): Partial<SessionProjectionMap>
261
314
 
262
315
  /**
263
316
  * Cold read: fold every persisted unit over a stored log suffix, seeding
264
317
  * each from its checkpoint row when usable — the one read recipe (cached
265
318
  * state + forward tail replay + `view`) applied without a live `Session`.
266
- * Call with the events returned by a persistence
267
- * `readFrom(id, restoreFloor(checkpoint))` and that same floor as
319
+ * Call with the stored events at or past `restoreFloor(checkpoint)` (a
320
+ * `SessionHandle.read` slice) and that same floor as
268
321
  * `baseSeq`; the floor's one-below anchor makes the supplied end honest,
269
322
  * so a shrunk log is detected here. A row is usable iff its
270
323
  * `ver` matches the live unit's `stateVersion`, it does not predate `baseSeq`
@@ -277,14 +330,28 @@ viewCheckpoint(checkpoint: ProjectionCheckpoint): Partial<SessionProjectionMap>
277
330
  * @param checkpoint - persisted rows for one session (possibly stale or empty).
278
331
  * @param events - the stored events with `seq >= baseSeq`, in seq order.
279
332
  * @param baseSeq - the seq `events` starts at (its first event's seq when non-empty).
333
+ * @param header - immutable metadata for the Session being restored.
334
+ * @param inheritedEventCount - exact fork-inherited prefix length supplied to unit initialization.
280
335
  * @returns the snapshot cut at the supplied log end (`asOfSeq` is the last
281
336
  * supplied event's seq, `baseSeq - 1` for an empty tail) plus the
282
337
  * refreshed checkpoint rows at that cut, ready for a durable write-back.
283
338
  */
284
- restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: number, ): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
339
+ restore( checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: SessionLogOffset, header: SessionHeader, inheritedEventCount: SessionLogOffset, ): { snapshot: ProjectionSnapshot; checkpoint: ProjectionCheckpoint }
340
+
341
+ /**
342
+ * Restore an exact cut and install its states on the supplied prepared Session.
343
+ * A later publication reuses these cells; ordinary live reads and event drive
344
+ * advance any constructor-owned suffix exactly once.
345
+ * @param session - exact prepared Session that owns the restored log prefix.
346
+ * @param checkpoint - persisted rows for this Session lifecycle.
347
+ * @param events - exact events at the observation cut.
348
+ * @param baseSeq - first supplied event sequence.
349
+ * @returns all projection values at the supplied cut.
350
+ */
351
+ hydrate( session: Session, checkpoint: ProjectionCheckpoint, events: readonly SessionEvent[], baseSeq: SessionLogOffset, ): ProjectionSnapshot
285
352
  ```
286
353
 
287
- Types: [Session](./session.md) · [SessionEvent](./session.md)
354
+ Types: [Session](./session.md) · [SessionEvent](./session.md) · [SessionHeader](./persistence.md) · [SessionLogOffset](./session.md)
288
355
 
289
356
  Source: [`packages/session/session-projection/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-projection/src/index.ts)
290
357
  <!-- END GENERATED cordis-surface -->
@@ -25,7 +25,7 @@ interface SessionRecord {
25
25
  header: SessionHeader
26
26
  /** Whether the id currently exists in `ctx.sessions`. */
27
27
  live: boolean
28
- /** Whether the active persistence backend currently materializes the id. */
28
+ /** Whether the active persistence backend currently lists the id, including a created-but-unmaterialized session it already observes. */
29
29
  persisted: boolean
30
30
  }
31
31
  ```
@@ -37,7 +37,9 @@ interface SessionRecord {
37
37
  interface SessionLogSnapshot {
38
38
  /** Cloned session header selected from the same observation as `events`. */
39
39
  session: SessionHeader
40
- /** Cloned contiguous raw events after persistence repair and replay validation. */
40
+ /** Exact number of fork-inherited events in the observed log. */
41
+ inheritedEventCount: SessionLogOffset
42
+ /** Cloned contiguous raw events after in-memory interrupted-turn balancing and replay validation. */
41
43
  events: SessionEvent[]
42
44
  }
43
45
  ```
@@ -47,8 +49,10 @@ interface SessionLogSnapshot {
47
49
  interface SessionSurfaceSnapshot {
48
50
  /** Cloned session header selected from the same corpus observation as `events`. */
49
51
  session: SessionHeader
52
+ /** Exact number of fork-inherited events in the observed log. */
53
+ inheritedEventCount: SessionLogOffset
50
54
  /** Highest raw-log seq included in the observation, or `null` for an empty log. */
51
- capturedThroughSeq: number | null
55
+ capturedThroughSeq: OptionalSessionSeq
52
56
  /** Cloned current surface events in model-history order. */
53
57
  events: SurfaceEvent[]
54
58
  }
@@ -93,7 +97,7 @@ interface SessionEventRecord {
93
97
  /** Session that owns the event. */
94
98
  sessionId: SessionId
95
99
  /** Monotonic event seq within the session. */
96
- seq: number
100
+ seq: SessionSeq
97
101
  /** Discriminant of the session event. */
98
102
  type: SessionEventType
99
103
  /** Event timestamp in Unix epoch milliseconds. */
@@ -141,7 +145,7 @@ interface SessionEventSearchDocument extends SessionEventRecord {
141
145
  }
142
146
  ```
143
147
 
144
- `ctx.sessionQuery.filterSessions(filters)` 会对完整的逻辑会话语料库应用 `SessionResultFilter`;`ctx.sessionQuery.filterEvents(sessionId, filters)` 按 seq 升序返回匹配的文档。消息、推理(reasoning)、工具调用和工具结果、被阻止的提示词、待办事项,以及失败和状态详情会纳入语义文本;结构事件和流分片则不会。
148
+ `ctx.sessionQuery.filterSessions(filters)` 会对完整的逻辑会话语料库应用 `SessionResultFilter`;`ctx.sessionQuery.filterEvents(sessionId, filters)` 按 seq 升序返回匹配的文档。消息、工具调用和工具结果、待办事项,以及失败和状态详情会纳入语义文本;推理(reasoning)块、被阻止的提示词、结构事件和流分片则不会。
145
149
 
146
150
  ## 全文搜索结果页
147
151
 
@@ -269,7 +273,7 @@ interface SessionEventReadRequest {
269
273
  /** Session that owns the target event. */
270
274
  sessionId: SessionId
271
275
  /** Target event seq. */
272
- seq: number
276
+ seq: SessionSeq
273
277
  /** Number of preceding raw events to include. */
274
278
  before?: number
275
279
  /** Number of following raw events to include. */
@@ -282,14 +286,16 @@ interface SessionEventReadRequest {
282
286
  interface SessionEventWindow {
283
287
  /** Cloned header for the live-preferred source read. */
284
288
  session: SessionHeader
289
+ /** Exact number of fork-inherited events in the observed log. */
290
+ inheritedEventCount: SessionLogOffset
285
291
  /** Full cloned target event. */
286
292
  target: SessionEvent
287
293
  /** Full cloned events from `startSeq` through `endSeq`. */
288
294
  events: SessionEvent[]
289
295
  /** First seq included in `events`. */
290
- startSeq: number
296
+ startSeq: SessionSeq
291
297
  /** Last seq included in `events`. */
292
- endSeq: number
298
+ endSeq: SessionSeq
293
299
  }
294
300
  ```
295
301
 
@@ -303,7 +309,7 @@ interface SessionEventTraceRequest {
303
309
  /** Session that owns the target event. */
304
310
  sessionId: SessionId
305
311
  /** Target event seq. */
306
- seq: number
312
+ seq: SessionSeq
307
313
  }
308
314
  ```
309
315
 
@@ -313,15 +319,15 @@ interface SessionEventTrace {
313
319
  /** Lightweight target record. */
314
320
  target: SessionEventRecord
315
321
  /** Immediate positional replacement event, when the target was shadowed. */
316
- replacedBy?: number
322
+ replacedBy?: SessionSeq
317
323
  /** Positional replacers from the immediate replacement to the final replacement. */
318
- replacementChain: number[]
324
+ replacementChain: SessionSeq[]
319
325
  /** Surface nodes directly removed when the target itself performed a replacement. */
320
- replacedEventSeqs: number[]
326
+ replacedEventSeqs: SessionSeq[]
321
327
  /** Earlier events cited directly as sources, in their recorded order. */
322
- sourceEventSeqs: number[]
328
+ sourceEventSeqs: SessionSeq[]
323
329
  /** Later events that directly cite the target as a source, in log order. */
324
- derivedEventSeqs: number[]
330
+ derivedEventSeqs: SessionSeq[]
325
331
  }
326
332
  ```
327
333
 
@@ -376,6 +382,14 @@ Unified live-preferred session query service.
376
382
  Exact reads, filters, and traces are backend-independent concrete behavior. A backend implements full-text observation, reconciliation, ranking, cursor generations, and query execution on the same `ctx.sessionQuery` service.
377
383
 
378
384
  ```ts cordis-catalog
385
+ /**
386
+ * Observe one exact live or prepared Session without a persistence listing preflight.
387
+ * @param sessionId - logical Session identity.
388
+ * @param options - cancellation and projection selection for this read.
389
+ * @returns a caller-owned observation lease.
390
+ */
391
+ observeSession( sessionId: SessionId, options: SessionObservationOptions = {}, ): Promise<SessionObservation>
392
+
379
393
  /**
380
394
  * Search the live-preferred logical corpus and group by session.
381
395
  * @param request - query text, metadata filters, page size, and cursor.
@@ -37,7 +37,7 @@ interface SessionReferenceInput {
37
37
  }
38
38
  ```
39
39
 
40
- `SessionReferenceCandidate` 是面向宿主的发现输出。存在最新会话标题时,它的 label 使用该标题;筛选仍只搜索 session id 和 cwd,绝不搜索 transcript(文本记录)。
40
+ `SessionReferenceCandidate` 是面向宿主的发现输出。存在最新会话标题时,它的 label 使用该标题;筛选搜索该 label 以及 session id 和 cwd,绝不搜索 transcript(文本记录)。
41
41
 
42
42
  ```ts type-equiv
43
43
  /** One host-facing candidate from exact session metadata. */
@@ -48,6 +48,12 @@ interface SessionReferenceCandidate {
48
48
  label: string
49
49
  /** Source session working directory, when recorded. */
50
50
  cwd?: string
51
+ /**
52
+ * True when {@link SessionReferenceCandidate.cwd} is recorded and equals the
53
+ * requesting agent's. Hosts that only surface a distinguishing location
54
+ * read this instead of comparing paths they never received.
55
+ */
56
+ sameWorkspace: boolean
51
57
  /** Source session creation time in Unix epoch milliseconds. */
52
58
  createdAt: number
53
59
  }
@@ -65,7 +71,31 @@ interface SessionReferenceMentionCandidate extends SessionReferenceCandidate {
65
71
 
66
72
  ## 准备后的消息
67
73
 
68
- 准备过程保留可读的当前消息内容,并最多返回一个聚合上下文。
74
+ 准备过程保留可读的当前消息内容,并最多返回一个聚合上下文。其持久 source 记录会把 `capturedThroughSeq` 保留为被引用 Session 原始 generation 中的坐标,绝不会把它重新解释为所在 Session 的 seq。`capturedFormatVersion` 记录该 generation;缺失表示已发布格式 v0。
75
+
76
+ ```ts type-equiv
77
+ /** Durable source session, cited event seqs, and snapshot facts for prepared cross-session context. */
78
+ interface SessionReferenceSource {
79
+ kind: 'session-reference'
80
+ /** Material lifted out of another session's log (`recall` context form). */
81
+ form: 'recall'
82
+ version: 1
83
+ references: {
84
+ sessionId: string
85
+ label: string
86
+ /** Source Session format generation; absence identifies version 0. */
87
+ capturedFormatVersion?: number
88
+ capturedThroughSeq: OptionalSessionSeq
89
+ compacted: boolean
90
+ originalMessages: number
91
+ retainedMessages: number
92
+ omittedMessages: number
93
+ omittedBytes: number
94
+ truncated: boolean
95
+ inputIndex: number
96
+ }[]
97
+ }
98
+ ```
69
99
 
70
100
  ```ts type-equiv
71
101
  /** Direct message content and optional referenced-session context. */
@@ -116,21 +146,32 @@ Host capability for cancellable file-reference discovery.
116
146
  * @returns deterministic path-only candidates.
117
147
  */
118
148
  abstract list( agent: Agent, query: string, signal: AbortSignal, ): Promise<FileReferenceCandidate[]>
149
+ ```
150
+
151
+ Types: [Agent](./core.md)
152
+
153
+ Source: [`packages/context/file-reference/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/context/file-reference/src/index.ts)
154
+
155
+ <a id="ctxsessionfilereferences--sessionfilereferences"></a>
156
+
157
+ ### `ctx.sessionFileReferences` — `SessionFileReferences`
158
+
159
+ Host Remote adapter over the composed file-reference provider.
119
160
 
161
+ ```ts cordis-catalog
120
162
  /**
121
- * Remote face of {@link list}; the decorator cannot mark the abstract
122
- * member, so this concrete adapter carries the identical contract.
123
- * @param agent - target agent whose session cwd bounds discovery.
163
+ * List file and directory candidates for one Agent's working directory.
164
+ * @param agent - target Agent resolved from the Session identity on the wire.
124
165
  * @param query - path text following `@` or `@"`.
125
166
  * @param signal - caller cancellation.
126
- * @returns deterministic path-only candidates.
167
+ * @returns deterministic path-only candidates from the composed provider.
127
168
  */
128
- @Remote('list') remoteExportList( agent: Agent, query: string, signal: AbortSignal, ): Promise<FileReferenceCandidate[]>
169
+ @Remote list( agent: Agent, query: string, signal: AbortSignal, ): Promise<FileReferenceCandidate[]>
129
170
  ```
130
171
 
131
172
  Types: [Agent](./core.md)
132
173
 
133
- Source: [`packages/context/file-reference/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/context/file-reference/src/index.ts)
174
+ Source: [`packages/api/session-controller/src/file-references.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/session-controller/src/file-references.ts)
134
175
 
135
176
  <a id="ctxsessionreferenceresolver--sessionreferenceresolver"></a>
136
177
 
@@ -141,6 +182,10 @@ Exact-read consumer that prepares immutable cross-session message context.
141
182
  ```ts cordis-catalog
142
183
  /**
143
184
  * List reference candidates, ranked by working-directory affinity.
185
+ *
186
+ * Discovery runs at keystroke rate, so a title only ever comes from a
187
+ * projection read: see {@link SessionReferenceResolver.projectedTitle} for
188
+ * which sessions can answer one and which fall back to their id.
144
189
  * @param agent - target agent; self is excluded and its cwd drives ranking.
145
190
  * @param query - optional case-insensitive session-id/cwd/title substring.
146
191
  * @param limit - optional positive result cap.
@@ -5,7 +5,7 @@ outline: [2,3]
5
5
 
6
6
  # 遥测(telemetry)
7
7
 
8
- 对外的会话上报拆分为一项[能力 seam](../capability-seams.md):Service Definition 与捕获协调器([dsh-session-telemetry](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry),`ctx.sessionTelemetry`)拥有捕获点、固定分片投影、`session-telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service Provider([dsh-session-telemetry-otel](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.zh.md)中定案;捕获点、游标与投影的约定见 [Service Definition README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/README.zh.md)。
8
+ 对外的会话上报拆分为一项[能力 seam](../capability-seams.md):Service Definition 与捕获协调器([dsh-session-telemetry](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry),`ctx.sessionTelemetry`)拥有完整的权威事件捕获、`session-telemetry/record` 脱敏 waterfall(瀑布式事件)、handoff 游标与最小后端约定;部署方加载的 Service Provider([dsh-session-telemetry-otel](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/session/session-telemetry-otel))则是原样配置的 OpenTelemetry JS SDK 日志流水线。它是一项可选能力,不属于 agent loop(智能体循环)主干,这里也没有任何内容会进入模型请求。边界公理(harness 的职责止于 `emit()`;批处理、重试、排队与丢失策略都属于上报 SDK)连同被否决的替代方案,均已在[复活 Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-23-session-telemetry-otel-revival.zh.md)中定案;捕获与游标约定见 [Service Definition README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/README.zh.md)。
9
9
 
10
10
  源码:[`packages/session/session-telemetry/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-telemetry/src/index.ts)
11
11
 
@@ -40,8 +40,9 @@ interface SessionTelemetryRecord {
40
40
  severity: SessionTelemetrySeverity
41
41
  /**
42
42
  * Identity attributes, deliberately minimal: ledger records carry
43
- * `session.id`, `event.type`, `event.seq`, plus `session.cwd` /
44
- * `session.parent_id` / `session.seed_length` when the header has them;
43
+ * `session.id`, `session.format_version`, `event.type`, `event.seq`, plus optional
44
+ * `session.cwd` / `session.parent_id`; a seeded Session also carries
45
+ * `session.seed_length` from its exact inherited event count;
45
46
  * ops records carry `telemetry.op`, `session.id`, and (for `agent-error`)
46
47
  * `agent.id`, `turn`, `step`, `error.name`. Anything recoverable from the
47
48
  * body is intentionally NOT duplicated here.
@@ -57,7 +58,7 @@ interface SessionTelemetryRecord {
57
58
  }
58
59
  ```
59
60
 
60
- 每个 `(turn, step)` 只发出第一条 `assistant/chunk`,即「流已开始」的信号;其余分片在捕获时丢弃,因此传输中的 `seq` 缺口是常态,绝不是数据丢失的信号。其他所有[会话事件](./session.md)类型都会完整透传,包括该 seam 从未听说过、由插件合并进来的事件类型。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(无游标的重新接管、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
61
+ 每条权威[会话事件](./session.md)都会完整透传为一条有序 ledger 记录,包括每个携带完整紧凑 stream 的 `assistant/message` `assistant/attempt`,以及该 seam 从未听说过、由插件合并进来的类型。进程本地 `agent/assistant-stream` frame 不进入该持久 feed。新 Session 对象会从 seq 0 回放完整日志,包括构造 seed 历史;重新收养同一对象时会从 handoff 游标之后继续。投递是尽力而为的:游标标记的是「已交接」而非「已送达」,记录可能丢失(崩溃、重载窗口)也可能重复(新对象回放、SDK 重试),因此接收端对 ledger 记录基于 `(session.id, session.format_version, event.seq)` 去重;ops 记录刻意省略这类标识——它们是用于告警的信号,而非用于累加的条目,重复被容忍而非被去重。
61
62
 
62
63
  ## 共享披露
63
64
 
@@ -67,9 +68,8 @@ interface SessionTelemetryRecord {
67
68
  /**
68
69
  * Deployment-selected session-sharing policy disclosed by a mounted
69
70
  * {@link SessionTelemetryBackend} backend to human-facing acknowledgement surfaces (the
70
- * `/feedback` command's confirmation text). The seam owns the vocabulary so
71
- * any backend can disclose a policy without depending on the OTel package;
72
- * the values mirror the OTel backend's serialized `SessionTelemetryMode` choices.
71
+ * `/feedback` command's confirmation text). The Service Definition owns the
72
+ * vocabulary so consumers and backends do not depend on a specific provider.
73
73
  */
74
74
  type SessionTelemetrySharingStatus = 'full' | 'feedback-only' | 'disabled'
75
75
  ```
@@ -126,7 +126,7 @@ interface SessionTelemetrySink {
126
126
 
127
127
  ## 脱敏 waterfall:`session-telemetry/record`
128
128
 
129
- 每条记录在投影与 `emit()` 之间都要经过 `session-telemetry/record` [waterfall](../cordis-primer.md#cordis-waterfall-semantics)([事件条目](#session-telemetryrecord--waterfall))。seam 自身不带任何规则:未挂载监听器时,记录以捕获时的原样到达后端;导出数据能干净到什么程度,恰恰取决于部署方挂载了什么规则。监听器通过变换 `next()` 的返回值来堆叠;不调用 `next()` 就返回,即替换其下方的全部逻辑;抛出异常的监听器会在协调器的隔离范围内以 fail-closed 方式扣下这一条记录。脱敏只作用于导出副本;权威会话日志永不改写。
129
+ 每条记录在权威事件副本与 `emit()` 之间都要经过 `session-telemetry/record` [waterfall](../cordis-primer.md#cordis-waterfall-semantics)([事件条目](#session-telemetryrecord--waterfall))。seam 自身不带任何规则:未挂载监听器时,记录以捕获时的原样到达后端;导出数据能干净到什么程度,恰恰取决于部署方挂载了什么规则。监听器通过变换 `next()` 的返回值来堆叠;不调用 `next()` 就返回,即替换其下方的全部逻辑;抛出异常的监听器会在协调器的隔离范围内以 fail-closed 方式扣下这一条记录。脱敏只作用于导出副本;权威会话日志永不改写。
130
130
 
131
131
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
132
132