dsh-plugin-dev-kb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/cordis.patch.yml +12 -0
  4. package/kb/INDEX.md +210 -0
  5. package/kb/README.md +69 -0
  6. package/kb/extra/AGENTS.md +75 -0
  7. package/kb/extra/api-gateway.md +164 -0
  8. package/kb/extra/api-gateway.zh.md +164 -0
  9. package/kb/extra/cookbook/adding-a-vendored-package.md +59 -0
  10. package/kb/extra/cookbook/adding-a-vendored-package.zh.md +59 -0
  11. package/kb/extra/cookbook/maintaining-dsh-code-review.md +64 -0
  12. package/kb/extra/cookbook/maintaining-dsh-code-review.zh.md +64 -0
  13. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.md +32 -0
  14. package/kb/extra/cookbook/responding-to-pr-review-on-a-stack.zh.md +32 -0
  15. package/kb/extra/defensive-patterns.md +33 -0
  16. package/kb/extra/defensive-patterns.zh.md +33 -0
  17. package/kb/extra/development.md +171 -0
  18. package/kb/extra/development.zh.md +171 -0
  19. package/kb/extra/event-producer-consumer.md +76 -0
  20. package/kb/extra/event-producer-consumer.zh.md +78 -0
  21. package/kb/extra/glossary.md +45 -0
  22. package/kb/extra/glossary.zh.md +45 -0
  23. package/kb/extra/graph-atlas.md +24 -0
  24. package/kb/extra/graph-atlas.zh.md +26 -0
  25. package/kb/extra/i18n/README.md +60 -0
  26. package/kb/extra/i18n/README.zh.md +60 -0
  27. package/kb/extra/i18n/style-samples.md +87 -0
  28. package/kb/extra/i18n/terminology.md +214 -0
  29. package/kb/extra/i18n/translation-prompt.md +263 -0
  30. package/kb/extra/i18n/translation-rules.md +69 -0
  31. package/kb/extra/i18n/translation-rules.zh.md +69 -0
  32. package/kb/extra/module-graph.md +1641 -0
  33. package/kb/extra/module-graph.zh.md +1643 -0
  34. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.md +113 -0
  35. package/kb/extra/postmortem/0001-acp-default-export-drops-inject.zh.md +113 -0
  36. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.md +47 -0
  37. package/kb/extra/postmortem/0002-js-expression-disabled-filesystem-tools.zh.md +47 -0
  38. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.md +53 -0
  39. package/kb/extra/postmortem/0003-web-agent-gui-feedback-loop.zh.md +53 -0
  40. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.md +55 -0
  41. package/kb/extra/postmortem/0004-landlock-partial-notice-misclassified-child-failures.zh.md +55 -0
  42. package/kb/extra/postmortem/README.md +18 -0
  43. package/kb/extra/postmortem/README.zh.md +18 -0
  44. package/kb/extra/rescope.md +53 -0
  45. package/kb/extra/rescope.zh.md +53 -0
  46. package/kb/extra/subsystems/attachment.md +125 -0
  47. package/kb/extra/subsystems/attachment.zh.md +125 -0
  48. package/kb/extra/subsystems/extensions.md +364 -0
  49. package/kb/extra/subsystems/extensions.zh.md +364 -0
  50. package/kb/extra/subsystems/feedback.md +266 -0
  51. package/kb/extra/subsystems/feedback.zh.md +266 -0
  52. package/kb/extra/testing.md +49 -0
  53. package/kb/extra/testing.zh.md +49 -0
  54. package/kb/extra/web-styling.md +25 -0
  55. package/kb/extra/web-styling.zh.md +25 -0
  56. package/kb/meta/search-index.json +1328 -0
  57. package/kb/meta/site-pages.txt +168 -0
  58. package/kb/meta/source.json +13 -0
  59. package/kb/meta/topics.md +75 -0
  60. package/kb/site/develop/basic/config.md +108 -0
  61. package/kb/site/develop/basic/index.md +146 -0
  62. package/kb/site/develop/basic/publish.md +185 -0
  63. package/kb/site/develop/basic/tool.md +54 -0
  64. package/kb/site/develop/cordis-tutorial/01-first-plugin.md +95 -0
  65. package/kb/site/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  66. package/kb/site/develop/cordis-tutorial/03-services.md +98 -0
  67. package/kb/site/develop/cordis-tutorial/04-events.md +144 -0
  68. package/kb/site/develop/cordis-tutorial/05-config.md +84 -0
  69. package/kb/site/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  70. package/kb/site/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  71. package/kb/site/develop/cordis-tutorial/index.md +62 -0
  72. package/kb/site/develop/framework/events.md +145 -0
  73. package/kb/site/develop/framework/index.md +139 -0
  74. package/kb/site/develop/framework/service.md +152 -0
  75. package/kb/site/develop/practice/index.md +157 -0
  76. package/kb/site/develop/practice/llm-adapter.md +190 -0
  77. package/kb/site/en/develop/basic/config.md +108 -0
  78. package/kb/site/en/develop/basic/index.md +146 -0
  79. package/kb/site/en/develop/basic/publish.md +185 -0
  80. package/kb/site/en/develop/basic/tool.md +54 -0
  81. package/kb/site/en/develop/cordis-tutorial/01-first-plugin.md +95 -0
  82. package/kb/site/en/develop/cordis-tutorial/02-lifecycle-and-effects.md +98 -0
  83. package/kb/site/en/develop/cordis-tutorial/03-services.md +98 -0
  84. package/kb/site/en/develop/cordis-tutorial/04-events.md +144 -0
  85. package/kb/site/en/develop/cordis-tutorial/05-config.md +84 -0
  86. package/kb/site/en/develop/cordis-tutorial/06-composition-and-hmr.md +113 -0
  87. package/kb/site/en/develop/cordis-tutorial/07-into-the-harness.md +107 -0
  88. package/kb/site/en/develop/cordis-tutorial/index.md +60 -0
  89. package/kb/site/en/develop/framework/events.md +145 -0
  90. package/kb/site/en/develop/framework/index.md +139 -0
  91. package/kb/site/en/develop/framework/service.md +150 -0
  92. package/kb/site/en/develop/practice/index.md +157 -0
  93. package/kb/site/en/develop/practice/llm-adapter.md +190 -0
  94. package/kb/site/en/guide/providers-custom-form.png +0 -0
  95. package/kb/site/en/guide/providers-models-page.png +0 -0
  96. package/kb/site/en/guide/providers.md +100 -0
  97. package/kb/site/en/guide/python-sdk.md +106 -0
  98. package/kb/site/en/guide/quickstart.md +32 -0
  99. package/kb/site/en/index.md +8 -0
  100. package/kb/site/en/reference/agent-lifecycle.md +86 -0
  101. package/kb/site/en/reference/capability-seams.md +475 -0
  102. package/kb/site/en/reference/config-catalog.md +3155 -0
  103. package/kb/site/en/reference/cookbook/adding-a-conversation-node.md +235 -0
  104. package/kb/site/en/reference/cookbook/adding-a-package.md +120 -0
  105. package/kb/site/en/reference/cookbook/adding-a-settings-card.md +102 -0
  106. package/kb/site/en/reference/cookbook/adding-a-tool.md +96 -0
  107. package/kb/site/en/reference/cookbook/adding-an-llm-adapter.md +45 -0
  108. package/kb/site/en/reference/cookbook/extension-cookbook.md +131 -0
  109. package/kb/site/en/reference/cordis-api/context.md +368 -0
  110. package/kb/site/en/reference/cordis-api/events.md +211 -0
  111. package/kb/site/en/reference/cordis-api/fiber.md +379 -0
  112. package/kb/site/en/reference/cordis-api/inherited.md +43 -0
  113. package/kb/site/en/reference/cordis-api/registry.md +156 -0
  114. package/kb/site/en/reference/cordis-api/service.md +106 -0
  115. package/kb/site/en/reference/cordis-primer.md +46 -0
  116. package/kb/site/en/reference/index.md +131 -0
  117. package/kb/site/en/reference/persistence-catalog.md +949 -0
  118. package/kb/site/en/reference/subsystems/approval.md +173 -0
  119. package/kb/site/en/reference/subsystems/client-modules.md +121 -0
  120. package/kb/site/en/reference/subsystems/code-runtime.md +194 -0
  121. package/kb/site/en/reference/subsystems/commands.md +190 -0
  122. package/kb/site/en/reference/subsystems/compaction.md +241 -0
  123. package/kb/site/en/reference/subsystems/core.md +1073 -0
  124. package/kb/site/en/reference/subsystems/credentials.md +136 -0
  125. package/kb/site/en/reference/subsystems/filesystem.md +498 -0
  126. package/kb/site/en/reference/subsystems/goal.md +280 -0
  127. package/kb/site/en/reference/subsystems/index.md +58 -0
  128. package/kb/site/en/reference/subsystems/invariants.md +91 -0
  129. package/kb/site/en/reference/subsystems/jobs.md +293 -0
  130. package/kb/site/en/reference/subsystems/llm-streaming.md +920 -0
  131. package/kb/site/en/reference/subsystems/lsp.md +205 -0
  132. package/kb/site/en/reference/subsystems/permission-presets.md +134 -0
  133. package/kb/site/en/reference/subsystems/persistence.md +388 -0
  134. package/kb/site/en/reference/subsystems/plan.md +90 -0
  135. package/kb/site/en/reference/subsystems/sandbox.md +221 -0
  136. package/kb/site/en/reference/subsystems/schedule.md +189 -0
  137. package/kb/site/en/reference/subsystems/scope.md +62 -0
  138. package/kb/site/en/reference/subsystems/session-projection.md +265 -0
  139. package/kb/site/en/reference/subsystems/session-query.md +498 -0
  140. package/kb/site/en/reference/subsystems/session-reference.md +111 -0
  141. package/kb/site/en/reference/subsystems/session-telemetry.md +197 -0
  142. package/kb/site/en/reference/subsystems/session-title.md +207 -0
  143. package/kb/site/en/reference/subsystems/session.md +852 -0
  144. package/kb/site/en/reference/subsystems/settings.md +313 -0
  145. package/kb/site/en/reference/subsystems/shell.md +306 -0
  146. package/kb/site/en/reference/subsystems/skills.md +334 -0
  147. package/kb/site/en/reference/subsystems/spill.md +120 -0
  148. package/kb/site/en/reference/subsystems/storage.md +232 -0
  149. package/kb/site/en/reference/subsystems/subagent.md +737 -0
  150. package/kb/site/en/reference/subsystems/subprocess.md +327 -0
  151. package/kb/site/en/reference/subsystems/system-prompt.md +210 -0
  152. package/kb/site/en/reference/subsystems/terminal.md +187 -0
  153. package/kb/site/en/reference/subsystems/token-meter.md +93 -0
  154. package/kb/site/en/reference/subsystems/tools.md +723 -0
  155. package/kb/site/en/reference/subsystems/typert.md +339 -0
  156. package/kb/site/en/reference/subsystems/user-questions.md +181 -0
  157. package/kb/site/en/reference/subsystems/web-server.md +111 -0
  158. package/kb/site/en/reference/subsystems/web.md +202 -0
  159. package/kb/site/en/reference/subsystems/workflow.md +281 -0
  160. package/kb/site/en/reference/subsystems/workspace.md +231 -0
  161. package/kb/site/en/reference/tool-catalog.md +1877 -0
  162. package/kb/site/en/reference/tool-execution-pipeline.md +66 -0
  163. package/kb/site/guide/providers-custom-form.zh.png +0 -0
  164. package/kb/site/guide/providers-models-page.zh.png +0 -0
  165. package/kb/site/guide/providers.md +100 -0
  166. package/kb/site/guide/python-sdk.md +106 -0
  167. package/kb/site/guide/quickstart.md +32 -0
  168. package/kb/site/index.md +8 -0
  169. package/kb/site/reference/agent-lifecycle.md +86 -0
  170. package/kb/site/reference/capability-seams.md +475 -0
  171. package/kb/site/reference/config-catalog.md +3154 -0
  172. package/kb/site/reference/cookbook/adding-a-conversation-node.md +235 -0
  173. package/kb/site/reference/cookbook/adding-a-package.md +120 -0
  174. package/kb/site/reference/cookbook/adding-a-settings-card.md +102 -0
  175. package/kb/site/reference/cookbook/adding-a-tool.md +98 -0
  176. package/kb/site/reference/cookbook/adding-an-llm-adapter.md +45 -0
  177. package/kb/site/reference/cookbook/extension-cookbook.md +133 -0
  178. package/kb/site/reference/cordis-api/context.md +368 -0
  179. package/kb/site/reference/cordis-api/events.md +211 -0
  180. package/kb/site/reference/cordis-api/fiber.md +379 -0
  181. package/kb/site/reference/cordis-api/inherited.md +43 -0
  182. package/kb/site/reference/cordis-api/registry.md +156 -0
  183. package/kb/site/reference/cordis-api/service.md +106 -0
  184. package/kb/site/reference/cordis-primer.md +52 -0
  185. package/kb/site/reference/index.md +135 -0
  186. package/kb/site/reference/persistence-catalog.md +949 -0
  187. package/kb/site/reference/subsystems/approval.md +173 -0
  188. package/kb/site/reference/subsystems/client-modules.md +121 -0
  189. package/kb/site/reference/subsystems/code-runtime.md +194 -0
  190. package/kb/site/reference/subsystems/commands.md +190 -0
  191. package/kb/site/reference/subsystems/compaction.md +241 -0
  192. package/kb/site/reference/subsystems/core.md +1081 -0
  193. package/kb/site/reference/subsystems/credentials.md +136 -0
  194. package/kb/site/reference/subsystems/filesystem.md +498 -0
  195. package/kb/site/reference/subsystems/goal.md +280 -0
  196. package/kb/site/reference/subsystems/index.md +58 -0
  197. package/kb/site/reference/subsystems/invariants.md +91 -0
  198. package/kb/site/reference/subsystems/jobs.md +293 -0
  199. package/kb/site/reference/subsystems/llm-streaming.md +926 -0
  200. package/kb/site/reference/subsystems/lsp.md +205 -0
  201. package/kb/site/reference/subsystems/permission-presets.md +134 -0
  202. package/kb/site/reference/subsystems/persistence.md +388 -0
  203. package/kb/site/reference/subsystems/plan.md +90 -0
  204. package/kb/site/reference/subsystems/sandbox.md +221 -0
  205. package/kb/site/reference/subsystems/schedule.md +189 -0
  206. package/kb/site/reference/subsystems/scope.md +62 -0
  207. package/kb/site/reference/subsystems/session-projection.md +265 -0
  208. package/kb/site/reference/subsystems/session-query.md +498 -0
  209. package/kb/site/reference/subsystems/session-reference.md +111 -0
  210. package/kb/site/reference/subsystems/session-telemetry.md +197 -0
  211. package/kb/site/reference/subsystems/session-title.md +207 -0
  212. package/kb/site/reference/subsystems/session.md +854 -0
  213. package/kb/site/reference/subsystems/settings.md +313 -0
  214. package/kb/site/reference/subsystems/shell.md +306 -0
  215. package/kb/site/reference/subsystems/skills.md +334 -0
  216. package/kb/site/reference/subsystems/spill.md +120 -0
  217. package/kb/site/reference/subsystems/storage.md +232 -0
  218. package/kb/site/reference/subsystems/subagent.md +739 -0
  219. package/kb/site/reference/subsystems/subprocess.md +327 -0
  220. package/kb/site/reference/subsystems/system-prompt.md +210 -0
  221. package/kb/site/reference/subsystems/terminal.md +187 -0
  222. package/kb/site/reference/subsystems/token-meter.md +93 -0
  223. package/kb/site/reference/subsystems/tools.md +723 -0
  224. package/kb/site/reference/subsystems/typert.md +339 -0
  225. package/kb/site/reference/subsystems/user-questions.md +181 -0
  226. package/kb/site/reference/subsystems/web-server.md +111 -0
  227. package/kb/site/reference/subsystems/web.md +202 -0
  228. package/kb/site/reference/subsystems/workflow.md +281 -0
  229. package/kb/site/reference/subsystems/workspace.md +231 -0
  230. package/kb/site/reference/tool-catalog.md +1880 -0
  231. package/kb/site/reference/tool-execution-pipeline.md +66 -0
  232. package/package.json +40 -0
  233. package/scripts/rebuild-index.mjs +88 -0
  234. package/skills/dsh-plugin-dev-kb.md +66 -0
