dsh-plugin-dev-kb 1.8.0 → 1.8.1

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 (229) hide show
  1. package/CHANGELOG.md +186 -178
  2. package/README.en.md +172 -172
  3. package/README.md +183 -183
  4. package/kb/INDEX.md +236 -234
  5. package/kb/README.md +88 -88
  6. package/kb/extra/AGENTS.md +77 -77
  7. package/kb/extra/deepseek-llm-api-wire-extensions.md +162 -162
  8. package/kb/extra/deepseek-llm-api-wire-extensions.zh.md +162 -162
  9. package/kb/extra/defensive-patterns/package-surface.md +233 -232
  10. package/kb/extra/defensive-patterns/package-surface.zh.md +233 -232
  11. package/kb/extra/defensive-patterns/remote-and-api.md +117 -117
  12. package/kb/extra/defensive-patterns/remote-and-api.zh.md +117 -117
  13. package/kb/extra/development.md +221 -221
  14. package/kb/extra/development.zh.md +228 -228
  15. package/kb/extra/event-producer-consumer.md +133 -123
  16. package/kb/extra/event-producer-consumer.zh.md +135 -125
  17. package/kb/extra/module-graph.md +1961 -1888
  18. package/kb/extra/module-graph.zh.md +1963 -1890
  19. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.md +60 -0
  20. package/kb/extra/persistence-changes/2026-11-05-timeline-priority-notice.zh.md +60 -0
  21. package/kb/extra/persistence-changes/README.md +92 -92
  22. package/kb/extra/persistence-changes/README.zh.md +92 -92
  23. package/kb/extra/persistence-changes/historical-formats/README.md +75 -75
  24. package/kb/extra/persistence-changes/historical-formats/README.zh.md +75 -75
  25. package/kb/extra/persistence-changes/releases/README.md +103 -103
  26. package/kb/extra/persistence-changes/releases/README.zh.md +103 -103
  27. package/kb/extra/rescope.md +55 -55
  28. package/kb/extra/rescope.zh.md +55 -55
  29. package/kb/extra/subsystems/boot.md +631 -621
  30. package/kb/extra/subsystems/boot.zh.md +631 -621
  31. package/kb/extra/subsystems/computer-use.md +179 -137
  32. package/kb/extra/subsystems/computer-use.zh.md +179 -137
  33. package/kb/extra/subsystems/extensions.md +387 -384
  34. package/kb/extra/subsystems/extensions.zh.md +387 -384
  35. package/kb/extra/subsystems/feedback.md +418 -400
  36. package/kb/extra/subsystems/feedback.zh.md +418 -400
  37. package/kb/extra/subsystems/forge.md +2169 -1226
  38. package/kb/extra/subsystems/forge.zh.md +2171 -1226
  39. package/kb/extra/subsystems/liveshare.md +167 -158
  40. package/kb/extra/subsystems/liveshare.zh.md +167 -158
  41. package/kb/extra/subsystems/mcp.md +237 -234
  42. package/kb/extra/subsystems/mcp.zh.md +237 -234
  43. package/kb/extra/subsystems/office-kit.md +122 -0
  44. package/kb/extra/subsystems/office-kit.zh.md +122 -0
  45. package/kb/extra/subsystems/working-directory.md +95 -64
  46. package/kb/extra/subsystems/working-directory.zh.md +95 -64
  47. package/kb/extra/subsystems/worktrees.md +187 -127
  48. package/kb/extra/subsystems/worktrees.zh.md +187 -127
  49. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.md +21 -21
  50. package/kb/extra/upgrade-guide/v0.2.1-alpha.1/python-ptc-sandbox/guide.zh.md +21 -21
  51. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.md +18 -0
  52. package/kb/extra/upgrade-guide/v0.2.1-rc.4/sandbox-unsupported-policy-error/guide.zh.md +18 -0
  53. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.md +18 -0
  54. package/kb/extra/upgrade-guide/v0.2.2-alpha.2/llm-error-builtin-codes/guide.zh.md +18 -0
  55. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.md +34 -0
  56. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-kit-package/guide.zh.md +34 -0
  57. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.md +49 -0
  58. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-operation-tools/guide.zh.md +49 -0
  59. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.md +36 -0
  60. package/kb/extra/upgrade-guide/v0.2.2-alpha.3/office-skill-resources/guide.zh.md +36 -0
  61. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.md +26 -0
  62. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-notification-fields/guide.zh.md +26 -0
  63. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.md +22 -0
  64. package/kb/extra/upgrade-guide/v0.2.2-rc.1/account-remote-provider/guide.zh.md +22 -0
  65. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.md +21 -0
  66. package/kb/extra/upgrade-guide/v0.2.2-rc.1/archive-worktrees/guide.zh.md +21 -0
  67. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.md +23 -0
  68. package/kb/extra/upgrade-guide/v0.2.2-rc.1/attachment-error-codes/guide.zh.md +23 -0
  69. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.md +20 -0
  70. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-ax-read-limits/guide.zh.md +20 -0
  71. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.md +18 -0
  72. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-hover-ax-only/guide.zh.md +18 -0
  73. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.md +23 -0
  74. package/kb/extra/upgrade-guide/v0.2.2-rc.1/cua-native-platform/guide.zh.md +23 -0
  75. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.md +35 -0
  76. package/kb/extra/upgrade-guide/v0.2.2-rc.1/dsh-doc-skill/guide.zh.md +35 -0
  77. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.md +26 -0
  78. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-change-request-overview/guide.zh.md +26 -0
  79. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.md +26 -0
  80. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-pinned-diff/guide.zh.md +26 -0
  81. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.md +19 -0
  82. package/kb/extra/upgrade-guide/v0.2.2-rc.1/forge-review-reads/guide.zh.md +19 -0
  83. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.md +26 -0
  84. package/kb/extra/upgrade-guide/v0.2.2-rc.1/package-export-cleanup/guide.zh.md +26 -0
  85. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.md +22 -0
  86. package/kb/extra/upgrade-guide/v0.2.2-rc.1/plugin-update-method/guide.zh.md +22 -0
  87. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.md +25 -0
  88. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-bootstrap-protocol/guide.zh.md +25 -0
  89. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.md +48 -0
  90. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-inspect-output/guide.zh.md +48 -0
  91. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.md +45 -0
  92. package/kb/extra/upgrade-guide/v0.2.2-rc.1/ptc-scoped-repl-default/guide.zh.md +45 -0
  93. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.md +19 -0
  94. package/kb/extra/upgrade-guide/v0.2.2-rc.1/runtime-context-reminders/guide.zh.md +19 -0
  95. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.md +17 -0
  96. package/kb/extra/upgrade-guide/v0.2.2-rc.1/session-append-overloads/guide.zh.md +17 -0
  97. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.md +27 -0
  98. package/kb/extra/upgrade-guide/v0.2.2-rc.1/subagent-interrupt-default/guide.zh.md +27 -0
  99. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.md +20 -0
  100. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-backend-cleanup-error/guide.zh.md +20 -0
  101. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.md +19 -0
  102. package/kb/extra/upgrade-guide/v0.2.2-rc.1/terminal-bundle-sidebar-backend/guide.zh.md +19 -0
  103. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.md +18 -0
  104. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-fetch-transport-error-codes/guide.zh.md +18 -0
  105. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.md +41 -0
  106. package/kb/extra/upgrade-guide/v0.2.2-rc.1/web-search-billing/guide.zh.md +41 -0
  107. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.md +21 -0
  108. package/kb/extra/upgrade-guide/v0.2.2-rc.1/window-drag-regions/guide.zh.md +21 -0
  109. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.md +29 -0
  110. package/kb/extra/upgrade-guide/v0.2.2-rc.2/client-module-metadata/guide.zh.md +29 -0
  111. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.md +25 -0
  112. package/kb/extra/upgrade-guide/v0.2.2-rc.2/connection-page-peer/guide.zh.md +25 -0
  113. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.md +31 -0
  114. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cordis-root-and-intercept-metadata/guide.zh.md +31 -0
  115. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.md +24 -0
  116. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-agents-without-preset/guide.zh.md +24 -0
  117. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.md +24 -0
  118. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-macos-provider/guide.zh.md +24 -0
  119. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.md +19 -0
  120. package/kb/extra/upgrade-guide/v0.2.2-rc.2/cua-partial-observations/guide.zh.md +19 -0
  121. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.md +15 -0
  122. package/kb/extra/upgrade-guide/v0.2.2-rc.2/deepseek-files-timeout/guide.zh.md +15 -0
  123. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.md +28 -0
  124. package/kb/extra/upgrade-guide/v0.2.2-rc.2/experimental-tool-error-codes/guide.zh.md +28 -0
  125. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.md +36 -0
  126. package/kb/extra/upgrade-guide/v0.2.2-rc.2/package-export-cleanup/guide.zh.md +36 -0
  127. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.md +22 -0
  128. package/kb/extra/upgrade-guide/v0.2.2-rc.2/python-ptc-removal/guide.zh.md +22 -0
  129. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.md +31 -0
  130. package/kb/extra/upgrade-guide/v0.2.2-rc.2/session-status-package/guide.zh.md +31 -0
  131. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.md +18 -0
  132. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shared-search-filter/guide.zh.md +18 -0
  133. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.md +30 -0
  134. package/kb/extra/upgrade-guide/v0.2.2-rc.2/shell-fs-tool-error-codes/guide.zh.md +30 -0
  135. package/kb/extra/web-styling.md +57 -57
  136. package/kb/extra/web-styling.zh.md +57 -57
  137. package/kb/meta/search-index.json +4508 -3980
  138. package/kb/meta/source.json +18 -18
  139. package/kb/site/develop/practice/llm-adapter.md +192 -192
  140. package/kb/site/en/develop/practice/llm-adapter.md +192 -192
  141. package/kb/site/en/guide/desktop-uninstall-cleanup.md +63 -0
  142. package/kb/site/en/guide/plugin-market.md +153 -151
  143. package/kb/site/en/guide/providers.md +234 -234
  144. package/kb/site/en/guide/quickstart.md +35 -34
  145. package/kb/site/en/reference/capability-seams.md +789 -767
  146. package/kb/site/en/reference/config-catalog.md +5432 -5128
  147. package/kb/site/en/reference/cookbook/adding-a-package.md +175 -175
  148. package/kb/site/en/reference/cookbook/adding-a-tool.md +105 -104
  149. package/kb/site/en/reference/cookbook/extension-cookbook.md +178 -135
  150. package/kb/site/en/reference/cordis-api/context.md +373 -369
  151. package/kb/site/en/reference/cordis-api/fiber.md +457 -433
  152. package/kb/site/en/reference/cordis-api/inherited.md +44 -44
  153. package/kb/site/en/reference/cordis-api/service.md +118 -107
  154. package/kb/site/en/reference/experimental-persistence-catalog.md +36 -23
  155. package/kb/site/en/reference/index.md +174 -174
  156. package/kb/site/en/reference/persistence-catalog.md +9453 -9432
  157. package/kb/site/en/reference/subsystems/compaction.md +288 -288
  158. package/kb/site/en/reference/subsystems/core.md +1172 -1171
  159. package/kb/site/en/reference/subsystems/credentials.md +526 -497
  160. package/kb/site/en/reference/subsystems/filesystem.md +708 -708
  161. package/kb/site/en/reference/subsystems/index.md +82 -82
  162. package/kb/site/en/reference/subsystems/llm-streaming.md +1290 -1288
  163. package/kb/site/en/reference/subsystems/lsp.md +230 -206
  164. package/kb/site/en/reference/subsystems/persistence.md +451 -432
  165. package/kb/site/en/reference/subsystems/plan.md +91 -91
  166. package/kb/site/en/reference/subsystems/ptc-runtime.md +295 -261
  167. package/kb/site/en/reference/subsystems/sandbox.md +250 -232
  168. package/kb/site/en/reference/subsystems/session-query.md +525 -515
  169. package/kb/site/en/reference/subsystems/session-reference.md +231 -229
  170. package/kb/site/en/reference/subsystems/session.md +1478 -1431
  171. package/kb/site/en/reference/subsystems/sidebar-right.md +165 -165
  172. package/kb/site/en/reference/subsystems/skills.md +356 -356
  173. package/kb/site/en/reference/subsystems/slots.md +235 -231
  174. package/kb/site/en/reference/subsystems/terminal.md +188 -188
  175. package/kb/site/en/reference/subsystems/tools.md +902 -891
  176. package/kb/site/en/reference/subsystems/user-questions.md +330 -327
  177. package/kb/site/en/reference/subsystems/web-client.md +161 -104
  178. package/kb/site/en/reference/subsystems/web-server.md +434 -351
  179. package/kb/site/en/reference/subsystems/web.md +268 -268
  180. package/kb/site/en/reference/subsystems/workflow.md +287 -282
  181. package/kb/site/en/reference/subsystems/workspace.md +743 -651
  182. package/kb/site/en/reference/tool-catalog.md +2867 -2704
  183. package/kb/site/guide/desktop-uninstall-cleanup.md +63 -0
  184. package/kb/site/guide/plugin-market.md +153 -151
  185. package/kb/site/guide/providers.md +234 -234
  186. package/kb/site/guide/quickstart.md +35 -34
  187. package/kb/site/reference/capability-seams.md +789 -767
  188. package/kb/site/reference/config-catalog.md +5432 -5128
  189. package/kb/site/reference/cookbook/adding-a-package.md +175 -175
  190. package/kb/site/reference/cookbook/adding-a-tool.md +107 -106
  191. package/kb/site/reference/cookbook/extension-cookbook.md +182 -139
  192. package/kb/site/reference/cordis-api/context.md +373 -369
  193. package/kb/site/reference/cordis-api/fiber.md +459 -435
  194. package/kb/site/reference/cordis-api/inherited.md +44 -44
  195. package/kb/site/reference/cordis-api/service.md +118 -107
  196. package/kb/site/reference/experimental-persistence-catalog.md +36 -23
  197. package/kb/site/reference/index.md +178 -178
  198. package/kb/site/reference/persistence-catalog.md +9453 -9432
  199. package/kb/site/reference/subsystems/compaction.md +288 -288
  200. package/kb/site/reference/subsystems/core.md +1184 -1183
  201. package/kb/site/reference/subsystems/credentials.md +526 -497
  202. package/kb/site/reference/subsystems/filesystem.md +708 -708
  203. package/kb/site/reference/subsystems/index.md +82 -82
  204. package/kb/site/reference/subsystems/llm-streaming.md +1296 -1294
  205. package/kb/site/reference/subsystems/lsp.md +230 -206
  206. package/kb/site/reference/subsystems/persistence.md +451 -432
  207. package/kb/site/reference/subsystems/plan.md +91 -91
  208. package/kb/site/reference/subsystems/ptc-runtime.md +295 -261
  209. package/kb/site/reference/subsystems/sandbox.md +250 -232
  210. package/kb/site/reference/subsystems/session-query.md +525 -515
  211. package/kb/site/reference/subsystems/session-reference.md +231 -229
  212. package/kb/site/reference/subsystems/session.md +1482 -1435
  213. package/kb/site/reference/subsystems/sidebar-right.md +165 -165
  214. package/kb/site/reference/subsystems/skills.md +356 -356
  215. package/kb/site/reference/subsystems/slots.md +239 -235
  216. package/kb/site/reference/subsystems/terminal.md +188 -188
  217. package/kb/site/reference/subsystems/tools.md +902 -891
  218. package/kb/site/reference/subsystems/user-questions.md +330 -327
  219. package/kb/site/reference/subsystems/web-client.md +161 -104
  220. package/kb/site/reference/subsystems/web-server.md +434 -351
  221. package/kb/site/reference/subsystems/web.md +268 -268
  222. package/kb/site/reference/subsystems/workflow.md +287 -282
  223. package/kb/site/reference/subsystems/workspace.md +743 -651
  224. package/kb/site/reference/tool-catalog.md +2872 -2709
  225. package/lib/index.js +359 -359
  226. package/package.json +68 -68
  227. package/skills/dsh-plugin-dev-kb.md +71 -70
  228. package/kb/extra/subsystems/office-to-pdf.md +0 -87
  229. package/kb/extra/subsystems/office-to-pdf.zh.md +0 -87
