dsh-plugin-dev-kb 1.0.7 → 1.0.9

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 (169) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.en.md +144 -0
  3. package/README.md +21 -7
  4. package/kb/INDEX.md +19 -5
  5. package/kb/README.md +11 -10
  6. package/kb/extra/AGENTS.md +4 -4
  7. package/kb/extra/cookbook/adding-a-vendored-package.md +2 -2
  8. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +2 -2
  9. package/kb/extra/deepseek-llm-api-wire-extensions.md +159 -0
  10. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +159 -0
  11. package/kb/extra/development.md +8 -14
  12. package/kb/extra/development.zh.md +8 -14
  13. package/kb/extra/event-producer-consumer.md +47 -41
  14. package/kb/extra/event-producer-consumer.zh.md +47 -41
  15. package/kb/extra/glossary.md +1 -1
  16. package/kb/extra/glossary.zh.md +1 -1
  17. package/kb/extra/graph-atlas.md +0 -2
  18. package/kb/extra/graph-atlas.zh.md +0 -2
  19. package/kb/extra/i18n/README.md +4 -4
  20. package/kb/extra/i18n/README.zh.md +4 -4
  21. package/kb/extra/module-graph.md +680 -413
  22. package/kb/extra/module-graph.zh.md +681 -414
  23. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +2 -2
  24. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +2 -2
  25. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +2 -2
  26. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +2 -2
  27. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +2 -2
  28. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +2 -2
  29. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +1 -1
  30. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +1 -1
  31. package/kb/extra/rescope.md +2 -2
  32. package/kb/extra/rescope.zh.md +2 -2
  33. package/kb/extra/subsystems/agent-team.md +24 -1
  34. package/kb/extra/subsystems/agent-team.zh.md +24 -1
  35. package/kb/extra/subsystems/attachment.md +12 -4
  36. package/kb/extra/subsystems/attachment.zh.md +12 -4
  37. package/kb/extra/subsystems/extensions.md +18 -0
  38. package/kb/extra/subsystems/extensions.zh.md +18 -0
  39. package/kb/extra/subsystems/feedback.md +2 -2
  40. package/kb/extra/subsystems/feedback.zh.md +2 -2
  41. package/kb/extra/subsystems/todo.md +32 -0
  42. package/kb/extra/subsystems/todo.zh.md +32 -0
  43. package/kb/extra/subsystems/webhook.md +70 -0
  44. package/kb/extra/subsystems/webhook.zh.md +70 -0
  45. package/kb/extra/testing.md +11 -10
  46. package/kb/extra/testing.zh.md +8 -7
  47. package/kb/meta/search-index.json +269 -161
  48. package/kb/meta/site-pages.txt +182 -168
  49. package/kb/meta/source.json +5 -5
  50. package/kb/meta/topics.md +14 -6
  51. package/kb/site/develop/basic/publish.md +2 -2
  52. package/kb/site/develop/basic/tool.md +1 -1
  53. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +4 -4
  54. package/kb/site/develop/framework/events.md +1 -1
  55. package/kb/site/develop/practice/dynamic-cordis.md +17 -0
  56. package/kb/site/develop/practice/llm-adapter.md +3 -3
  57. package/kb/site/en/develop/basic/publish.md +2 -2
  58. package/kb/site/en/develop/basic/tool.md +1 -1
  59. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +4 -4
  60. package/kb/site/en/develop/framework/events.md +1 -1
  61. package/kb/site/en/develop/practice/dynamic-cordis.md +17 -0
  62. package/kb/site/en/develop/practice/llm-adapter.md +3 -3
  63. package/kb/site/en/guide/github-review.md +104 -0
  64. package/kb/site/en/guide/mcp-memory.md +103 -0
  65. package/kb/site/en/guide/python-sdk.md +80 -34
  66. package/kb/site/en/guide/schedule.md +21 -0
  67. package/kb/site/en/reference/agent-lifecycle.md +1 -1
  68. package/kb/{extra → site/en/reference}/api-gateway.md +11 -9
  69. package/kb/site/en/reference/capability-seams.md +115 -67
  70. package/kb/site/en/reference/config-catalog.md +358 -164
  71. package/kb/site/en/reference/cookbook/adding-a-package.md +2 -2
  72. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +2 -2
  73. package/kb/site/en/reference/cookbook/adding-a-tool.md +11 -4
  74. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +1 -1
  75. package/kb/site/en/reference/cookbook/extension-cookbook.md +6 -6
  76. package/kb/site/en/reference/cordis-api/inherited.md +1 -1
  77. package/kb/site/en/reference/cordis-primer.md +2 -1
  78. package/kb/site/en/reference/index.md +19 -7
  79. package/kb/site/en/reference/persistence-catalog.md +91 -44
  80. package/kb/site/en/reference/subsystems/approval.md +10 -10
  81. package/kb/site/en/reference/subsystems/client-modules.md +58 -16
  82. package/kb/site/en/reference/subsystems/code-runtime.md +3 -3
  83. package/kb/site/en/reference/subsystems/compaction.md +2 -2
  84. package/kb/site/en/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +43 -24
  85. package/kb/site/en/reference/subsystems/core.md +70 -12
  86. package/kb/site/en/reference/subsystems/credentials.md +43 -3
  87. package/kb/site/en/reference/subsystems/filesystem.md +12 -2
  88. package/kb/site/en/reference/subsystems/index.md +6 -1
  89. package/kb/site/en/reference/subsystems/jobs.md +1 -1
  90. package/kb/site/en/reference/subsystems/llm-streaming.md +132 -11
  91. package/kb/site/en/reference/subsystems/permission-presets.md +1 -1
  92. package/kb/site/en/reference/subsystems/persistence.md +22 -3
  93. package/kb/site/en/reference/subsystems/plan.md +1 -1
  94. package/kb/site/en/reference/subsystems/session-projection.md +74 -33
  95. package/kb/site/en/reference/subsystems/session-query.md +9 -1
  96. package/kb/site/en/reference/subsystems/session-reference.md +28 -7
  97. package/kb/site/en/reference/subsystems/session-telemetry.md +2 -3
  98. package/kb/site/en/reference/subsystems/session.md +260 -41
  99. package/kb/site/en/reference/subsystems/settings.md +78 -1
  100. package/kb/site/en/reference/subsystems/skills.md +23 -0
  101. package/kb/site/en/reference/subsystems/slots.md +177 -0
  102. package/kb/site/en/reference/subsystems/spill.md +2 -2
  103. package/kb/site/en/reference/subsystems/storage.md +9 -1
  104. package/kb/site/en/reference/subsystems/subagent.md +90 -23
  105. package/kb/site/en/reference/subsystems/system-prompt.md +4 -4
  106. package/kb/site/en/reference/subsystems/token-meter.md +25 -10
  107. package/kb/site/en/reference/subsystems/tools.md +39 -39
  108. package/kb/site/en/reference/subsystems/typert.md +44 -37
  109. package/kb/site/en/reference/subsystems/user-questions.md +33 -33
  110. package/kb/site/en/reference/subsystems/web-client.md +98 -0
  111. package/kb/site/en/reference/subsystems/web-server.md +11 -5
  112. package/kb/site/en/reference/subsystems/web.md +7 -1
  113. package/kb/site/en/reference/subsystems/workspace.md +95 -2
  114. package/kb/site/en/reference/tool-catalog.md +76 -18
  115. package/kb/site/en/reference/tool-execution-pipeline.md +1 -1
  116. package/kb/site/guide/github-review.md +104 -0
  117. package/kb/site/guide/mcp-memory.md +103 -0
  118. package/kb/site/guide/python-sdk.md +87 -41
  119. package/kb/site/guide/schedule.md +21 -0
  120. package/kb/site/reference/agent-lifecycle.md +1 -1
  121. package/kb/{extra/api-gateway.zh.md → site/reference/api-gateway.md} +11 -9
  122. package/kb/site/reference/capability-seams.md +115 -67
  123. package/kb/site/reference/config-catalog.md +357 -163
  124. package/kb/site/reference/cookbook/adding-a-package.md +2 -2
  125. package/kb/site/reference/cookbook/adding-a-settings-card.md +2 -2
  126. package/kb/site/reference/cookbook/adding-a-tool.md +11 -4
  127. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +1 -1
  128. package/kb/site/reference/cookbook/extension-cookbook.md +6 -6
  129. package/kb/site/reference/cordis-api/inherited.md +1 -1
  130. package/kb/site/reference/cordis-primer.md +2 -1
  131. package/kb/site/reference/index.md +19 -7
  132. package/kb/site/reference/persistence-catalog.md +87 -40
  133. package/kb/site/reference/subsystems/approval.md +10 -10
  134. package/kb/site/reference/subsystems/client-modules.md +58 -16
  135. package/kb/site/reference/subsystems/code-runtime.md +3 -3
  136. package/kb/site/reference/subsystems/compaction.md +2 -2
  137. package/kb/site/reference/{cookbook/adding-a-conversation-node.md → subsystems/conversation.md} +43 -24
  138. package/kb/site/reference/subsystems/core.md +70 -12
  139. package/kb/site/reference/subsystems/credentials.md +43 -3
  140. package/kb/site/reference/subsystems/filesystem.md +12 -2
  141. package/kb/site/reference/subsystems/index.md +6 -1
  142. package/kb/site/reference/subsystems/jobs.md +1 -1
  143. package/kb/site/reference/subsystems/llm-streaming.md +132 -11
  144. package/kb/site/reference/subsystems/persistence.md +22 -3
  145. package/kb/site/reference/subsystems/plan.md +1 -1
  146. package/kb/site/reference/subsystems/session-projection.md +74 -33
  147. package/kb/site/reference/subsystems/session-query.md +9 -1
  148. package/kb/site/reference/subsystems/session-reference.md +28 -7
  149. package/kb/site/reference/subsystems/session-telemetry.md +2 -3
  150. package/kb/site/reference/subsystems/session.md +260 -41
  151. package/kb/site/reference/subsystems/settings.md +78 -1
  152. package/kb/site/reference/subsystems/skills.md +23 -0
  153. package/kb/site/reference/subsystems/slots.md +177 -0
  154. package/kb/site/reference/subsystems/spill.md +2 -2
  155. package/kb/site/reference/subsystems/storage.md +9 -1
  156. package/kb/site/reference/subsystems/subagent.md +90 -23
  157. package/kb/site/reference/subsystems/system-prompt.md +4 -4
  158. package/kb/site/reference/subsystems/token-meter.md +25 -10
  159. package/kb/site/reference/subsystems/tools.md +39 -39
  160. package/kb/site/reference/subsystems/typert.md +44 -37
  161. package/kb/site/reference/subsystems/user-questions.md +33 -33
  162. package/kb/site/reference/subsystems/web-client.md +98 -0
  163. package/kb/site/reference/subsystems/web-server.md +11 -5
  164. package/kb/site/reference/subsystems/web.md +7 -1
  165. package/kb/site/reference/subsystems/workspace.md +95 -2
  166. package/kb/site/reference/tool-catalog.md +76 -18
  167. package/kb/site/reference/tool-execution-pipeline.md +1 -1
  168. package/package.json +11 -3
  169. package/skills/dsh-plugin-dev-kb.md +8 -6