@@ -0,0 +1,293 @@
1
+ ---
2
+ editSource: "docs/subsystems/jobs.md"
3
+ outline: [2,3]
4
+ ---
5
+
6
+ # Background Task Runtime
7
+
8
+ Types shared by long-running producers, `ctx.jobs`, and job controls. The [runtime Agent Note](https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-06-20-generic-long-running-tool-runtime.md) owns the design; this page records the exact fields and variants from [`packages/jobs/jobs/src/types.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/src/types.ts).
9
+
10
+ ## Ids and status
11
+
12
+ `JobId` is a [branded id](./core.md#branded-ids) generated as `<kind>-N`. Access control relies on owner authorization, not id secrecy. `JobKind` derives from a merge-extensible map; the registry treats kinds as opaque id namespaces.
13
+
14
+ ```ts type-equiv
15
+ /**
16
+ * Producer-defined job kinds. Plugins extend this map by declaration merging;
17
+ * the registry treats every value as an opaque id namespace.
18
+ */
19
+ interface JobKindMap {
20
+ bash: 'bash'
21
+ subagent: 'subagent'
22
+ }
23
+ ```
24
+
25
+ `JobStatus` is `'running' | 'stopping' | 'completed' | 'killed' | 'failed'`; producer-specific facts belong in `JobSnapshot.detail`.
26
+
27
+ ## Producer contract
28
+
29
+ `JobStart` declares identity and a starter. The runtime finishes preflight before calling `run()` and commits without a later failable step. Producers own execution resources; the runtime owns identity, access, and lifecycle state.
30
+
31
+ ```ts type-equiv
32
+ /**
33
+ * Producer declaration passed to {@link JobRegistry.start}. The runtime
34
+ * preflights access and cleanup before invoking {@link run}; the producer owns
35
+ * execution resources while the runtime owns identity and lifecycle state.
36
+ */
37
+ interface JobStart {
38
+ /** Producer kind — also the id prefix (`bash`, `subagent`, …). */
39
+ kind: JobKind
40
+ /** One-line model-facing label (the command; the delegation description). */
41
+ label: string
42
+ /**
43
+ * Optional UTF-8 byte cap for each complete model-facing completion notice or
44
+ * output read, including controller status metadata.
45
+ */
46
+ outputLimitBytes?: number
47
+ /**
48
+ * Owning live agent. Access is fenced by its session id, and agent disposal
49
+ * cancels and awaits the job. The instance must be the one currently
50
+ * registered under its agent id. Omitting the owner creates an unowned job,
51
+ * open to any caller until service disposal.
52
+ */
53
+ owner?: Agent
54
+ /**
55
+ * Start the work after preflight and synchronously return its hooks. Called
56
+ * once; a throw leaves nothing registered, and the producer must clean up any
57
+ * partially started resources.
58
+ */
59
+ run(): JobHooks
60
+ }
61
+ ```
62
+
63
+ `JobHooks.done` resolves after the producer releases its resources, not merely when work finishes. Optional `readOutput` distinguishes consuming stream jobs from final-output-only jobs.
64
+
65
+ ```ts type-equiv
66
+ /** Hooks through which the runtime controls and observes producer work. */
67
+ interface JobHooks {
68
+ /**
69
+ * Request termination. Must be synchronous, idempotent, and eventually settle
70
+ * {@link done}; throws propagate. The optional reason is forwarded verbatim.
71
+ */
72
+ cancel(reason?: string): void
73
+ /**
74
+ * Resolves after the producer releases its resources, not merely when work
75
+ * finishes. Must not reject; the runtime converts a rejection to `failed`.
76
+ * If teardown cancellation throws, the runtime may force-fail only the
77
+ * registry record without claiming that the work stopped.
78
+ */
79
+ done: Promise<JobOutcome>
80
+ /**
81
+ * Consume output produced since the previous call. The producer formats
82
+ * truncation and spill notices. Absence marks a final-output-only job; each
83
+ * job has one consuming cursor.
84
+ */
85
+ readOutput?(): string
86
+ }
87
+ ```
88
+
89
+ ```ts type-equiv
90
+ /** Terminal result supplied by a producer through {@link JobHooks.done}. */
91
+ interface JobOutcome {
92
+ /** How the job ended: finished (`completed`), cancelled (`killed`), or broke (`failed`). */
93
+ status: 'completed' | 'killed' | 'failed'
94
+ /** Kind-specific detail rendered into status lines ('exit code: 3', 'max-tokens'). */
95
+ detail?: string
96
+ /** Final output for jobs without `readOutput`; stream jobs leave it unset. */
97
+ output?: string
98
+ }
99
+ ```
100
+
101
+ ## Consumer views
102
+
103
+ Snapshots are fresh read-only projections. `ownerSession` carries the shared `SessionId` used for authorization; completion listeners separately receive the exact owner object used for lifecycle cleanup. `reported` suppresses a completion notice after another reporter has delivered or committed to deliver the terminal state, including the teardown cancel that drains an owner or the service.
104
+
105
+ ```ts type-equiv
106
+ /**
107
+ * A read-only projection of one job, safe to hand to listeners and tools —
108
+ * a fresh object per call, never live registry state.
109
+ */
110
+ interface JobSnapshot {
111
+ /** The registry-issued id (`<kind>-N`). */
112
+ id: JobId
113
+ /** The producer kind the job was registered with. */
114
+ kind: JobKind
115
+ /** The producer-supplied one-line label. */
116
+ label: string
117
+ /** Producer-owned cap for complete model-facing notices and output reads. */
118
+ outputLimitBytes?: number
119
+ /**
120
+ * Owner session id used for authorization and correlation; absent for
121
+ * unowned jobs. Completion listeners receive the exact {@link Agent}
122
+ * separately through {@link JobDoneListener}.
123
+ */
124
+ ownerSession?: SessionId
125
+ /** Current lifecycle state. */
126
+ status: JobStatus
127
+ /** Kind-specific status detail, present once the producer supplied one (usually terminal). */
128
+ detail?: string
129
+ /** Epoch ms when the job was registered. */
130
+ startedAt: number
131
+ /** Epoch ms when the job settled; absent while `running`/`stopping`. */
132
+ finishedAt?: number
133
+ /**
134
+ * True when a kill, read, wait, or teardown cancel has reported or committed
135
+ * to report the terminal state. Completion reporters suppress redundant
136
+ * notices when set. Teardown claims it because the owner or service being
137
+ * destroyed leaves no reader: a reporter that opens a turn on notice would
138
+ * otherwise spend a model request per teardown layer.
139
+ */
140
+ reported: boolean
141
+ }
142
+ ```
143
+
144
+ ```ts type-equiv
145
+ /** Output and post-read state returned by {@link JobRegistry.read}. */
146
+ interface JobRead {
147
+ /**
148
+ * Stream kinds: the consuming delta since the previous read. Final-output
149
+ * kinds: empty while live, the terminal {@link JobOutcome.output} (or
150
+ * empty) once settled — idempotent, never consumed.
151
+ */
152
+ text: string
153
+ /** The job's state at read time. */
154
+ snapshot: JobSnapshot
155
+ }
156
+ ```
157
+
158
+ ## Service behavior
159
+
160
+ The abstract [`JobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/src/index.ts) Service Definition specifies atomic `start`, caller-scoped `get` and `list`, `read`, `kill`, bounded `wait`, failure-isolated `onJobDone` and `onJobsChanged` listeners, and when `attachController` becomes available; [`LocalJobRegistry`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/src/index.ts) is the process-local Service Provider. Authorization compares owner sessions; owner cleanup and admission use the exact registered `Agent` instance. The local provider's positive-safe-integer `maxConcurrentJobsPerOwner` config defaults to `10` and counts `running` plus `stopping` records per exact owner, with one shared bucket for unowned jobs; terminal producer settlement releases capacity. See [`dsh-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/README.md) for the Service Definition contract, [`dsh-jobs-local`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs-local/README.md) for the registry lifecycle and admission policy, and [`dsh-tool-jobs`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/tool-jobs/README.md) for the model-facing Consumer.
161
+
162
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
163
+
164
+ <a id="cordis-surface"></a>
165
+
166
+ ## Cordis API
167
+
168
+ Generated from source by `scripts/gen-cordis-catalog.ts` (verified fresh by `pnpm run verify-cordis-catalog` in doc-sync; regenerate with `pnpm run gen-cordis-catalog`) — this section is byte-identical in both language sides of the page. Signature blocks use a `ts cordis-catalog` fence and keep the original source JSDoc; dispatch modes are defined in the [primer](../cordis-primer.md#dispatch-modes), and the framework-inherited `ctx` API lives in [cordis-api/inherited.md](../cordis-api/inherited.md).
169
+
170
+ <a id="ctxjobs--jobregistry-abstract-seam"></a>
171
+
172
+ ### `ctx.jobs` — `JobRegistry` (abstract seam)
173
+
174
+ Abstract background job registry. Subclass, implement the abstract methods, and load the subclass as a plugin — it registers as `ctx.jobs` (one implementation per context; loading a second throws, which is cordis' standard duplicate-service behavior).
175
+
176
+ Implementations must honor these semantics:
177
+
178
+ - Registrations outlive producer and controller fibers. Owner and service disposal cancel live work and await compliant producers; a throwing teardown cancel force-fails only the record. Teardown cancellation also marks the record reported, because a record its owner is being destroyed for has no reader left.
179
+ - Owned-job access is fenced by the owner's session id. Ids are predictable, so authorization — not secrecy — is the boundary.
180
+ - Settlement is first-wins: one terminal record, released waiters, and one round of contained listener notification, even against a late producer outcome. Completion is announced last, after the record is committed and every other observer of the settlement has seen it, because a reporter may open a model turn synchronously.
181
+ - start refuses work while no attached job controller serves the spec's owner, so a producer cannot start work that owner cannot collect or stop. One registry serves every composition in the process, so this question — and completion-listener delivery — is owner-relative rather than process-wide: registrations made from an unscoped context serve every owner, and registrations made under an agent composition's scope serve exactly the agents composed under it.
182
+
183
+ ```ts cordis-catalog
184
+ /**
185
+ * Preflight access, validation, owner cleanup, and implementation-owned
186
+ * admission before starting and atomically registering work. Any preflight
187
+ * rejection leaves no job id or execution resource. A throwing starter
188
+ * leaves nothing registered; after it returns, registration cannot fail.
189
+ * Settlement records the outcome, notifies listeners, and releases waiters.
190
+ * @param spec - job identity, owner, and synchronous starter.
191
+ * @returns the registry-issued `<kind>-N` id.
192
+ */
193
+ abstract start(spec: JobStart): JobId
194
+
195
+ /**
196
+ * List caller-owned and unowned jobs in registration order without exposing
197
+ * another session's labels.
198
+ * @param caller - reading agent; a non-agent caller sees only unowned jobs.
199
+ * @returns fresh snapshots.
200
+ */
201
+ abstract list(caller?: Agent): JobSnapshot[]
202
+
203
+ /**
204
+ * Return a non-consuming snapshot without changing its read cursor or notice
205
+ * state. Throws for an unknown or foreign job.
206
+ * @param id - job to look up.
207
+ * @param caller - reading agent checked against the owner.
208
+ * @returns a fresh snapshot.
209
+ */
210
+ abstract get(id: JobId, caller?: Agent): JobSnapshot
211
+
212
+ /**
213
+ * Read the next stream delta, or the idempotent final output after settlement.
214
+ * A terminal read marks the job reported. Throws for an unknown or foreign
215
+ * job.
216
+ * @param id - job to read.
217
+ * @param caller - reading agent checked against the owner.
218
+ * @returns output text and the post-read snapshot.
219
+ */
220
+ abstract read(id: JobId, caller?: Agent): JobRead
221
+
222
+ /**
223
+ * Request cancellation, then mark the job stopping and reported. A producer
224
+ * throw propagates without changing job state. Throws for an unknown or
225
+ * foreign job.
226
+ * @param id - job to cancel.
227
+ * @param caller - killing agent checked against the owner.
228
+ * @param reason - logged reason forwarded to the producer.
229
+ * @returns `requested` for live work, otherwise `already-finished`.
230
+ */
231
+ abstract kill(id: JobId, caller?: Agent, reason?: string): 'requested' | 'already-finished'
232
+
233
+ /**
234
+ * Wait for settlement or timeout without cancelling the job. Caller abort
235
+ * rejects only while the job is live; after settlement the terminal
236
+ * snapshot wins so a notice suppressed for this waiter is still delivered.
237
+ * Throws for invalid, unknown, or foreign input.
238
+ * @param id - job to wait for.
239
+ * @param timeoutMs - positive finite wait bound in milliseconds.
240
+ * @param caller - waiting agent checked against the owner.
241
+ * @param signal - optional cancellation of the wait itself.
242
+ * @returns snapshot at settlement or timeout.
243
+ */
244
+ abstract wait(id: JobId, timeoutMs: number, caller?: Agent, signal?: AbortSignal): Promise<JobSnapshot>
245
+
246
+ /**
247
+ * Register an effect-scoped completion listener. It receives the settlements
248
+ * of the owners its registering context's scope covers; each listener is
249
+ * contained; returned promises are observed but not awaited. No listener runs
250
+ * after service disposal.
251
+ * @param listener - receives each terminal snapshot and its exact owner.
252
+ * @returns disposer that unregisters the listener.
253
+ */
254
+ abstract onJobDone(listener: JobDoneListener): () => void
255
+
256
+ /**
257
+ /**
258
+ * Register an effect-scoped observer of visible-set changes. It fires after
259
+ * every commit that changes what {@link list} returns for that owner —
260
+ * registration, every stopping transition (including the one teardown
261
+ * performs before it awaits a slow producer), settlement, owner-disposal
262
+ * removal, and the emptying that service disposal commits — so an observer
263
+ * re-reads rather than accumulating deltas.
264
+ *
265
+ * Delivery is owner-relative on the same terms as {@link onJobDone}: an
266
+ * observer registered from an unscoped context — a host composition's own
267
+ * carrier — sees every owner, while one registered under an agent
268
+ * composition's scope sees exactly the agents composed under it.
269
+ *
270
+ * This is not a superset of {@link onJobDone}: that one delivers the terminal
271
+ * record under first-wins semantics a job controller couples to notice
272
+ * delivery, while this one carries no delivery meaning and marks nothing
273
+ * reported. Listeners are contained and never awaited.
274
+ * @param listener - receives the owner whose visible set changed, or
275
+ * `undefined` when an unowned job changed and every caller's set did.
276
+ * @returns disposer that unregisters the listener.
277
+ */
278
+ abstract onJobsChanged(listener: JobsChangedListener): () => void
279
+
280
+ /**
281
+ * Attach an effect-scoped controller that can read and stop jobs. It serves the
282
+ * owners its registering context's scope covers, and {@link start} refuses an
283
+ * owner no attached controller serves.
284
+ * @param name - diagnostic label; duplicate names remain independent.
285
+ * @returns disposer that detaches this controller.
286
+ */
287
+ abstract attachController(name: string): () => void
288
+ ```
289
+
290
+ Types: [Agent](./core.md)
291
+
292
+ Source: [`packages/jobs/jobs/src/index.ts:62`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/jobs/jobs/src/index.ts)
293
+ <!-- END GENERATED cordis-surface -->