@@ -1,356 +1,356 @@
1
- ---
2
- editSource: "docs/subsystems/skills.md"
3
- rawMarkdownPath: "en/reference/subsystems/skills.md"
4
- outline: [2,3]
5
- ---
6
-
7
- # Skills
8
-
9
- The [skill capability family](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill) includes the Service Definition ([dsh-skill](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill), `ctx.skills`), the local Service Provider ([dsh-skill-filesystem](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill-filesystem)), optional packaged providers ([dsh-skill-badge](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/experimental/skill-badge), [dsh-skill-office](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill-office), and the Windows ACL diagnosis provider in [dsh-sandbox-windows-acl](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox-windows-acl)), and the Consumer ([dsh-tool-skill](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](./core.md).
10
-
11
- Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts), [`packages/skill/skill-filesystem/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-filesystem/src/index.ts), [`packages/experimental/skill-badge/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/skill-badge/src/index.ts), [`packages/skill/skill-office/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-office/src/index.ts), [`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox-windows-acl/src/acl-skill.ts), and [`packages/skill/tool-skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/tool-skill/src/index.ts).
12
-
13
- ## Provider registry
14
-
15
- `ctx.skills` combines local, embedded, remote, or other providers. Registration is synchronous; remote initialization and discovery belong in awaited `list()`. Provider objects, options, and candidates are borrowed readonly, while semantic fields are validated.
16
-
17
- The registry is host+per-scope layered, the shape the [tools registry](./tools.md) established over [dsh-scope](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/scope): a registration files into the layer of its calling context's scope, so host rows and repository plugins land in the global layer while a plugin mounted by an agent preset's standing composition lands in that preset's layer, and provider names are unique per layer rather than process-wide. A read merges the global layer with the viewing scope's chain — the nearest layer's entry wins a duplicate skill name outright, and the rank order below decides duplicates only within one layer. Discovery caches are keyed by the resolved scope chain, so re-parenting a scope (a blank-session recompose) is visible to the next read without a registry mutation.
18
-
19
- Within one layer, duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and omitted from an incomplete observation, while an explicit incomplete observation contributes usable candidates without making the result cacheable; malformed candidates fail fast. Each provider factory receives a registration-scoped control whose `invalidate()` clears completed catalogs only while that exact registration remains active and whose signal aborts on failed registration or disposal. An in-flight discovery retries once when its provider generation changes; a second change returns the latest candidates incomplete and uncached. Provider and runtime mutations emit the unfiltered `skills/change` invalidation event; it carries no diff, so consumers refetch `snapshot()` with their own lookup options.
20
-
21
- An array returned by `SkillProvider.list()` is complete-discovery shorthand. `SkillProviderObservation` lets a provider expose candidates that remain directly loadable while reporting that the observation is not authoritative.
22
-
23
- ```ts type-equiv
24
- /** Provider candidates plus whether the current discovery is authoritative. */
25
- interface SkillProviderObservation {
26
- /** Candidates available from the current provider discovery. */
27
- readonly candidates: readonly SkillCandidate[]
28
- /** Whether discovery completed and these candidates may be cached. */
29
- readonly complete: boolean
30
- }
31
- ```
32
-
33
- ```ts type-equiv
34
- /** Provider interface for one source of skills, such as local directories or a remote registry. */
35
- interface SkillProvider {
36
- /** Unique provider name in the `ctx.skills` registry. */
37
- readonly name: string
38
- /**
39
- * List available skill candidates for the current lookup context. Provider
40
- * plugins register synchronously during `apply()`; remote initialization,
41
- * authentication, and discovery are awaited inside this method. Implementations
42
- * should settle promptly when `options.signal` aborts.
43
- * @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
44
- * @returns provider candidates as a complete-array shorthand, or an explicit
45
- * observation when usable candidates came from incomplete discovery.
46
- */
47
- readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>
48
- /**
49
- * Load a complete skill body for a previously listed candidate.
50
- * @param candidate - the winning candidate originally returned by this provider.
51
- * @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
52
- * @returns the full skill body, or `undefined` if it is no longer loadable.
53
- */
54
- readonly get: (candidate: SkillCandidate, options: SkillLookupOptions) => Promise<SkillDefinition | undefined>
55
- }
56
- ```
57
-
58
- ```ts type-equiv
59
- /** Registration-scoped lifecycle and invalidation capability borrowed by one provider. */
60
- interface SkillProviderControl {
61
- /** Aborts if registration fails or when the exact provider registration is disposed. */
62
- readonly signal: AbortSignal
63
- /** Invalidate completed catalogs and notify consumers only while the exact registration remains active. */
64
- readonly invalidate: () => void
65
- }
66
- ```
67
-
68
- ## Local discovery priority
69
-
70
- The shipped local provider scans roots in rank order:
71
-
72
- | Rank | Source | Root |
73
- |---|---|---|
74
- | 100 | `project-dsh` | `<projectRoot>/.dsh/skills` |
75
- | 200 | `project-agents` | `<projectRoot>/.agents/skills` |
76
- | 300 | `custom` | `Config.customSkillDirs` |
77
- | 400 | `user-dsh` | `<dshHome>/skills` |
78
- | 500 | `user-agents` | `<agentsHome>/skills` |
79
- | 600 | `bundled` | `Config.bundledSkillDir` when configured |
80
-
81
- The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. When `ctx.fs` is available, the git-root walk probes `.git` through the filesystem service so remote or sandboxed workspaces do not fall back to the host filesystem boundary. The user DSH root skips its `.system` child. The local provider does not synthesize built-in system skills; deployments supply packaged skills through configured bundled roots or dedicated providers. A failed root contributes no candidates, so a lower-priority same-name skill from another root may supply both the catalog description and loaded body until recovery.
82
-
83
- `dsh-skill-badge` registers one immutable `bundled` candidate at `BUNDLED_SKILL_RANK` and exposes its packaged asset directory through `resourceBase`. The shipped CLI declares the plugin disabled, so enabling its composition row is an explicit opt-in.
84
-
85
- Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete without hiding readable candidates from direct loads; project-scoped watchers use a configured bounded LRU.
86
-
87
- ## Skill identity
88
-
89
- Skill names are kebab-case (`^[a-z0-9]+(?:-[a-z0-9]+)*$`). The local provider accepts directory bundles (`<name>/SKILL.md`) and flat Markdown files (`<name>.md`). Nested recursive `**/SKILL.md` discovery is not supported.
90
-
91
- ```ts type-equiv
92
- /** Origin bucket for a skill contribution. The value is prompt-visible metadata, not precedence by itself. */
93
- type SkillSource = 'project-dsh' | 'project-agents' | 'runtime' | 'user-dsh' | 'user-agents' | 'custom' | 'bundled' | (string & {})
94
- ```
95
-
96
- ## Summaries, candidates, and complete definitions
97
-
98
- `SkillSummary` is the registry's invocation-neutral summary shape. Consumers choose which entries and fields to render; the model session catalog uses only model-invocable `name` and `description`, never the body or absolute file path. `SkillInvocationPolicy` normalizes the two independent invocation controls into positive booleans, and every resolved summary, candidate, and definition carries it without turning arbitrary frontmatter into the domain model.
99
-
100
- ```ts type-equiv
101
- /** Invocation controls shared by skill discovery consumers. */
102
- interface SkillInvocationPolicy {
103
- /** Whether model-facing catalogs and loaders include this skill. */
104
- readonly modelInvocable: boolean
105
- /** Whether human-facing command catalogs and loaders include this skill. */
106
- readonly userInvocable: boolean
107
- }
108
- ```
109
-
110
- ```ts type-equiv
111
- /** Invocation-neutral skill metadata returned by `ctx.skills.list()`. */
112
- interface SkillSummary {
113
- /** Absolute instruction file path when supplied by the provider; absent for virtual skills. */
114
- readonly path?: string
115
- /** Kebab-case identifier used to address the skill. */
116
- readonly name: string
117
- /** Short routing description shown by discovery consumers. */
118
- readonly description: string
119
- /** Optional extra routing guidance. */
120
- readonly whenToUse?: string
121
- /** Resolved model and user invocation controls. */
122
- readonly invocation: SkillInvocationPolicy
123
- /** Discovery source that produced this winning skill. */
124
- readonly source: SkillSource
125
- /** Provider that owns this skill body. */
126
- readonly provider: string
127
- /** Provider-specific base for relative resources. */
128
- readonly resourceBase?: SkillResourceBase
129
- }
130
- ```
131
-
132
- `ctx.skills.list()` preserves all four policy combinations. `isModelInvocable(skill)` and `isUserInvocable(skill)` read the corresponding required field. A model-only skill sets `{ modelInvocable: true, userInvocable: false }`, a user-only skill sets `{ modelInvocable: false, userInvocable: true }`, and setting both fields to `false` keeps the skill available only through trusted `ctx.skills.get()` callers. The local provider reads the exact kebab-case frontmatter keys `disable-model-invocation` and `user-invocable`, defaults omitted fields to `true`, and projects every parsed skill into this normalized policy.
133
-
134
- `SkillCatalogSnapshot` distinguishes authoritative absence from transient provider failure or a catalog that kept changing during discovery. `skills` contains the sorted invocation-neutral summaries collected in that observation; `complete` is true only when every registered provider completed without a concurrent catalog revision. Incomplete snapshots are not cached, so the next lookup retries discovery; each consumer decides how to present the partial result.
135
-
136
- ```ts type-equiv
137
- /** One catalog observation plus whether discovery completed within a stable catalog revision. */
138
- interface SkillCatalogSnapshot {
139
- /** Sorted invocation-neutral summaries collected in this observation. */
140
- readonly skills: SkillSummary[]
141
- /** Whether every registered provider completed without a concurrent catalog revision. */
142
- readonly complete: boolean
143
- }
144
- ```
145
-
146
- `SkillCandidate` is the provider-to-registry shape. `locator` is opaque provider state; the registry only stores it and gives it back to the winning provider's `get()`.
147
-
148
- ```ts type-equiv
149
- /** Provider catalog entry used by the registry to merge and later load skills. */
150
- interface SkillCandidate extends SkillSummary {
151
- /** Lower ranks win duplicate skill names before provider registration order is considered. */
152
- readonly rank: number
153
- /** Opaque provider-owned handle passed back to `provider.get()`. */
154
- readonly locator: unknown
155
- /** Parsed optional metadata object from provider-specific skill frontmatter. */
156
- readonly metadata?: Readonly<Record<string, unknown>>
157
- }
158
- ```
159
-
160
- `SkillDefinition` is the complete parsed result returned by `ctx.skills.get()` and used by the `skill` tool. `resourceBase` tells the tool how to render relative-resource guidance for local, URL, or provider-managed skills.
161
-
162
- ```ts type-equiv
163
- /** Optional provider-specific base used by loaded skill bodies to resolve relative resources. */
164
- type SkillResourceBase =
165
- | { readonly kind: 'directory'; readonly path: string }
166
- | { readonly kind: 'url'; readonly url: string }
167
- | { readonly kind: 'opaque'; readonly description: string }
168
- ```
169
-
170
- ```ts type-equiv
171
- /** Complete parsed skill definition, including the body loaded by `ctx.skills.get()`. */
172
- interface SkillDefinition extends SkillSummary {
173
- /** Markdown instruction body after any provider-specific metadata removal. */
174
- readonly content: string
175
- /** Parsed optional metadata object from frontmatter. */
176
- readonly metadata?: Readonly<Record<string, unknown>>
177
- }
178
- ```
179
-
180
- Runtime skill inputs may omit invocation controls and the provider label. The registry resolves both defaults once, then uses the same complete definition shape and first-wins collection order as providers. The returned disposer removes the contribution and invalidates discovery caches.
181
-
182
- ```ts type-equiv
183
- /** Runtime skill contribution accepted by `ctx.skills.register()`. */
184
- type SkillRegistration = Omit<SkillDefinition, 'invocation' | 'provider'> & {
185
- /** Invocation controls; omission permits both model and user surfaces. */
186
- readonly invocation?: SkillInvocationPolicy
187
- /** Provider label; omission uses the registry-owned runtime provider. */
188
- readonly provider?: string
189
- }
190
- ```
191
-
192
- ## Lookup and configuration
193
-
194
- Skill lookup is cwd-sensitive because providers may expose workspace-local skills, and its optional signal cancels provider work for the caller. Registry reads additionally take the viewing scope — consumers pass the calling agent, which is its own scope key — through `SkillViewOptions`; the registry consumes `scope` for layer selection, and providers read only their `SkillLookupOptions` contract from the same borrowed options object. Cancellation is checked before and after catalog selection, including cache hits, and races both discovery and full-definition loading. If no git root is found, the local provider treats the supplied cwd itself as the project root.
195
-
196
- Full definitions are not cached by the registry. Each `get()` calls the winning provider with the selected candidate, so the local provider rereads the current body. A definition whose name no longer matches that candidate is rejected and invalidates the exact provider for rediscovery.
197
-
198
- ```ts type-equiv
199
- /** Caller context used for cwd-sensitive and abortable provider work. */
200
- interface SkillLookupOptions {
201
- /** Workspace selector for the current lookup. */
202
- readonly cwd?: string | undefined
203
- /** Abort discovery or loading work for the current caller. */
204
- readonly signal?: AbortSignal | undefined
205
- }
206
- ```
207
-
208
- ```ts type-equiv
209
- /**
210
- * Registry read options: provider lookup context plus the viewing scope.
211
- * The registry consumes `scope` to select layers; providers receive the same
212
- * borrowed options object and read only their {@link SkillLookupOptions}
213
- * contract from it.
214
- */
215
- interface SkillViewOptions extends SkillLookupOptions {
216
- /** Viewing scope (the calling agent); omitted reads the global layer alone. */
217
- readonly scope?: ScopeKey | undefined
218
- }
219
- ```
220
-
221
- The registry owns only its discovery-cache bound. The local provider owns filesystem roots (`dshHome`, `agentsHome`, `customSkillDirs`, and optional `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`) plus watcher enablement, polling, stability, symlink, and project-capacity controls. The consumer owns its catalog description bound. Exact defaults and validation are in the generated [config catalog](../config-catalog.md).
222
-
223
- ```ts type-equiv
224
- /** Skill registry configuration. */
225
- interface Config {
226
- /** Maximum number of completed cwd/provider catalogs kept in memory. */
227
- readonly collectCacheMaxEntries?: number
228
- }
229
- ```
230
-
231
- ## Session catalog and tool contract
232
-
233
- `dsh-tool-skill` injects the initial durable user-role `<system-reminder>` at the first `agent/pre-step` of a live session that observes available skills or incomplete discovery. The catalog contains sorted skill `name` and normalized, XML-escaped `description` only; it omits bodies, paths, sources, providers, and routing hints. Discovery forwards the step's abort signal through `SkillLookupOptions`. `catalogDescriptionMaxLength` is the consumer config for the description bound, with default `500` and integer minimum `3`.
234
-
235
- Before each later model step, the consumer applies exact tool visibility and compares the entries and completeness with the newest recognizable visible catalog message in the session log. A changed observation contributes a durable replacement to the pre-step decision; deleting every skill appends an explicit empty replacement. Incomplete discovery publishes the available subset with a warning and optional `incomplete: true` source metadata; absence of that flag means complete. Recovery republishes the catalog even when its entries are unchanged. If compaction hides every historical catalog message, the next observation re-establishes the current catalog; a complete empty view with no prior catalog emits nothing. These catalog messages are session history, not World State.
236
-
237
- The model-facing `skill({ name })` tool validates the kebab-case name, finds the summary in the invocation-neutral catalog, rejects it before loading unless `isModelInvocable` permits access, then rereads the complete definition for the calling agent cwd and rechecks the policy before returning content. It reports an unresolved skill as unknown or no longer available and returns a tool result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`. `resourceBase` resolves explicitly referenced scripts, references, and assets only as needed; the loaded result does not enumerate a skill directory. Body-only edits therefore change later tool calls without producing catalog messages or rewriting earlier tool results.
238
-
239
- ## Browser Session catalog
240
-
241
- `SkillListRequest` addresses one Session by `sessionId`; `SkillListValue` returns the user-invocable entries with name, description, optional usage guidance, and model-invocation availability. `SessionSkillCatalog` reads the Session cwd and recorded preset without activating an Agent. A live Agent may supply its scoped registry, while a cold Session uses the preset's standing scope.
242
-
243
- <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
244
-
245
- <a id="cordis-surface"></a>
246
-
247
- ## Cordis API
248
-
249
- 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`) — the language sides differ only in locale-specific paired document paths. 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).
250
-
251
- <a id="ctxsessionskillcatalog--sessionskillcatalog"></a>
252
-
253
- ### `ctx.sessionSkillCatalog` — `SessionSkillCatalog`
254
-
255
- Host service backing `ctx.remote.skills` without activating a cold Agent.
256
-
257
- ```ts cordis-catalog
258
- /**
259
- * List the user-invocable skills visible to one Session composition.
260
- * @param request - Session identity whose cwd and preset select the catalog view.
261
- * @param signal - caller lifetime carried by the Remote transport; admitted catalog reads retain their existing completion semantics.
262
- * @returns user-invocable skill metadata without loading skill bodies.
263
- * @throws RemoteError when the Session cannot be inspected or no registry can serve it.
264
- */
265
- @Remote async list(request: SkillListRequest, signal: AbortSignal): Promise<SkillListValue>
266
- ```
267
-
268
- Source: [`packages/api/session-controller/src/skill-catalog.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/session-controller/src/skill-catalog.ts)
269
-
270
- <a id="ctxskills--skillregistry"></a>
271
-
272
- ### `ctx.skills` — `SkillRegistry`
273
-
274
- Layered registry of skill providers, the host+per-scope shape the tools registry established. A registration files into the layer of its calling context's scope (scopeOf): host rows and repository plugins land in the global layer, while a plugin mounted by an agent preset's standing composition lands in that preset's layer. A read merges the global layer with the viewing scope's chain — the nearest layer's entry wins a duplicate name outright, and the rank order decides duplicates only within one layer. It exposes sorted invocation-neutral summaries and loads full skill bodies on demand.
275
-
276
- ```ts cordis-catalog
277
- /**
278
- * Register a borrowed same-process provider synchronously during plugin
279
- * apply, into the calling context's layer: a scoped context (an agent
280
- * preset's standing mount) registers for that scope alone, an unscoped
281
- * context registers globally. Duplicate names within one layer and reserved
282
- * names throw; remote initialization belongs in `list()`. Fiber disposal
283
- * unregisters the provider and invalidates catalog caches.
284
- * @param create - synchronous factory receiving this registration's lifecycle and invalidation control.
285
- * @returns the exact Cordis effect disposer that unregisters this provider;
286
- * composite effects may yield it directly to preserve teardown ordering.
287
- */
288
- registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void
289
-
290
- /**
291
- * Register a borrowed readonly runtime skill into the calling context's
292
- * layer. Project entries outrank runtime entries, which outrank user
293
- * entries, within one layer. Same-name runtime entries in one layer are
294
- * first-wins; a duplicate logs a warning and receives a no-op disposer so
295
- * it cannot remove the winner.
296
- * @param skill - the skill definition input; omitted invocation and provider fields receive defaults.
297
- * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.
298
- */
299
- register(skill: SkillRegistration): () => void
300
-
301
- /**
302
- * List invocation-neutral skill summaries for a workspace. Consumers apply
303
- * model or user invocation policy at their operational boundary. Lookup
304
- * options and provider candidates are readonly same-process values borrowed
305
- * throughout discovery.
306
- * @param options - view options; `scope` selects the viewing agent's layers, `cwd` selects project roots, and `signal` cancels discovery.
307
- * @returns all sorted winning summaries.
308
- */
309
- async list(options: SkillViewOptions = {}): Promise<SkillSummary[]>
310
-
311
- /**
312
- * Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.
313
- * Incomplete observations are never cached, allowing consumers to retain last-good state and
314
- * retry on their next request boundary.
315
- * @param options - view options; `scope` selects the viewing agent's layers, `cwd` selects project roots, and `signal` cancels discovery.
316
- * @returns sorted summaries plus discovery-completeness state.
317
- */
318
- async snapshot(options: SkillViewOptions = {}): Promise<SkillCatalogSnapshot>
319
-
320
- /**
321
- * Load and validate the winning candidate, passing its opaque discovery locator back to the
322
- * provider. Cancellation is rechecked after selection, including cache hits, and raced against
323
- * loading so an uncooperative provider cannot hang the caller.
324
- * @param name - kebab-case skill name.
325
- * @param options - view options; `scope` selects the viewing agent's layers,
326
- * `cwd` selects workspace-sensitive skills, and `signal` cancels work.
327
- * @returns the full skill, including body content, or `undefined`.
328
- */
329
- async get(name: string, options: SkillViewOptions = {}): Promise<SkillDefinition | undefined>
330
- ```
331
-
332
- Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts)
333
-
334
- <a id="skills-events"></a>
335
-
336
- ### `skills/*` events
337
-
338
- <a id="skillschange--emit"></a>
339
-
340
- #### `skills/change` — emit
341
-
342
- A skill provider, runtime contribution, or provider-backed catalog may have changed. This is an unfiltered invalidation notification; consumers refetch the catalog for their own lookup options. Listener failures are contained and cannot veto the registry mutation.
343
-
344
- ```ts cordis-catalog
345
- /**
346
- * A skill provider, runtime contribution, or provider-backed catalog may
347
- * have changed. This is an unfiltered invalidation notification; consumers
348
- * refetch the catalog for their own lookup options. Listener failures are
349
- * contained and cannot veto the registry mutation.
350
- * @mode emit
351
- */
352
- 'skills/change'(): void
353
- ```
354
-
355
- Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts)
356
- <!-- END GENERATED cordis-surface -->
1
+ ---
2
+ editSource: "docs/subsystems/skills.md"
3
+ rawMarkdownPath: "en/reference/subsystems/skills.md"
4
+ outline: [2,3]
5
+ ---
6
+
7
+ # Skills
8
+
9
+ The [skill capability family](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill) includes the Service Definition ([dsh-skill](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill), `ctx.skills`), the local Service Provider ([dsh-skill-filesystem](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill-filesystem)), optional packaged providers ([dsh-skill-badge](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/experimental/skill-badge), [dsh-skill-office](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/skill-office), and the Windows ACL diagnosis provider in [dsh-sandbox-windows-acl](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/sandbox/sandbox-windows-acl)), and the Consumer ([dsh-tool-skill](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/skill/tool-skill)). The registry merges provider catalogs across its host and per-scope layers; providers contribute local or packaged skills; the Consumer owns the initial and replacement catalogs plus the model-facing `skill` tool. Skills are optional instructions, not session events, so their vocabulary lives here rather than in [core.md](./core.md).
10
+
11
+ Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts), [`packages/skill/skill-filesystem/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-filesystem/src/index.ts), [`packages/experimental/skill-badge/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/experimental/skill-badge/src/index.ts), [`packages/skill/skill-office/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill-office/src/index.ts), [`packages/sandbox/sandbox-windows-acl/src/acl-skill.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/sandbox/sandbox-windows-acl/src/acl-skill.ts), and [`packages/skill/tool-skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/tool-skill/src/index.ts).
12
+
13
+ ## Provider registry
14
+
15
+ `ctx.skills` combines local, embedded, remote, or other providers. Registration is synchronous; remote initialization and discovery belong in awaited `list()`. Provider objects, options, and candidates are borrowed readonly, while semantic fields are validated.
16
+
17
+ The registry is host+per-scope layered, the shape the [tools registry](./tools.md) established over [dsh-scope](https://github.com/deepseek-ai/deepseek-harness/tree/master/packages/core/scope): a registration files into the layer of its calling context's scope, so host rows and repository plugins land in the global layer while a plugin mounted by an agent preset's standing composition lands in that preset's layer, and provider names are unique per layer rather than process-wide. A read merges the global layer with the viewing scope's chain — the nearest layer's entry wins a duplicate skill name outright, and the rank order below decides duplicates only within one layer. Discovery caches are keyed by the resolved scope chain, so re-parenting a scope (a blank-session recompose) is visible to the next read without a registry mutation.
18
+
19
+ Within one layer, duplicate names resolve by rank, provider order, then local order; summaries sort by name. A rejected `list()` is logged and omitted from an incomplete observation, while an explicit incomplete observation contributes usable candidates without making the result cacheable; malformed candidates fail fast as `SkillError` with `SKILL_INVALID_DEFINITION`. Each provider factory receives a registration-scoped control whose `invalidate()` clears completed catalogs only while that exact registration remains active and whose signal aborts on failed registration or disposal. An in-flight discovery retries once when its provider generation changes; a second change returns the latest candidates incomplete and uncached. Provider and runtime mutations emit the unfiltered `skills/change` invalidation event; it carries no diff, so consumers refetch `snapshot()` with their own lookup options.
20
+
21
+ An array returned by `SkillProvider.list()` is complete-discovery shorthand. `SkillProviderObservation` lets a provider expose candidates that remain directly loadable while reporting that the observation is not authoritative.
22
+
23
+ ```ts type-equiv
24
+ /** Provider candidates plus whether the current discovery is authoritative. */
25
+ interface SkillProviderObservation {
26
+ /** Candidates available from the current provider discovery. */
27
+ readonly candidates: readonly SkillCandidate[]
28
+ /** Whether discovery completed and these candidates may be cached. */
29
+ readonly complete: boolean
30
+ }
31
+ ```
32
+
33
+ ```ts type-equiv
34
+ /** Provider interface for one source of skills, such as local directories or a remote registry. */
35
+ interface SkillProvider {
36
+ /** Unique provider name in the `ctx.skills` registry. */
37
+ readonly name: string
38
+ /**
39
+ * List available skill candidates for the current lookup context. Provider
40
+ * plugins register synchronously during `apply()`; remote initialization,
41
+ * authentication, and discovery are awaited inside this method. Implementations
42
+ * should settle promptly when `options.signal` aborts.
43
+ * @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
44
+ * @returns provider candidates as a complete-array shorthand, or an explicit
45
+ * observation when usable candidates came from incomplete discovery.
46
+ */
47
+ readonly list: (options: SkillLookupOptions) => Promise<readonly SkillCandidate[] | SkillProviderObservation>
48
+ /**
49
+ * Load a complete skill body for a previously listed candidate.
50
+ * @param candidate - the winning candidate originally returned by this provider.
51
+ * @param options - lookup options; `cwd` selects workspace-sensitive skills and `signal` cancels work.
52
+ * @returns the full skill body, or `undefined` if it is no longer loadable.
53
+ */
54
+ readonly get: (candidate: SkillCandidate, options: SkillLookupOptions) => Promise<SkillDefinition | undefined>
55
+ }
56
+ ```
57
+
58
+ ```ts type-equiv
59
+ /** Registration-scoped lifecycle and invalidation capability borrowed by one provider. */
60
+ interface SkillProviderControl {
61
+ /** Aborts if registration fails or when the exact provider registration is disposed. */
62
+ readonly signal: AbortSignal
63
+ /** Invalidate completed catalogs and notify consumers only while the exact registration remains active. */
64
+ readonly invalidate: () => void
65
+ }
66
+ ```
67
+
68
+ ## Local discovery priority
69
+
70
+ The shipped local provider scans roots in rank order:
71
+
72
+ | Rank | Source | Root |
73
+ |---|---|---|
74
+ | 100 | `project-dsh` | `<projectRoot>/.dsh/skills` |
75
+ | 200 | `project-agents` | `<projectRoot>/.agents/skills` |
76
+ | 300 | `custom` | `Config.customSkillDirs` |
77
+ | 400 | `user-dsh` | `<dshHome>/skills` |
78
+ | 500 | `user-agents` | `<agentsHome>/skills` |
79
+ | 600 | `bundled` | `Config.bundledSkillDir` when configured |
80
+
81
+ The project root is the nearest ancestor containing `.git`; without one, the current cwd is used. When `ctx.fs` is available, the git-root walk probes `.git` through the filesystem service so remote or sandboxed workspaces do not fall back to the host filesystem boundary. The user DSH root skips its `.system` child. The local provider does not synthesize built-in system skills; deployments supply packaged skills through configured bundled roots or dedicated providers. A failed root contributes no candidates, so a lower-priority same-name skill from another root may supply both the catalog description and loaded body until recovery.
82
+
83
+ `dsh-skill-badge` registers one immutable `bundled` candidate at `BUNDLED_SKILL_RANK` and exposes its packaged asset directory through `resourceBase`. The shipped CLI declares the plugin disabled, so enabling its composition row is an explicit opt-in.
84
+
85
+ Chokidar watches existing roots for direct bundle/flat-entry additions and removals plus direct skill-entry changes. A missing root is followed one absent path segment at a time from its nearest existing ancestor until Chokidar can attach. Resource files below a bundle are not catalog changes. Model-facing `write` and `edit` observations synchronously invalidate the provider when their target is catalog-relevant, while the host watcher covers IDE, Git, shell, and external-process mutations. Watcher failures make the current observation incomplete without hiding readable candidates from direct loads; project-scoped watchers use a configured bounded LRU.
86
+
87
+ ## Skill identity
88
+
89
+ Skill names are kebab-case (`^[a-z0-9]+(?:-[a-z0-9]+)*$`). The local provider accepts directory bundles (`<name>/SKILL.md`) and flat Markdown files (`<name>.md`). Nested recursive `**/SKILL.md` discovery is not supported.
90
+
91
+ ```ts type-equiv
92
+ /** Origin bucket for a skill contribution. The value is prompt-visible metadata, not precedence by itself. */
93
+ type SkillSource = 'project-dsh' | 'project-agents' | 'runtime' | 'user-dsh' | 'user-agents' | 'custom' | 'bundled' | (string & {})
94
+ ```
95
+
96
+ ## Summaries, candidates, and complete definitions
97
+
98
+ `SkillSummary` is the registry's invocation-neutral summary shape. Consumers choose which entries and fields to render; the model session catalog uses only model-invocable `name` and `description`, never the body or absolute file path. `SkillInvocationPolicy` normalizes the two independent invocation controls into positive booleans, and every resolved summary, candidate, and definition carries it without turning arbitrary frontmatter into the domain model.
99
+
100
+ ```ts type-equiv
101
+ /** Invocation controls shared by skill discovery consumers. */
102
+ interface SkillInvocationPolicy {
103
+ /** Whether model-facing catalogs and loaders include this skill. */
104
+ readonly modelInvocable: boolean
105
+ /** Whether human-facing command catalogs and loaders include this skill. */
106
+ readonly userInvocable: boolean
107
+ }
108
+ ```
109
+
110
+ ```ts type-equiv
111
+ /** Invocation-neutral skill metadata returned by `ctx.skills.list()`. */
112
+ interface SkillSummary {
113
+ /** Absolute instruction file path when supplied by the provider; absent for virtual skills. */
114
+ readonly path?: string
115
+ /** Kebab-case identifier used to address the skill. */
116
+ readonly name: string
117
+ /** Short routing description shown by discovery consumers. */
118
+ readonly description: string
119
+ /** Optional extra routing guidance. */
120
+ readonly whenToUse?: string
121
+ /** Resolved model and user invocation controls. */
122
+ readonly invocation: SkillInvocationPolicy
123
+ /** Discovery source that produced this winning skill. */
124
+ readonly source: SkillSource
125
+ /** Provider that owns this skill body. */
126
+ readonly provider: string
127
+ /** Provider-specific base for relative resources. */
128
+ readonly resourceBase?: SkillResourceBase
129
+ }
130
+ ```
131
+
132
+ `ctx.skills.list()` preserves all four policy combinations. `isModelInvocable(skill)` and `isUserInvocable(skill)` read the corresponding required field. A model-only skill sets `{ modelInvocable: true, userInvocable: false }`, a user-only skill sets `{ modelInvocable: false, userInvocable: true }`, and setting both fields to `false` keeps the skill available only through trusted `ctx.skills.get()` callers. The local provider reads the exact kebab-case frontmatter keys `disable-model-invocation` and `user-invocable`, defaults omitted fields to `true`, and projects every parsed skill into this normalized policy.
133
+
134
+ `SkillCatalogSnapshot` distinguishes authoritative absence from transient provider failure or a catalog that kept changing during discovery. `skills` contains the sorted invocation-neutral summaries collected in that observation; `complete` is true only when every registered provider completed without a concurrent catalog revision. Incomplete snapshots are not cached, so the next lookup retries discovery; each consumer decides how to present the partial result.
135
+
136
+ ```ts type-equiv
137
+ /** One catalog observation plus whether discovery completed within a stable catalog revision. */
138
+ interface SkillCatalogSnapshot {
139
+ /** Sorted invocation-neutral summaries collected in this observation. */
140
+ readonly skills: SkillSummary[]
141
+ /** Whether every registered provider completed without a concurrent catalog revision. */
142
+ readonly complete: boolean
143
+ }
144
+ ```
145
+
146
+ `SkillCandidate` is the provider-to-registry shape. `locator` is opaque provider state; the registry only stores it and gives it back to the winning provider's `get()`.
147
+
148
+ ```ts type-equiv
149
+ /** Provider catalog entry used by the registry to merge and later load skills. */
150
+ interface SkillCandidate extends SkillSummary {
151
+ /** Lower ranks win duplicate skill names before provider registration order is considered. */
152
+ readonly rank: number
153
+ /** Opaque provider-owned handle passed back to `provider.get()`. */
154
+ readonly locator: unknown
155
+ /** Parsed optional metadata object from provider-specific skill frontmatter. */
156
+ readonly metadata?: Readonly<Record<string, unknown>>
157
+ }
158
+ ```
159
+
160
+ `SkillDefinition` is the complete parsed result returned by `ctx.skills.get()` and used by the `skill` tool. `resourceBase` tells the tool how to render relative-resource guidance for local, URL, or provider-managed skills.
161
+
162
+ ```ts type-equiv
163
+ /** Optional provider-specific base used by loaded skill bodies to resolve relative resources. */
164
+ type SkillResourceBase =
165
+ | { readonly kind: 'directory'; readonly path: string }
166
+ | { readonly kind: 'url'; readonly url: string }
167
+ | { readonly kind: 'opaque'; readonly description: string }
168
+ ```
169
+
170
+ ```ts type-equiv
171
+ /** Complete parsed skill definition, including the body loaded by `ctx.skills.get()`. */
172
+ interface SkillDefinition extends SkillSummary {
173
+ /** Markdown instruction body after any provider-specific metadata removal. */
174
+ readonly content: string
175
+ /** Parsed optional metadata object from frontmatter. */
176
+ readonly metadata?: Readonly<Record<string, unknown>>
177
+ }
178
+ ```
179
+
180
+ Runtime skill inputs may omit invocation controls and the provider label. The registry resolves both defaults once, then uses the same complete definition shape and first-wins collection order as providers. The returned disposer removes the contribution and invalidates discovery caches.
181
+
182
+ ```ts type-equiv
183
+ /** Runtime skill contribution accepted by `ctx.skills.register()`. */
184
+ type SkillRegistration = Omit<SkillDefinition, 'invocation' | 'provider'> & {
185
+ /** Invocation controls; omission permits both model and user surfaces. */
186
+ readonly invocation?: SkillInvocationPolicy
187
+ /** Provider label; omission uses the registry-owned runtime provider. */
188
+ readonly provider?: string
189
+ }
190
+ ```
191
+
192
+ ## Lookup and configuration
193
+
194
+ Skill lookup is cwd-sensitive because providers may expose workspace-local skills, and its optional signal cancels provider work for the caller. Registry reads additionally take the viewing scope — consumers pass the calling agent, which is its own scope key — through `SkillViewOptions`; the registry consumes `scope` for layer selection, and providers read only their `SkillLookupOptions` contract from the same borrowed options object. Cancellation is checked before and after catalog selection, including cache hits, and races both discovery and full-definition loading. If no git root is found, the local provider treats the supplied cwd itself as the project root.
195
+
196
+ Full definitions are not cached by the registry. Each `get()` calls the winning provider with the selected candidate, so the local provider rereads the current body. A definition whose name no longer matches that candidate is rejected and invalidates the exact provider for rediscovery.
197
+
198
+ ```ts type-equiv
199
+ /** Caller context used for cwd-sensitive and abortable provider work. */
200
+ interface SkillLookupOptions {
201
+ /** Workspace selector for the current lookup. */
202
+ readonly cwd?: string | undefined
203
+ /** Abort discovery or loading work for the current caller. */
204
+ readonly signal?: AbortSignal | undefined
205
+ }
206
+ ```
207
+
208
+ ```ts type-equiv
209
+ /**
210
+ * Registry read options: provider lookup context plus the viewing scope.
211
+ * The registry consumes `scope` to select layers; providers receive the same
212
+ * borrowed options object and read only their {@link SkillLookupOptions}
213
+ * contract from it.
214
+ */
215
+ interface SkillViewOptions extends SkillLookupOptions {
216
+ /** Viewing scope (the calling agent); omitted reads the global layer alone. */
217
+ readonly scope?: ScopeKey | undefined
218
+ }
219
+ ```
220
+
221
+ The registry owns only its discovery-cache bound. The local provider owns filesystem roots (`dshHome`, `agentsHome`, `customSkillDirs`, and optional `bundledSkillDir`/`DSH_BUNDLED_SKILL_DIR`) plus watcher enablement, polling, stability, symlink, and project-capacity controls. The consumer owns its catalog description bound. Exact defaults and validation are in the generated [config catalog](../config-catalog.md).
222
+
223
+ ```ts type-equiv
224
+ /** Skill registry configuration. */
225
+ interface Config {
226
+ /** Maximum number of completed cwd/provider catalogs kept in memory. */
227
+ readonly collectCacheMaxEntries?: number
228
+ }
229
+ ```
230
+
231
+ ## Session catalog and tool contract
232
+
233
+ `dsh-tool-skill` injects the initial durable user-role `<system-reminder>` at the first `agent/pre-step` of a live session that observes available skills or incomplete discovery. The catalog contains sorted skill `name` and normalized, XML-escaped `description` only; it omits bodies, paths, sources, providers, and routing hints. Discovery forwards the step's abort signal through `SkillLookupOptions`. `catalogDescriptionMaxLength` is the consumer config for the description bound, with default `500` and integer minimum `3`.
234
+
235
+ Before each later model step, the consumer applies exact tool visibility and compares the entries and completeness with the newest recognizable visible catalog message in the session log. A changed observation contributes a durable replacement to the pre-step decision; deleting every skill appends an explicit empty replacement. Incomplete discovery publishes the available subset with a warning and optional `incomplete: true` source metadata; absence of that flag means complete. Recovery republishes the catalog even when its entries are unchanged. If compaction hides every historical catalog message, the next observation re-establishes the current catalog; a complete empty view with no prior catalog emits nothing. These catalog messages are session history, not World State.
236
+
237
+ The model-facing `skill({ name })` tool validates the kebab-case name, finds the summary in the invocation-neutral catalog, rejects it before loading unless `isModelInvocable` permits access, then rereads the complete definition for the calling agent cwd and rechecks the policy before returning content. It reports an unresolved skill as unknown or no longer available and returns a tool result containing `<skill_content name="...">`, `<skill_resources>`, and `<skill_instructions>`. `resourceBase` resolves explicitly referenced scripts, references, and assets only as needed; the loaded result does not enumerate a skill directory. Body-only edits therefore change later tool calls without producing catalog messages or rewriting earlier tool results.
238
+
239
+ ## Browser Session catalog
240
+
241
+ `SkillListRequest` addresses one Session by `sessionId`; `SkillListValue` returns the user-invocable entries with name, description, optional usage guidance, and model-invocation availability. `SessionSkillCatalog` reads the Session cwd and recorded preset without activating an Agent. A live Agent may supply its scoped registry, while a cold Session uses the preset's standing scope.
242
+
243
+ <!-- BEGIN GENERATED cordis-surface (gen-cordis-catalog.ts) — do not edit between markers -->
244
+
245
+ <a id="cordis-surface"></a>
246
+
247
+ ## Cordis API
248
+
249
+ 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`) — the language sides differ only in locale-specific paired document paths. 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).
250
+
251
+ <a id="ctxsessionskillcatalog--sessionskillcatalog"></a>
252
+
253
+ ### `ctx.sessionSkillCatalog` — `SessionSkillCatalog`
254
+
255
+ Host service backing `ctx.remote.skills` without activating a cold Agent.
256
+
257
+ ```ts cordis-catalog
258
+ /**
259
+ * List the user-invocable skills visible to one Session composition.
260
+ * @param request - Session identity whose cwd and preset select the catalog view.
261
+ * @param signal - caller lifetime carried by the Remote transport; admitted catalog reads retain their existing completion semantics.
262
+ * @returns user-invocable skill metadata without loading skill bodies.
263
+ * @throws RemoteError when the Session cannot be inspected or no registry can serve it.
264
+ */
265
+ @Remote async list(request: SkillListRequest, signal: AbortSignal): Promise<SkillListValue>
266
+ ```
267
+
268
+ Source: [`packages/api/session-controller/src/skill-catalog.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/api/session-controller/src/skill-catalog.ts)
269
+
270
+ <a id="ctxskills--skillregistry"></a>
271
+
272
+ ### `ctx.skills` — `SkillRegistry`
273
+
274
+ Layered registry of skill providers, the host+per-scope shape the tools registry established. A registration files into the layer of its calling context's scope (scopeOf): host rows and repository plugins land in the global layer, while a plugin mounted by an agent preset's standing composition lands in that preset's layer. A read merges the global layer with the viewing scope's chain — the nearest layer's entry wins a duplicate name outright, and the rank order decides duplicates only within one layer. It exposes sorted invocation-neutral summaries and loads full skill bodies on demand.
275
+
276
+ ```ts cordis-catalog
277
+ /**
278
+ * Register a borrowed same-process provider synchronously during plugin
279
+ * apply, into the calling context's layer: a scoped context (an agent
280
+ * preset's standing mount) registers for that scope alone, an unscoped
281
+ * context registers globally. Duplicate names within one layer and reserved
282
+ * names throw; remote initialization belongs in `list()`. Fiber disposal
283
+ * unregisters the provider and invalidates catalog caches.
284
+ * @param create - synchronous factory receiving this registration's lifecycle and invalidation control.
285
+ * @returns the exact Cordis effect disposer that unregisters this provider;
286
+ * composite effects may yield it directly to preserve teardown ordering.
287
+ */
288
+ registerProvider(create: (control: SkillProviderControl) => SkillProvider): () => void
289
+
290
+ /**
291
+ * Register a borrowed readonly runtime skill into the calling context's
292
+ * layer. Project entries outrank runtime entries, which outrank user
293
+ * entries, within one layer. Same-name runtime entries in one layer are
294
+ * first-wins; a duplicate logs a warning and receives a no-op disposer so
295
+ * it cannot remove the winner.
296
+ * @param skill - the skill definition input; omitted invocation and provider fields receive defaults.
297
+ * @returns the exact Cordis effect disposer, preserving composite teardown order and invalidating caches.
298
+ */
299
+ register(skill: SkillRegistration): () => void
300
+
301
+ /**
302
+ * List invocation-neutral skill summaries for a workspace. Consumers apply
303
+ * model or user invocation policy at their operational boundary. Lookup
304
+ * options and provider candidates are readonly same-process values borrowed
305
+ * throughout discovery.
306
+ * @param options - view options; `scope` selects the viewing agent's layers, `cwd` selects project roots, and `signal` cancels discovery.
307
+ * @returns all sorted winning summaries.
308
+ */
309
+ async list(options: SkillViewOptions = {}): Promise<SkillSummary[]>
310
+
311
+ /**
312
+ * Observe the current invocation-neutral catalog and whether discovery completed within a stable revision.
313
+ * Incomplete observations are never cached, allowing consumers to retain last-good state and
314
+ * retry on their next request boundary.
315
+ * @param options - view options; `scope` selects the viewing agent's layers, `cwd` selects project roots, and `signal` cancels discovery.
316
+ * @returns sorted summaries plus discovery-completeness state.
317
+ */
318
+ async snapshot(options: SkillViewOptions = {}): Promise<SkillCatalogSnapshot>
319
+
320
+ /**
321
+ * Load and validate the winning candidate, passing its opaque discovery locator back to the
322
+ * provider. Cancellation is rechecked after selection, including cache hits, and raced against
323
+ * loading so an uncooperative provider cannot hang the caller.
324
+ * @param name - kebab-case skill name.
325
+ * @param options - view options; `scope` selects the viewing agent's layers,
326
+ * `cwd` selects workspace-sensitive skills, and `signal` cancels work.
327
+ * @returns the full skill, including body content, or `undefined`.
328
+ */
329
+ async get(name: string, options: SkillViewOptions = {}): Promise<SkillDefinition | undefined>
330
+ ```
331
+
332
+ Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts)
333
+
334
+ <a id="skills-events"></a>
335
+
336
+ ### `skills/*` events
337
+
338
+ <a id="skillschange--emit"></a>
339
+
340
+ #### `skills/change` — emit
341
+
342
+ A skill provider, runtime contribution, or provider-backed catalog may have changed. This is an unfiltered invalidation notification; consumers refetch the catalog for their own lookup options. Listener failures are contained and cannot veto the registry mutation.
343
+
344
+ ```ts cordis-catalog
345
+ /**
346
+ * A skill provider, runtime contribution, or provider-backed catalog may
347
+ * have changed. This is an unfiltered invalidation notification; consumers
348
+ * refetch the catalog for their own lookup options. Listener failures are
349
+ * contained and cannot veto the registry mutation.
350
+ * @mode emit
351
+ */
352
+ 'skills/change'(): void
353
+ ```
354
+
355
+ Source: [`packages/skill/skill/src/index.ts`](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/skill/skill/src/index.ts)
356
+ <!-- END GENERATED cordis-surface -->