@@ -12,7 +12,7 @@ Every event type that can appear in a session's durable event log: the complete
12
12
 
13
13
  This file is GENERATED from source (`scripts/gen-persistence-catalog.ts`) and verified fresh by `pnpm run verify-persistence-catalog` (part of `doc-sync`) — do not edit it by hand. Declaration blocks retain the source declaration and nested property JSDoc, removing only the indentation imposed by a containing interface/module, and use a `ts persistence-catalog` fence (skipped by doc-typecheck because declarations reference types from their owning modules). Type names in a payload link to the page that documents them. See [the persistence-log-catalog Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/archived/process/2026-07-04-persistence-log-catalog.md).
14
14
 
15
- The envelope declarations below compose each event's `type`, monotonic `seq`, epoch-ms `time`, `data`, the optional `ignorable` unknown-type skip marker, and the conditional `surfaceOp`/`sourceEventSeqs` fields. **surface** marks a `SurfaceEventType` member: it produces an LLM message and declares how it joins the surface list. **log-only** marks everything else: a durable, replayable record with no derived-history contribution. Every payload is JSON-serializable (enforced at `Session.append`), and the whole format is pinned at `SESSION_FORMAT_VERSION = 0` — pre-release, no compatibility implied ([the version stance](./subsystems/persistence.md)). Scope: the packages in this repo; a downstream plugin can merge further event types, which are outside this catalog by construction.
15
+ The envelope declarations below compose each event's `type`, monotonic `seq`, epoch-ms `time`, `data`, and the conditional `surfaceOp`/`sourceEventSeqs` fields. **surface** marks a `SurfaceEventType` member: it produces an LLM message and declares how it joins the surface list. **log-only** marks everything else: a durable, replayable record with no derived-history contribution. Every payload is JSON-serializable (enforced at `Session.append`), and the whole format is pinned at `SESSION_FORMAT_VERSION = 0` — pre-release, no compatibility implied ([the version stance](./subsystems/persistence.md)). Scope: the packages in this repo; a downstream plugin can merge further event types, which are outside this catalog by construction.
16
16
 
17
17
  ## Event envelope
18
18
 
@@ -68,17 +68,6 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
68
68
  /** Unix epoch milliseconds. */
69
69
  time: number
70
70
  data: SessionEventMap[K]
71
- /**
72
- * Marks an event a reader may safely skip when it does not recognize
73
- * `type`. Absent means required: a reader meeting an unrecognized type
74
- * without this marker MUST refuse to reconstruct the session instead of
75
- * silently dropping the event, because an unrecognized required event may
76
- * change how the rest of the log is interpreted. A writer sets `true` only
77
- * on purely informational records whose loss cannot affect reconstruction;
78
- * defaulting to required means a forgotten marker over-refuses (an
79
- * inconvenience) rather than silently resuming a gutted session.
80
- */
81
- ignorable?: true
82
71
  } & (K extends SurfaceEventType ? {
83
72
  /**
84
73
  * Seq numbers of earlier events that this event cites as sources
@@ -95,7 +84,7 @@ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
95
84
  }[T]
96
85
  ```
97
86
 
98
- Sources: [`packages/core/session/src/types.ts:340`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:347`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:376`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:408`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
87
+ Sources: [`packages/core/session/src/types.ts:328`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:335`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:364`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts) · [`packages/core/session/src/types.ts:396`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
99
88
 
100
89
  ## Events
101
90
 
@@ -120,7 +109,7 @@ Sources: [`packages/core/session/src/types.ts:340`](https://github.com/deepseek-
120
109
  }
121
110
  ```
122
111
 
123
- Source: [`packages/core/agent/src/types.ts:19`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/types.ts)
112
+ Source: [`packages/core/agent/src/types.ts:38`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/agent/src/types.ts)
124
113
 
125
114
  ### `agent-preset/*`
126
115
 
@@ -138,7 +127,7 @@ Source: [`packages/core/agent/src/types.ts:19`](https://github.com/deepseek-ai/d
138
127
  'agent-preset/selected': { agentPreset: string }
139
128
  ```
140
129
 
141
- Source: [`packages/preset/agent-presets/src/session.ts:26`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/preset/agent-presets/src/session.ts)
130
+ Source: [`packages/preset/agent-presets/src/session.ts:28`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/preset/agent-presets/src/session.ts)
142
131
 
143
132
  ### `approval/*`
144
133
 
@@ -158,14 +147,14 @@ Source: [`packages/preset/agent-presets/src/session.ts:26`](https://github.com/d
158
147
  'approval/asked': {
159
148
  id: ApprovalRequestId
160
149
  toolName: string
161
- callId?: CallId
150
+ callId?: ToolCallId
162
151
  reason?: string
163
152
  }
164
153
  ```
165
154
 
166
- Types: [CallId](./subsystems/core.md)
155
+ Types: [ToolCallId](./subsystems/core.md)
167
156
 
168
- Source: [`packages/interaction/user-approval/src/index.ts:44`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/index.ts)
157
+ Source: [`packages/interaction/user-approval/src/types.ts:44`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/types.ts)
169
158
 
170
159
  <a id="approvaldecided--log-only"></a>
171
160
 
@@ -183,7 +172,7 @@ Source: [`packages/interaction/user-approval/src/index.ts:44`](https://github.co
183
172
  }
184
173
  ```
185
174
 
186
- Source: [`packages/interaction/user-approval/src/index.ts:55`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/index.ts)
175
+ Source: [`packages/interaction/user-approval/src/types.ts:55`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/types.ts)
187
176
 
188
177
  <a id="approvalpolicy--log-only"></a>
189
178
 
@@ -205,7 +194,7 @@ Source: [`packages/interaction/user-approval/src/index.ts:55`](https://github.co
205
194
  }
206
195
  ```
207
196
 
208
- Source: [`packages/interaction/user-approval/src/index.ts:67`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/index.ts)
197
+ Source: [`packages/interaction/user-approval/src/index.ts:32`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/index.ts)
209
198
 
210
199
  ### `assistant/*`
211
200
 
@@ -220,7 +209,7 @@ Source: [`packages/interaction/user-approval/src/index.ts:67`](https://github.co
220
209
 
221
210
  Types: [StreamChunk](./subsystems/llm-streaming.md)
222
211
 
223
- Source: [`packages/core/session/src/types.ts:266`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
212
+ Source: [`packages/core/session/src/types.ts:251`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
224
213
 
225
214
  <a id="assistantmessage--surface"></a>
226
215
 
@@ -242,7 +231,7 @@ Source: [`packages/core/session/src/types.ts:266`](https://github.com/deepseek-a
242
231
 
243
232
  Types: [TokenUsage](./subsystems/llm-streaming.md)
244
233
 
245
- Source: [`packages/core/session/src/types.ts:277`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
234
+ Source: [`packages/core/session/src/types.ts:262`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
246
235
 
247
236
  ### `command/*`
248
237
 
@@ -503,6 +492,22 @@ Source: [`packages/llm/llm-retry/src/types.ts:9`](https://github.com/deepseek-ai
503
492
 
504
493
  Source: [`packages/llm/llm-retry/src/types.ts:11`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/llm/llm-retry/src/types.ts)
505
494
 
495
+ ### `model/*`
496
+
497
+ <a id="modelselection--log-only"></a>
498
+
499
+ #### `model/selection` — log-only
500
+
501
+ ```ts persistence-catalog
502
+ /**
503
+ * Complete validated model selection requested for subsequent prompt
504
+ * assembly. Log-only: it never enters derived model history.
505
+ */
506
+ 'model/selection': ModelSelection
507
+ ```
508
+
509
+ Source: [`packages/api/session-controller/src/types.ts:40`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/session-controller/src/types.ts)
510
+
506
511
  ### `permission/*`
507
512
 
508
513
  <a id="permissionpreset--log-only"></a>
@@ -552,7 +557,7 @@ Source: [`packages/plan/plan-mode/src/index.ts:53`](https://github.com/deepseek-
552
557
  'request/context': RequestContext
553
558
  ```
554
559
 
555
- Source: [`packages/core/session/src/types.ts:313`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
560
+ Source: [`packages/core/session/src/types.ts:301`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
556
561
 
557
562
  <a id="requestheader--log-only"></a>
558
563
 
@@ -563,10 +568,15 @@ Source: [`packages/core/session/src/types.ts:313`](https://github.com/deepseek-a
563
568
  * Full header for the next request, appended inside its step before dispatch.
564
569
  * It is log-only; the latest snapshot reconstructs the request header.
565
570
  */
566
- 'request/header': { header: EpochHeader; reason: RequestHeaderReason }
571
+ 'request/header': {
572
+ header: EpochHeader
573
+ reason: RequestHeaderReason
574
+ /** A changed header also begins a distinct model-message series. */
575
+ startsSeries?: true
576
+ }
567
577
  ```
568
578
 
569
- Source: [`packages/core/session/src/types.ts:308`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
579
+ Source: [`packages/core/session/src/types.ts:291`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
570
580
 
571
581
  ### `sandbox/*`
572
582
 
@@ -641,7 +651,7 @@ Source: [`packages/schedule/schedule/src/types.ts:219`](https://github.com/deeps
641
651
  'session/end-seed': Record<string, never>
642
652
  ```
643
653
 
644
- Source: [`packages/core/session/src/types.ts:336`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
654
+ Source: [`packages/core/session/src/types.ts:324`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
645
655
 
646
656
  <a id="sessiontitle--log-only"></a>
647
657
 
@@ -672,6 +682,24 @@ Types: [SessionTitleLlmRequestEventData](./subsystems/session-title.md)
672
682
 
673
683
  Source: [`packages/session/session-title-llm/src/index.ts:43`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-title-llm/src/index.ts)
674
684
 
685
+ ### `session-log-deepseek/*`
686
+
687
+ <a id="session-log-deepseekdelivery-accepted--log-only"></a>
688
+
689
+ #### `session-log-deepseek/delivery-accepted` — log-only
690
+
691
+ ```ts persistence-catalog
692
+ /** Records that the configured endpoint accepted one delivery through `throughSeq`. */
693
+ 'session-log-deepseek/delivery-accepted': {
694
+ /** Session identity the accepted delivery carried; inherited fork markers retain the parent's id. */
695
+ sessionId: import('@deepseek-ai/dsh-session/types').SessionId
696
+ /** Last canonical event included in the accepted request. */
697
+ throughSeq: number
698
+ }
699
+ ```
700
+
701
+ Source: [`packages/session/session-log-deepseek/src/types.ts:26`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-log-deepseek/src/types.ts)
702
+
675
703
  ### `step/*`
676
704
 
677
705
  <a id="stepend--log-only"></a>
@@ -683,7 +711,7 @@ Source: [`packages/session/session-title-llm/src/index.ts:43`](https://github.co
683
711
  'step/end': { turn: number; step: number }
684
712
  ```
685
713
 
686
- Source: [`packages/core/session/src/types.ts:256`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
714
+ Source: [`packages/core/session/src/types.ts:241`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
687
715
 
688
716
  <a id="stepstart--log-only"></a>
689
717
 
@@ -694,7 +722,7 @@ Source: [`packages/core/session/src/types.ts:256`](https://github.com/deepseek-a
694
722
  'step/start': { turn: number; step: number }
695
723
  ```
696
724
 
697
- Source: [`packages/core/session/src/types.ts:254`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
725
+ Source: [`packages/core/session/src/types.ts:239`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
698
726
 
699
727
  ### `subagent/*`
700
728
 
@@ -713,7 +741,26 @@ Source: [`packages/core/session/src/types.ts:254`](https://github.com/deepseek-a
713
741
  'subagent/descriptor': SubagentDescriptorData
714
742
  ```
715
743
 
716
- Source: [`packages/subagent/subagent/src/descriptor.ts:37`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/descriptor.ts)
744
+ Source: [`packages/subagent/subagent/src/descriptor.ts:38`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/subagent/src/descriptor.ts)
745
+
746
+ <a id="subagentmodel-selection-policy--log-only"></a>
747
+
748
+ #### `subagent/model-selection-policy` — log-only
749
+
750
+ ```ts persistence-catalog
751
+ /**
752
+ * Records that this session's delegation tool exposes child provider,
753
+ * model, and reasoning-effort selection. Appended before the first model
754
+ * request; absence means the fixed-route definition. Log-only: it carries
755
+ * no `surfaceOp` and never enters model history.
756
+ */
757
+ 'subagent/model-selection-policy': {
758
+ /** Exact routes this Session may select explicitly for a child. */
759
+ allowedModels: AllowedModelRoute[]
760
+ }
761
+ ```
762
+
763
+ Source: [`packages/subagent/tool-subagent/src/model-selection-state.ts:14`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/subagent/tool-subagent/src/model-selection-state.ts)
717
764
 
718
765
  ### `team/*`
719
766
 
@@ -728,7 +775,7 @@ Source: [`packages/subagent/subagent/src/descriptor.ts:37`](https://github.com/d
728
775
 
729
776
  Types: [TeamId](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md) · [TeamMemberSnapshot](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md)
730
777
 
731
- Source: [`packages/experimental/agent-team/src/types.ts:206`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
778
+ Source: [`packages/experimental/agent-team/src/types.ts:223`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
732
779
 
733
780
  <a id="teammessagedelivered--log-only"></a>
734
781
 
@@ -746,7 +793,7 @@ Source: [`packages/experimental/agent-team/src/types.ts:206`](https://github.com
746
793
 
747
794
  Types: [TeamId](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md) · [TeamMessageId](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md)
748
795
 
749
- Source: [`packages/experimental/agent-team/src/types.ts:212`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
796
+ Source: [`packages/experimental/agent-team/src/types.ts:229`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
750
797
 
751
798
  <a id="teammessagequeued--log-only"></a>
752
799
 
@@ -759,7 +806,7 @@ Source: [`packages/experimental/agent-team/src/types.ts:212`](https://github.com
759
806
 
760
807
  Types: [TeamId](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md) · [TeamMessageSnapshot](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md)
761
808
 
762
- Source: [`packages/experimental/agent-team/src/types.ts:210`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
809
+ Source: [`packages/experimental/agent-team/src/types.ts:227`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
763
810
 
764
811
  <a id="teamtask--log-only"></a>
765
812
 
@@ -772,7 +819,7 @@ Source: [`packages/experimental/agent-team/src/types.ts:210`](https://github.com
772
819
 
773
820
  Types: [TeamId](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md) · [TeamTaskSnapshot](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/agent-team.md)
774
821
 
775
- Source: [`packages/experimental/agent-team/src/types.ts:208`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
822
+ Source: [`packages/experimental/agent-team/src/types.ts:225`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/agent-team/src/types.ts)
776
823
 
777
824
  ### `todo/*`
778
825
 
@@ -785,9 +832,9 @@ Source: [`packages/experimental/agent-team/src/types.ts:208`](https://github.com
785
832
  'todo/write': { todos: TodoItem[] }
786
833
  ```
787
834
 
788
- Types: [TodoItem](./subsystems/session.md)
835
+ Types: [TodoItem](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/todo.md)
789
836
 
790
- Source: [`packages/core/session/src/types.ts:303`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
837
+ Source: [`packages/todo/tool-todo/src/types.ts:31`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/todo/tool-todo/src/types.ts)
791
838
 
792
839
  ### `tool/*`
793
840
 
@@ -801,12 +848,12 @@ Source: [`packages/core/session/src/types.ts:303`](https://github.com/deepseek-a
801
848
  * JSON string exactly as the model produced it (unparsed). `callId` pairs the
802
849
  * call with its `tool/result`.
803
850
  */
804
- 'tool/call': { turn: number; step: number; callId: CallId; name: string; arguments: string }
851
+ 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string }
805
852
  ```
806
853
 
807
- Types: [CallId](./subsystems/core.md)
854
+ Types: [ToolCallId](./subsystems/core.md)
808
855
 
809
- Source: [`packages/core/session/src/types.ts:283`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
856
+ Source: [`packages/core/session/src/types.ts:268`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
810
857
 
811
858
  <a id="toolcode-dispatch--log-only"></a>
812
859
 
@@ -828,7 +875,7 @@ Source: [`packages/core/session/src/types.ts:283`](https://github.com/deepseek-a
828
875
  * before returning), so its execution-enclosure relation holds by
829
876
  * construction.
830
877
  */
831
- 'tool/code-dispatch': CodeDispatchEventData
878
+ 'tool/code-dispatch': PtcDispatchEventData
832
879
  ```
833
880
 
834
881
  Source: [`packages/core/tools/src/types.ts:56`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/types.ts)
@@ -851,7 +898,7 @@ Source: [`packages/core/tools/src/types.ts:56`](https://github.com/deepseek-ai/d
851
898
  * with `tool/code-dispatch` by `subCallId` (timing = the two events'
852
899
  * `time` fields).
853
900
  */
854
- 'tool/code-dispatch-start': CodeDispatchStartEventData
901
+ 'tool/code-dispatch-start': PtcDispatchStartEventData
855
902
  ```
856
903
 
857
904
  Source: [`packages/core/tools/src/types.ts:40`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/tools/src/types.ts)
@@ -881,7 +928,7 @@ Source: [`packages/core/tools/src/types.ts:40`](https://github.com/deepseek-ai/d
881
928
  }
882
929
  ```
883
930
 
884
- Source: [`packages/core/session/src/types.ts:295`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
931
+ Source: [`packages/core/session/src/types.ts:280`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
885
932
 
886
933
  ### `tool-workflow/*`
887
934
 
@@ -961,7 +1008,7 @@ Source: [`packages/workflow/tool-workflow/src/types.ts:47`](https://github.com/d
961
1008
 
962
1009
  Types: [TurnEndReason](./subsystems/session.md)
963
1010
 
964
- Source: [`packages/core/session/src/types.ts:252`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
1011
+ Source: [`packages/core/session/src/types.ts:237`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
965
1012
 
966
1013
  <a id="turnstart--log-only"></a>
967
1014
 
@@ -977,7 +1024,7 @@ Source: [`packages/core/session/src/types.ts:252`](https://github.com/deepseek-a
977
1024
  'turn/start': { turn: number }
978
1025
  ```
979
1026
 
980
- Source: [`packages/core/session/src/types.ts:243`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
1027
+ Source: [`packages/core/session/src/types.ts:228`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
981
1028
 
982
1029
  ### `user/*`
983
1030
 
@@ -996,7 +1043,7 @@ Source: [`packages/core/session/src/types.ts:243`](https://github.com/deepseek-a
996
1043
  'user/message': UserMessage
997
1044
  ```
998
1045
 
999
- Source: [`packages/core/session/src/types.ts:264`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
1046
+ Source: [`packages/core/session/src/types.ts:249`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/core/session/src/types.ts)
1000
1047
 
1001
1048
  ### `web/*`
1002
1049
 
@@ -33,7 +33,7 @@ type ApprovalOutcome = 'allowed-once' | 'rejected' | 'cancelled' | 'unavailable'
33
33
 
34
34
  ## Per-session policy
35
35
 
36
- `ApprovalPolicy` determines what happens before interactive answerers run. `ask` delegates to the composed answerer chain, whose no-answer default is `unavailable`; `never` deterministically returns `rejected` without dispatching any answerer. The effective value is the last `approval/policy` event in the session log, falling back to the service config. `setApprovalPolicy(session, policy)` is the single write path, so replay reconstructs the override.
36
+ `ApprovalPolicy` determines what happens before interactive answerers run. `ask` delegates to the composed answerer chain, whose no-answer default is `unavailable`; `never` deterministically returns `rejected` without dispatching any answerer. The effective value is the last `approval/policy` event in the session log, falling back to the service config. Consumers read it with `ctx.approval.effectivePolicy(session)`; `setApprovalPolicy(session, policy)` is the single write path, so replay reconstructs the override.
37
37
 
38
38
  ```ts type-equiv
39
39
  /**
@@ -60,7 +60,7 @@ Both policies contribute their complete current meaning to the cache-safe runtim
60
60
  * Readonly same-process permission question. `callId` links to an already
61
61
  * presented tool call, so arguments are not duplicated here.
62
62
  */
63
- interface ApprovalRequest {
63
+ interface ApprovalRequest extends ApprovalRequestEvent {
64
64
  /**
65
65
  * The agent on whose behalf the question is asked. Routes the question (a
66
66
  * UI answerer only answers for agents it owns) and receives the audit
@@ -73,7 +73,7 @@ interface ApprovalRequest {
73
73
  * The exact tool call being decided, when the asker has one — lets a UI
74
74
  * attach the prompt to the tool call it already streamed.
75
75
  */
76
- readonly callId?: CallId
76
+ readonly callId?: ToolCallId
77
77
  /** The asker's human-readable explanation of WHY it is asking. */
78
78
  readonly reason?: string
79
79
  /**
@@ -154,20 +154,20 @@ Source: [`packages/interaction/user-approval/src/index.ts`](https://github.com/d
154
154
 
155
155
  #### `approval/request` — waterfall
156
156
 
157
- Ask composed answerers for one decision. Return an outcome to claim the request or call `next()`; failure yields the fail-closed default. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
157
+ Ask composed answerers for one decision. Return an outcome to claim the request or call `next()` to delegate. Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
158
158
 
159
159
  ```ts cordis-catalog
160
160
  /**
161
161
  * Ask composed answerers for one decision. Return an outcome to claim the
162
- * request or call `next()`; failure yields the fail-closed default.
163
- * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
164
- * @param req - the pending decision (agent, tool identity, reason, signal).
162
+ * request or call `next()` to delegate. Scope-filtered dispatch
163
+ * (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent.
164
+ * @param req - pending approval request.
165
165
  * @mode waterfall
166
166
  */
167
- 'approval/request'(this: Scoped<ApprovalService>, req: ApprovalRequest, next: () => Promise<ApprovalOutcome>): Promise<ApprovalOutcome>
167
+ 'approval/request'( this: Scoped<Agent>, req: ApprovalRequestEvent, next: () => Promise<ApprovalOutcome>, ): Promise<ApprovalOutcome>
168
168
  ```
169
169
 
170
- Types: [Scoped](./scope.md)
170
+ Types: [Agent](./core.md) · [Scoped](./scope.md)
171
171
 
172
- Source: [`packages/interaction/user-approval/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/index.ts)
172
+ Source: [`packages/interaction/user-approval/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/interaction/user-approval/src/types.ts)
173
173
  <!-- END GENERATED cordis-surface -->
@@ -5,32 +5,31 @@ outline: [2,3]
5
5
 
6
6
  # Client Modules
7
7
 
8
- The web plugin table: the Node half of the client module system in [dsh-client-modules](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/modules), provided as `ctx.clientModules` (`ClientModuleRegistry`). It scans the host Loader's entries for packages declaring `dsh.client`, composes the `window.__DSH_BOOT__` entry graph, serves each bundle at `/plugins/<id>/client.js`, and answers every index-injection collection with the boot manifest rows — the four faces of one service. It is an optional capability of the web GUI stack, not part of the agent-loop spine, and it is a consumer of [dsh-host-webserver](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/host/webserver): the carrier described in [web-server.md](./web-server.md) supplies the prefix route and the `webserver/index-inject` event this service answers. The same package's browser half (`ctx.modules`, the lazy-CJS module table that fetches and materializes these bundles) is kernel machinery documented in the [package README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/modules/README.md), not here.
8
+ The web plugin table: the Node half of the client module system in [dsh-client-modules](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/client/modules), provided as `ctx.clientModules` (`ClientModuleRegistry`). It scans the host Loader's entries for packages declaring `dsh.client`, composes the `window.__DSH_BOOT__` entry graph, serves versioned one-or-more-resource combo scripts under `/plugins`, and answers every index-injection collection with the boot protocol rows — the four faces of one service. It is an optional capability of the web GUI stack, not part of the agent-loop spine, and it is a consumer of [dsh-host-webserver](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/host/webserver): the carrier described in [web-server.md](./web-server.md) supplies the prefix route and the `webserver/index-inject` event this service answers. The same package's browser half (`ctx.modules`, the lazy-CJS module table that fetches and materializes these bundles) is kernel machinery documented in the [package README](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/modules/README.md), not here.
9
9
 
10
10
  Source: [`packages/client/modules/src/client/manifest.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/modules/src/client/manifest.ts)
11
11
 
12
12
  ## The wire
13
13
 
14
- The graph is the wire single source between the Node and browser halves: the host composes `WebBootEntry` rows from scanned packages, publishes the graph as a `global` injection row rendered ahead of later script rows (`globalThis["__DSH_BOOT__"]`, with `<` escaped so plugin-controlled strings cannot break out of the script element), and the shell parses it before booting anything. A page without a valid manifest cannot boot the browser-side parser throws loud on a missing or malformed graph.
14
+ The graph is the wire single source between the Node and browser halves. The host composes `WebBootEntry` rows and `WebBootBatch` descriptors from scanned packages, then contributes the registration facade, application preloads, bootstrap scripts, and graph global to the structured index-injection table before the Vite entry. The `global` row renders as `globalThis["__DSH_BOOT__"]` with `<` escaped so plugin-controlled strings cannot break out of the script element. A page without a valid manifest cannot boot: the browser parser rejects malformed rows or batches, unknown members, and entries without exactly one initial combo descriptor.
15
15
 
16
16
  ```ts type-equiv
17
17
  /**
18
18
  * One composed client entry pushed by the host (a graph row). Wire
19
19
  * single source: the host node half (package root) produces this same shape.
20
- * `immediately` marks stage-one prefetch; `inject` is informational graph
21
- * metadata (the authoritative edges live in each package's `dsh.client`
22
- * declaration and reach fibers through entry creation). `external` carries
23
- * module-graph edges: unlike `inject`, they constrain code arrival because
24
- * `require` is synchronous (see {@link WebBootGraph.entries}).
20
+ * `immediately` marks stage-one prefetch. `inject` names package rows whose
21
+ * factories must arrive before this row materializes, while Cordis separately
22
+ * uses the same package edges to compose entries. `external` carries exact
23
+ * non-inject module requests (see {@link WebBootGraph.entries}).
25
24
  */
26
25
  interface WebBootEntry {
27
26
  /** Entry name == package name. */
28
27
  id: string
29
- /** Bundle endpoint, '/plugins/<id>/client.js?rev=<rev>'. */
28
+ /** Revisioned single-resource combo endpoint used by HMR. */
30
29
  url: string
31
- /** Bundle content hash (cache-busting consistency anchor). */
30
+ /** Opaque plugin-artifact revision used for HMR cache busting. */
32
31
  rev: string
33
- /** Package-name dependency edges, informational (preflight display / HMR diffing). */
32
+ /** Package-name dependency edges used for factory arrival and plugin composition. */
34
33
  inject?: string[]
35
34
  /** Stage-one prefetch mark: load the script for factory registration during module-face boot. */
36
35
  immediately?: boolean
@@ -39,6 +38,25 @@ interface WebBootEntry {
39
38
  }
40
39
  ```
41
40
 
41
+ ```ts type-equiv
42
+ /** Initial scheduling phase for one content-addressed combo script. */
43
+ type WebBootBatchPhase = 'bootstrap' | 'application'
44
+ ```
45
+
46
+ ```ts type-equiv
47
+ /** One initial combo script; a scheduling phase may span several descriptors. */
48
+ interface WebBootBatch {
49
+ /** Parser-blocking bootstrap or preloaded application scheduling. */
50
+ phase: WebBootBatchPhase
51
+ /** Content-addressed combo script endpoint. */
52
+ url: string
53
+ /** Revision over the combined plugin script bytes and indexed source map. */
54
+ rev: string
55
+ /** Graph entry ids whose factories the script registers, in execution order. */
56
+ entries: string[]
57
+ }
58
+ ```
59
+
42
60
  ```ts type-equiv
43
61
  /** The composed client entry graph the host injects as `window.__DSH_BOOT__`. */
44
62
  interface WebBootGraph {
@@ -50,28 +68,42 @@ interface WebBootGraph {
50
68
  * unrelated and remains owned by fiber service waiting.
51
69
  */
52
70
  entries: WebBootEntry[]
71
+ /** Initial combo descriptors; every entry belongs to exactly one descriptor. */
72
+ batches: WebBootBatch[]
53
73
  }
54
74
  ```
55
75
 
56
- Each row's `rev` is the bundle's content hash and rides the URL as a cache-busting query; the graph `rev` hashes the composed rows, so any row change changes it. `immediately` marks the stage-one prefetch tier (fetch and execute during module-face boot, registration only); a lazy row is fetched on first import.
76
+ Each initial row's `rev` is an opaque process nonce plus sequence, so graph composition does not hash every plugin artifact. After HMR observes a change, that row's revision becomes the hash of its new bundle and available source map. The initial descriptors partition rows into bootstrap and application scheduling phases, and either phase may contain several descriptors. Their URLs contain only the ordered package-resource list and revision; phase names do not enter the route. Graph composition preserves row order while greedily splitting before the map-form URL exceeds 3 KiB. Startup combo revisions hash the combined plugin script bytes and indexed source map, and the graph revision hashes both rows and descriptors. `immediately` marks the stage-one registration barrier; rows within one combo share its script transport, while separate combos load independently.
57
77
 
58
78
  ## The scan
59
79
 
60
- A package joins the table by declaring `dsh.client` (`platform: 'web'`, optional `inject` edges, optional `immediately`) in its package.json and exporting its built bundle at `exports["./client"]`. Package resolution anchors at the config tree's `ctx.baseUrl` the cordis.yml directory, whose package declares every composed plugin as a dependency and construction throws when that anchor is unset.
80
+ A package joins the table by declaring `dsh.client` (`platform: 'web'`, optional `inject` edges, optional `immediately`) in its package.json and exporting its built bundle at `exports["./client"]`. Each live row resolves from its own Loader specifier and owning-tree `baseUrl`, through the same `loader.internal.resolveSync` implementation that imports its Host face when available. The nearest owning package manifest supplies the browser module id, so relative source and built overlays retain the package identity. Distinct active Loader sources resolving to one package name fail composition; after one source unloads, the surviving source supplies the row without a fiber restart.
61
81
 
62
82
  Scanning is incremental per package; there is no full-rescan code path. Every cordis `internal/plugin` emission (fiber construction or disposal) marks the fiber's entry name dirty, and a microtask flush reconciles each dirty name against the live loader entries. The activation pass seeds the same dirty set with all current entries and flushes synchronously, so first scan and steady state share one implementation — with opposite failure postures. At activation, a malformed declaration or missing bundle among the already-loaded entries aggregates into one loud `AggregateError` listing every broken package: the fiber FAILS and the boot's fail-loud sweep reports it. In steady state, a broken package logs a warning and must not poison the others.
63
83
 
64
- Package metadata — including the negative "not a client package" verdict — is cached per name and never expires: plugin-set changes take effect on restart. A fiber restart reuses its row and rev untouched; bundle content changes reach the graph only through `rebuilt()`.
84
+ Package metadata — including the negative "not a client package" verdict — is cached per Loader specifier and owning-tree base URL until restart. A fiber restart from the same source reuses its row and rev untouched; bundle content changes reach the graph only through `rebuilt()`.
65
85
 
66
86
  ## The bundle route and index injection
67
87
 
68
- `GET`/`HEAD /plugins/<id>/client.js` serves the registered bundle from disk with `no-cache` (the rev query, not HTTP caching, anchors consistency); other methods are 405. An unknown id or a registered row whose bundle is unreadable because it has not been built yet answers a loud 404, so no unreadable bundle appears as a successful JavaScript response. The injection rows carry the current graph on every index render, so a reload always boots against the live composition.
88
+ `GET`/`HEAD /plugins/??<package-a>/client.js,<package-b>/client.js&rev=<rev>` serves an exact generated combo script; a one-resource request uses the same form and is the HMR path. Its absolute `sourceMappingURL` changes every resource suffix in parallel, yielding `/plugins/??<package-a>/client.js.map,<package-b>/client.js.map&rev=<rev>`. The map is Indexed Source Map v3 even for one resource. An authored component map supplies its section; a component without one receives an identity section whose `sourcesContent` is the generated bundle and whose source name is its packaged `sourceURL` or plugin route. Every startup request URL is at most 3 KiB measured as UTF-8 bytes; partitioning uses the longer map form. All application URLs are preloaded, and all bootstrap URLs execute before the graph global and Vite entry. All advertised responses use long-lived immutable caching. Unknown or altered resource lists, missing revisions, and stale revisions answer 404 rather than serving different bytes or letting the SPA fallback return HTML as JavaScript; other methods are 405. The injection rows carry the current graph on every index render, so a reload always boots against the live composition.
69
89
 
70
90
  ## The service
71
91
 
72
- `ClientModuleRegistry` (`ctx.clientModules`, defined in [`packages/client/modules/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/modules/src/index.ts)) exposes reads and the rebuild face; signatures are in the generated [service catalog](#ctxclientmodules--clientmoduleregistry). `graph()` returns the current composed graph (a stable object between changes) and `clientPath(id)` the bundle's absolute path. `rebuilt(id)` is the only entry point through which bundle content reaches the graph: it re-hashes the file, and only a real rev change recomposes the graph and notifies. `onRebuilt` fires per changed bundle with the new rev; `onGraphChanged` fires after any flush that recomposed the graph (row added or removed, or a rebuilt rev change) and is pull-model — listeners re-read `graph()`. Both notification paths contain listener exceptions so one throwing subscriber cannot skip later subscribers or kill whatever triggered the flush.
92
+ ```ts type-equiv
93
+ /** Filesystem baseline captured before a client artifact snapshot is read. */
94
+ interface ClientArtifactBaseline {
95
+ /** Absolute path of the client bundle. */
96
+ readonly path: string
97
+ /** Bundle modification time in milliseconds. */
98
+ readonly mtimeMs: number
99
+ /** Bundle size in bytes. */
100
+ readonly size: number
101
+ }
102
+ ```
103
+
104
+ `ClientModuleRegistry` (`ctx.clientModules`, defined in [`packages/client/modules/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/modules/src/index.ts)) exposes reads and the rebuild face; signatures are in the generated [service catalog](#ctxclientmodules--clientmoduleregistry). `graph()` returns the current composed graph (a stable object between changes), `clientPath(id)` returns the bundle's absolute path, and `artifactBaseline(id)` returns the bundle stat values captured before the current snapshot was read. `rebuilt(id)` is the only entry point through which changed bundle content reaches the graph: it re-hashes the bundle together with its current source map, and only a real rev change recomposes the graph and notifies. `onRebuilt` fires per changed bundle with the new rev; `onGraphChanged` fires after any flush that recomposed the graph (row added or removed, or a rebuilt rev change) and is pull-model — listeners re-read `graph()`. Both notification paths contain listener exceptions so one throwing subscriber cannot skip later subscribers or kill whatever triggered the flush.
73
105
 
74
- In development, [dsh-client-hmr](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/hmr/README.md) is the registry's watch driver: its node half stat-polls every graph row's bundle from a synchronously captured baseline, calls `rebuilt(id)` on change, resyncs its watch set through `onGraphChanged`, and broadcasts rev changes to the browser half over SSE. Production graphs omit the HMR row entirely; the module host itself never watches files.
106
+ In development, [dsh-client-hmr](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/client/hmr/README.md) is the registry's watch driver: its node half stat-polls every graph row's bundle from the module host's pre-read baseline, calls `rebuilt(id)` only for a changed or dirty row, resyncs its watch set through `onGraphChanged`, and broadcasts rev changes to the browser half over SSE. Source-map changes alone do not trigger a reload; the current map joins the snapshot when a bundle change does. Production graphs omit the HMR row entirely; the module host itself never watches files.
75
107
 
76
108
  <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
77
109
 
@@ -101,6 +133,16 @@ graph(): WebBootGraph
101
133
  */
102
134
  clientPath(id: string): string | undefined
103
135
 
136
+ /**
137
+ * Filesystem baseline captured before an entry's current bytes were read.
138
+ * HMR compares it with the live files when installing a watch, so a write
139
+ * between startup composition and watch installation cannot disappear into
140
+ * the watcher's initial state.
141
+ * @param id - entry id (package name).
142
+ * @returns the path and baseline, or undefined for an unknown id.
143
+ */
144
+ artifactBaseline(id: string): ClientArtifactBaseline | undefined
145
+
104
146
  /**
105
147
  * Re-hash one bundle (the HMR watch's registration hook — the only entry
106
148
  * point through which bundle content changes reach the graph).
@@ -5,7 +5,7 @@ outline: [2,3]
5
5
 
6
6
  # Code Runtime
7
7
 
8
- The code-execution seam — a [capability seam](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose Service Definition ([dsh-code-runtime](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](./core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread Service Provider and tool-registry Consumer are specified by the [Code Mode foundation](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-15-code-mode.md) and [typed-return contract](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-20-code-mode-typed-tool-returns.md).
8
+ The code-execution seam — a [capability seam](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-06-13-capability-seams.md) whose Service Definition ([dsh-code-runtime](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/code-runtime/code-runtime), `ctx.codeRuntime`) runs one model-written program against host-provided async bindings and reports what it printed and returned. Code execution is **one optional capability**, not part of the agent-loop spine — so its vocabulary lives here, not in [core.md](./core.md). Backends differ by execution substrate and source language, both readonly descriptors on the service; the worker-thread Service Provider and tool-registry Consumer are specified by the [PTC mode foundation](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-06-15-ptc.md) and [typed-return contract](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/feature/2026-07-20-ptc-typed-tool-returns.md).
9
9
 
10
10
  Source: [`packages/code-runtime/code-runtime/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/code-runtime/code-runtime/src/types.ts)
11
11
 
@@ -64,7 +64,7 @@ interface CodeRunResult {
64
64
 
65
65
  ## Bindings: host functions as program globals
66
66
 
67
- Each `CodeBindingNamespace` becomes one global object of async callables inside the program (the Code Mode consumer passes one: `tools`). Arguments and resolutions must be lossless JSON and cross without a seam-level byte cap; the runtime may bridge them through structured clone. A namespace may declare a program-visible error class without making the runtime know the consumer's names: the runtime injects the real constructor and turns rejected calls into its instances. A runtime also treats binding names as hostile input (`__proto__` is an ordinary own property, never a prototype collision):
67
+ Each `CodeBindingNamespace` becomes one global object of async callables inside the program (the PTC mode consumer passes one: `tools`). Arguments and resolutions must be lossless JSON and cross without a seam-level byte cap; the runtime may bridge them through structured clone. A namespace may declare a program-visible error class without making the runtime know the consumer's names: the runtime injects the real constructor and turns rejected calls into its instances. A runtime also treats binding names as hostile input (`__proto__` is an ordinary own property, never a prototype collision):
68
68
 
69
69
  ```ts type-equiv
70
70
  /**
@@ -72,7 +72,7 @@ Each `CodeBindingNamespace` becomes one global object of async callables inside
72
72
  * injects a real error constructor under `name`; rejected member calls become
73
73
  * its instances and expose the exact member name through
74
74
  * `memberNameProperty`. Both strings are runtime data rather than knowledge
75
- * of a particular consumer such as Code Mode.
75
+ * of a particular consumer such as PTC mode.
76
76
  */
77
77
  interface CodeBindingErrorClass {
78
78
  /** Constructor global and resulting `Error.name`; same portable identifier rule as {@link CodeBindingNamespace.global}. */
@@ -86,7 +86,7 @@ type ManualCompactionErrorCode =
86
86
 
87
87
  `changed` and `summary` leave the conversation surface unchanged but still close and persist the failed attempt in the log. `commit` may follow partial mutation; `persistence` means the in-memory bracket closed but its flush failed. Cancellation remains separate and throws the exact abort reason after required cleanup.
88
88
 
89
- Pressure compaction runs at serial `agent/pre-step` before request derivation. Once pressure or canonical overflow qualifies, compaction-basic invokes optional [`ctx.toolResultPruner`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/compaction/compaction-tool-result-pruner/README.md) before range selection, remeasures through `ctx.tokenMeter`, and can advance the surface without a summary. Failed-request recovery runs through `agent/request-error` after the failed step closes and returns a retry action only when the surface replacement generation advances, even if later summary work throws after pruning; cancellation still wins. Region boundaries preserve tool-call/result pairing but not whole turns, allowing early closed steps of one oversized turn to compact. `dsh-compaction-basic` owns thresholds, retained-tail policy, overflow caps, and failure handling.
89
+ Pressure compaction runs at the `agent/pre-step` waterfall before request derivation. Once pressure or canonical overflow qualifies, compaction-basic invokes optional [`ctx.toolResultPruner`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/compaction/compaction-tool-result-pruner/README.md) before range selection, remeasures through `ctx.tokenMeter`, and can advance the surface without a summary. Failed-request recovery runs through `agent/request-error` after the failed step closes and returns a retry action only when the surface replacement generation advances, even if later summary work throws after pruning; cancellation still wins. Region boundaries preserve tool-call/result pairing but not whole turns, allowing early closed steps of one oversized turn to compact. `dsh-compaction-basic` owns thresholds, retained-tail policy, overflow caps, and failure handling.
90
90
 
91
91
  The Service Definition exports `toolPairingBalancedBefore(session, seq)` and `toolPairingBalancedAfter(session, seq)` for the tool-call/result pairing checks before and after a seq. Both validate current surface membership and reject missing seqs and orphan results; the [package contract](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/compaction/compaction/README.md#tool-pairing-boundaries) defines their cache behavior.
92
92
 
@@ -102,7 +102,7 @@ interface PrunedEntry {
102
102
  /** Newly appended pruned tool-result event. */
103
103
  readonly replacementSeq: number
104
104
  /** Tool call shared by the original and replacement. */
105
- readonly callId: CallId
105
+ readonly callId: ToolCallId
106
106
  /** Original text size in Unicode code points. */
107
107
  readonly charsBefore: number
108
108
  /** Replacement text size in Unicode code points. */