@canonical/pragma-cli 0.38.0 → 0.40.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 (330) hide show
  1. package/README.md +1 -1
  2. package/dist/package.json +14 -14
  3. package/dist/pragma.conf.js +273 -176
  4. package/dist/pragma.conf.js.map +1 -1
  5. package/dist/src/capabilities/capabilities/capabilities.verb.js +2 -0
  6. package/dist/src/capabilities/capabilities/capabilities.verb.js.map +1 -1
  7. package/dist/src/capabilities/capabilities/catalog.js +47 -51
  8. package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
  9. package/dist/src/capabilities/capabilities/index.js +2 -0
  10. package/dist/src/capabilities/capabilities/index.js.map +1 -1
  11. package/dist/src/capabilities/capabilities/types.js +5 -5
  12. package/dist/src/capabilities/colophon/colophon.render.js +7 -4
  13. package/dist/src/capabilities/colophon/colophon.render.js.map +1 -1
  14. package/dist/src/capabilities/colophon/colophon.verb.js +1 -0
  15. package/dist/src/capabilities/colophon/colophon.verb.js.map +1 -1
  16. package/dist/src/capabilities/config/get.verb.js +2 -0
  17. package/dist/src/capabilities/config/get.verb.js.map +1 -1
  18. package/dist/src/capabilities/config/runField.js +2 -2
  19. package/dist/src/capabilities/config/runField.js.map +1 -1
  20. package/dist/src/capabilities/config/set.verb.js +2 -0
  21. package/dist/src/capabilities/config/set.verb.js.map +1 -1
  22. package/dist/src/capabilities/config/show.verb.js +1 -0
  23. package/dist/src/capabilities/config/show.verb.js.map +1 -1
  24. package/dist/src/capabilities/config/unset.verb.js +2 -0
  25. package/dist/src/capabilities/config/unset.verb.js.map +1 -1
  26. package/dist/src/capabilities/create/constants.js +2 -2
  27. package/dist/src/capabilities/create/create.verb.js +14 -4
  28. package/dist/src/capabilities/create/create.verb.js.map +1 -1
  29. package/dist/src/capabilities/distribution.js +3 -1
  30. package/dist/src/capabilities/distribution.js.map +1 -1
  31. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +10 -2
  32. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -1
  33. package/dist/src/capabilities/doctor/doctor.verb.js +2 -0
  34. package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -1
  35. package/dist/src/capabilities/graph/connect.verb.js +2 -0
  36. package/dist/src/capabilities/graph/connect.verb.js.map +1 -1
  37. package/dist/src/capabilities/graph/inspect.render.js +7 -1
  38. package/dist/src/capabilities/graph/inspect.render.js.map +1 -1
  39. package/dist/src/capabilities/graph/inspect.verb.js +2 -0
  40. package/dist/src/capabilities/graph/inspect.verb.js.map +1 -1
  41. package/dist/src/capabilities/graph/query.render.js +37 -5
  42. package/dist/src/capabilities/graph/query.render.js.map +1 -1
  43. package/dist/src/capabilities/graph/query.verb.js +2 -0
  44. package/dist/src/capabilities/graph/query.verb.js.map +1 -1
  45. package/dist/src/capabilities/graph/queryText.js +28 -0
  46. package/dist/src/capabilities/graph/queryText.js.map +1 -1
  47. package/dist/src/capabilities/graph/runConnect.js +3 -3
  48. package/dist/src/capabilities/graph/runConnect.js.map +1 -1
  49. package/dist/src/capabilities/graph/runQuery.js +8 -6
  50. package/dist/src/capabilities/graph/runQuery.js.map +1 -1
  51. package/dist/src/capabilities/info/info.verb.js +2 -0
  52. package/dist/src/capabilities/info/info.verb.js.map +1 -1
  53. package/dist/src/capabilities/meta/mcp.verb.js +1 -0
  54. package/dist/src/capabilities/meta/mcp.verb.js.map +1 -1
  55. package/dist/src/capabilities/ontology/verbs.js +7 -10
  56. package/dist/src/capabilities/ontology/verbs.js.map +1 -1
  57. package/dist/src/capabilities/prompt/verbs.js +5 -4
  58. package/dist/src/capabilities/prompt/verbs.js.map +1 -1
  59. package/dist/src/capabilities/resources/provider.js +6 -3
  60. package/dist/src/capabilities/resources/provider.js.map +1 -1
  61. package/dist/src/capabilities/setup/setup.verb.js +13 -5
  62. package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
  63. package/dist/src/capabilities/shared/calls.js +16 -0
  64. package/dist/src/capabilities/shared/calls.js.map +1 -0
  65. package/dist/src/capabilities/skill/render.js +7 -5
  66. package/dist/src/capabilities/skill/render.js.map +1 -1
  67. package/dist/src/capabilities/skill/verbs.js +5 -4
  68. package/dist/src/capabilities/skill/verbs.js.map +1 -1
  69. package/dist/src/capabilities/sources/collectStatus.js +6 -1
  70. package/dist/src/capabilities/sources/collectStatus.js.map +1 -1
  71. package/dist/src/capabilities/sources/index.js +4 -3
  72. package/dist/src/capabilities/sources/index.js.map +1 -1
  73. package/dist/src/capabilities/sources/reset.render.js +37 -0
  74. package/dist/src/capabilities/sources/reset.render.js.map +1 -0
  75. package/dist/src/capabilities/sources/reset.verb.js +51 -0
  76. package/dist/src/capabilities/sources/reset.verb.js.map +1 -0
  77. package/dist/src/capabilities/sources/runReset.js +59 -0
  78. package/dist/src/capabilities/sources/runReset.js.map +1 -0
  79. package/dist/src/capabilities/sources/runUpdate.js +7 -6
  80. package/dist/src/capabilities/sources/runUpdate.js.map +1 -1
  81. package/dist/src/capabilities/sources/status.render.js +24 -8
  82. package/dist/src/capabilities/sources/status.render.js.map +1 -1
  83. package/dist/src/capabilities/sources/status.verb.js +1 -0
  84. package/dist/src/capabilities/sources/status.verb.js.map +1 -1
  85. package/dist/src/capabilities/sources/update.verb.js +2 -0
  86. package/dist/src/capabilities/sources/update.verb.js.map +1 -1
  87. package/dist/src/capabilities/upgrade/upgrade.verb.js +1 -0
  88. package/dist/src/capabilities/upgrade/upgrade.verb.js.map +1 -1
  89. package/dist/src/capabilities/version/version.verb.js +1 -0
  90. package/dist/src/capabilities/version/version.verb.js.map +1 -1
  91. package/dist/src/constants.js +4 -3
  92. package/dist/src/constants.js.map +1 -1
  93. package/dist/src/kernel/error/index.js +1 -1
  94. package/dist/src/kernel/error/index.js.map +1 -1
  95. package/dist/src/kernel/error/recovery.js +24 -42
  96. package/dist/src/kernel/error/recovery.js.map +1 -1
  97. package/dist/src/kernel/packs/collect.js +123 -9
  98. package/dist/src/kernel/packs/collect.js.map +1 -1
  99. package/dist/src/kernel/packs/compile.js +74 -15
  100. package/dist/src/kernel/packs/compile.js.map +1 -1
  101. package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js +3 -3
  102. package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js.map +1 -1
  103. package/dist/src/kernel/packs/iri.js +2 -4
  104. package/dist/src/kernel/packs/iri.js.map +1 -1
  105. package/dist/src/kernel/packs/renderPack.js +90 -50
  106. package/dist/src/kernel/packs/renderPack.js.map +1 -1
  107. package/dist/src/kernel/packs/resolveEntity.js +202 -90
  108. package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
  109. package/dist/src/kernel/packs/runBodies.js +89 -30
  110. package/dist/src/kernel/packs/runBodies.js.map +1 -1
  111. package/dist/src/kernel/packs/schema.js +66 -12
  112. package/dist/src/kernel/packs/schema.js.map +1 -1
  113. package/dist/src/kernel/packs/sparql/buildListQuery.js +80 -13
  114. package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -1
  115. package/dist/src/kernel/packs/sparql/buildLookupQuery.js +41 -13
  116. package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
  117. package/dist/src/kernel/packs/sparql/filterValues.js +32 -23
  118. package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -1
  119. package/dist/src/kernel/packs/sparql/runSelect.js +3 -5
  120. package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
  121. package/dist/src/kernel/packs/storyRules.js +31 -4
  122. package/dist/src/kernel/packs/storyRules.js.map +1 -1
  123. package/dist/src/kernel/packs/tierScope.js +3 -3
  124. package/dist/src/kernel/packs/tierScope.js.map +1 -1
  125. package/dist/src/kernel/packs/types.js +4 -0
  126. package/dist/src/kernel/packs/types.js.map +1 -1
  127. package/dist/src/kernel/project/cli/buildProgram.js +4 -0
  128. package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
  129. package/dist/src/kernel/project/cli/dispatch.js +32 -8
  130. package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
  131. package/dist/src/kernel/project/cli/suggestNames.js +44 -1
  132. package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
  133. package/dist/src/kernel/project/cli/verbHelp.js +17 -18
  134. package/dist/src/kernel/project/cli/verbHelp.js.map +1 -1
  135. package/dist/src/kernel/project/mcp/buildServer.js +11 -4
  136. package/dist/src/kernel/project/mcp/buildServer.js.map +1 -1
  137. package/dist/src/kernel/project/mcp/envelope.js +3 -2
  138. package/dist/src/kernel/project/mcp/envelope.js.map +1 -1
  139. package/dist/src/kernel/project/mcp/instructions.js +101 -31
  140. package/dist/src/kernel/project/mcp/instructions.js.map +1 -1
  141. package/dist/src/kernel/project/mcp/registerVerb.js +59 -23
  142. package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
  143. package/dist/src/kernel/render/renderers.js +3 -3
  144. package/dist/src/kernel/render/turtle.js +21 -4
  145. package/dist/src/kernel/render/turtle.js.map +1 -1
  146. package/dist/src/kernel/runtime/graphpack/build.js +54 -1
  147. package/dist/src/kernel/runtime/graphpack/build.js.map +1 -1
  148. package/dist/src/kernel/runtime/graphpack/manifest.js +14 -0
  149. package/dist/src/kernel/runtime/graphpack/manifest.js.map +1 -1
  150. package/dist/src/kernel/runtime/graphpack/read.js +3 -5
  151. package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
  152. package/dist/src/kernel/runtime/graphpack/schemas.js +1 -0
  153. package/dist/src/kernel/runtime/graphpack/schemas.js.map +1 -1
  154. package/dist/src/kernel/runtime/loadSession.js +8 -1
  155. package/dist/src/kernel/runtime/loadSession.js.map +1 -1
  156. package/dist/src/kernel/runtime/packVersion.js +75 -0
  157. package/dist/src/kernel/runtime/packVersion.js.map +1 -0
  158. package/dist/src/kernel/runtime/readEntity.js +43 -4
  159. package/dist/src/kernel/runtime/readEntity.js.map +1 -1
  160. package/dist/src/kernel/runtime/resolveSources.js +61 -9
  161. package/dist/src/kernel/runtime/resolveSources.js.map +1 -1
  162. package/dist/src/kernel/runtime/storeReadiness.js +3 -2
  163. package/dist/src/kernel/runtime/storeReadiness.js.map +1 -1
  164. package/dist/src/kernel/spec/call.js +167 -0
  165. package/dist/src/kernel/spec/call.js.map +1 -0
  166. package/dist/src/kernel/spec/emitReference.js +9 -13
  167. package/dist/src/kernel/spec/emitReference.js.map +1 -1
  168. package/dist/src/kernel/spec/emitSurface.js +8 -1
  169. package/dist/src/kernel/spec/emitSurface.js.map +1 -1
  170. package/dist/src/kernel/spec/guidance.js +63 -0
  171. package/dist/src/kernel/spec/guidance.js.map +1 -0
  172. package/dist/src/kernel/spec/wireType.js +36 -0
  173. package/dist/src/kernel/spec/wireType.js.map +1 -0
  174. package/package.json +14 -14
  175. package/pragma.conf.ts +294 -177
  176. package/src/capabilities/block.parity.test.ts +1 -1
  177. package/src/capabilities/callRule.test.ts +147 -0
  178. package/src/capabilities/capabilities/capabilities.test.ts +47 -19
  179. package/src/capabilities/capabilities/capabilities.verb.ts +2 -0
  180. package/src/capabilities/capabilities/catalog.ts +60 -55
  181. package/src/capabilities/capabilities/index.ts +2 -0
  182. package/src/capabilities/capabilities/types.ts +16 -19
  183. package/src/capabilities/colophon/colophon.render.ts +9 -5
  184. package/src/capabilities/colophon/colophon.verb.ts +1 -0
  185. package/src/capabilities/config/get.verb.ts +2 -0
  186. package/src/capabilities/config/runField.ts +3 -3
  187. package/src/capabilities/config/set.verb.ts +3 -0
  188. package/src/capabilities/config/show.verb.ts +2 -0
  189. package/src/capabilities/config/unset.verb.ts +2 -0
  190. package/src/capabilities/create/constants.ts +2 -2
  191. package/src/capabilities/create/create.verb.ts +16 -0
  192. package/src/capabilities/create/createGrammar.test.ts +1 -1
  193. package/src/capabilities/distribution.test.ts +6 -3
  194. package/src/capabilities/distribution.ts +6 -0
  195. package/src/capabilities/doctor/checks/checkPackageRefs.ts +14 -2
  196. package/src/capabilities/doctor/doctor.test.ts +38 -1
  197. package/src/capabilities/doctor/doctor.verb.ts +2 -0
  198. package/src/capabilities/emptyRecovery.test.ts +5 -0
  199. package/src/capabilities/graph/connect.verb.ts +2 -0
  200. package/src/capabilities/graph/inspect.render.ts +9 -1
  201. package/src/capabilities/graph/inspect.test.ts +73 -0
  202. package/src/capabilities/graph/inspect.verb.ts +2 -0
  203. package/src/capabilities/graph/query.render.test.ts +35 -0
  204. package/src/capabilities/graph/query.render.ts +45 -7
  205. package/src/capabilities/graph/query.shipped.exec.test.ts +44 -0
  206. package/src/capabilities/graph/query.verb.ts +2 -0
  207. package/src/capabilities/graph/queryText.test.ts +55 -1
  208. package/src/capabilities/graph/queryText.ts +47 -0
  209. package/src/capabilities/graph/runConnect.ts +4 -5
  210. package/src/capabilities/graph/runQuery.ts +23 -9
  211. package/src/capabilities/info/info.verb.ts +2 -0
  212. package/src/capabilities/links.shipped.exec.test.ts +398 -0
  213. package/src/capabilities/listBudget.shipped.exec.test.ts +2 -2
  214. package/src/capabilities/listLookup.shipped.exec.test.ts +122 -13
  215. package/src/capabilities/listQuery.shipped.exec.test.ts +39 -16
  216. package/src/capabilities/lookupBudget.shipped.exec.test.ts +208 -0
  217. package/src/capabilities/meta/mcp.verb.ts +2 -0
  218. package/src/capabilities/ontology/ontology.test.ts +24 -0
  219. package/src/capabilities/ontology/verbs.ts +16 -12
  220. package/src/capabilities/prompt/verbs.ts +10 -4
  221. package/src/capabilities/resources/provider.ts +7 -3
  222. package/src/capabilities/resources/resources.test.ts +2 -1
  223. package/src/capabilities/setup/setup.verb.ts +16 -0
  224. package/src/capabilities/shared/calls.ts +20 -0
  225. package/src/capabilities/skill/render.ts +9 -6
  226. package/src/capabilities/skill/verbs.ts +8 -4
  227. package/src/capabilities/sources/collectStatus.ts +6 -1
  228. package/src/capabilities/sources/index.ts +4 -3
  229. package/src/capabilities/sources/reset.render.test.ts +33 -0
  230. package/src/capabilities/sources/reset.render.ts +43 -0
  231. package/src/capabilities/sources/reset.verb.ts +59 -0
  232. package/src/capabilities/sources/runReset.ts +65 -0
  233. package/src/capabilities/sources/runUpdate.ts +12 -11
  234. package/src/capabilities/sources/sources.test.ts +158 -3
  235. package/src/capabilities/sources/status.render.test.ts +63 -1
  236. package/src/capabilities/sources/status.render.ts +25 -8
  237. package/src/capabilities/sources/status.verb.ts +2 -0
  238. package/src/capabilities/sources/types.ts +26 -0
  239. package/src/capabilities/sources/update.verb.ts +3 -0
  240. package/src/capabilities/surface.test.ts +2 -2
  241. package/src/capabilities/token.parity.test.ts +3 -2
  242. package/src/capabilities/tokenGraph.shipped.exec.test.ts +14 -2
  243. package/src/capabilities/upgrade/upgrade.verb.ts +1 -0
  244. package/src/capabilities/variable.parity.test.ts +2 -1
  245. package/src/capabilities/version/version.verb.ts +1 -0
  246. package/src/capabilities/wireContract.test.ts +110 -0
  247. package/src/constants.ts +4 -3
  248. package/src/kernel/copy.test.ts +1 -1
  249. package/src/kernel/error/PragmaError.test.ts +7 -3
  250. package/src/kernel/error/index.ts +1 -1
  251. package/src/kernel/error/recovery.test.ts +52 -18
  252. package/src/kernel/error/recovery.ts +25 -46
  253. package/src/kernel/error/types.ts +1 -1
  254. package/src/kernel/packs/collect.test.ts +79 -0
  255. package/src/kernel/packs/collect.ts +151 -11
  256. package/src/kernel/packs/compile.test.ts +107 -10
  257. package/src/kernel/packs/compile.ts +100 -11
  258. package/src/kernel/packs/filteredEmpty.test.ts +22 -5
  259. package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +5 -6
  260. package/src/kernel/packs/graphqlSource.test.ts +42 -0
  261. package/src/kernel/packs/iri.ts +5 -4
  262. package/src/kernel/packs/listNotice.test.ts +1 -1
  263. package/src/kernel/packs/nounLink.test.ts +385 -0
  264. package/src/kernel/packs/renderPack.ts +137 -57
  265. package/src/kernel/packs/resolveEntity.test.ts +170 -1
  266. package/src/kernel/packs/resolveEntity.ts +281 -101
  267. package/src/kernel/packs/runBodies.ts +133 -31
  268. package/src/kernel/packs/schema.ts +77 -12
  269. package/src/kernel/packs/sparql/buildListQuery.test.ts +78 -1
  270. package/src/kernel/packs/sparql/buildListQuery.ts +106 -16
  271. package/src/kernel/packs/sparql/buildLookupQuery.ts +44 -13
  272. package/src/kernel/packs/sparql/filterValues.test.ts +36 -4
  273. package/src/kernel/packs/sparql/filterValues.ts +50 -31
  274. package/src/kernel/packs/sparql/runSelect.ts +4 -6
  275. package/src/kernel/packs/storyRules.ts +37 -4
  276. package/src/kernel/packs/tierScope.test.ts +120 -6
  277. package/src/kernel/packs/tierScope.ts +5 -7
  278. package/src/kernel/packs/toolDescription.test.ts +59 -74
  279. package/src/kernel/packs/types.ts +93 -11
  280. package/src/kernel/project/cli/buildProgram.ts +4 -0
  281. package/src/kernel/project/cli/dispatch.ts +34 -8
  282. package/src/kernel/project/cli/suggest.test.ts +77 -0
  283. package/src/kernel/project/cli/suggestNames.ts +47 -1
  284. package/src/kernel/project/cli/verbHelp.ts +16 -19
  285. package/src/kernel/project/mcp/buildServer.ts +15 -4
  286. package/src/kernel/project/mcp/envelope.ts +3 -2
  287. package/src/kernel/project/mcp/instructions.ts +123 -35
  288. package/src/kernel/project/mcp/prompts/prompts.test.ts +136 -20
  289. package/src/kernel/project/mcp/registerVerb.test.ts +28 -0
  290. package/src/kernel/project/mcp/registerVerb.ts +67 -29
  291. package/src/kernel/render/__snapshots__/renderers.test.ts.snap +1 -1
  292. package/src/kernel/render/renderers.test.ts +2 -2
  293. package/src/kernel/render/renderers.ts +3 -3
  294. package/src/kernel/render/turtle.ts +24 -4
  295. package/src/kernel/runtime/graphpack/build.ts +58 -1
  296. package/src/kernel/runtime/graphpack/graphpack.test.ts +20 -0
  297. package/src/kernel/runtime/graphpack/manifest.ts +15 -0
  298. package/src/kernel/runtime/graphpack/read.ts +4 -6
  299. package/src/kernel/runtime/graphpack/schemas.ts +1 -0
  300. package/src/kernel/runtime/graphpack/types.ts +13 -0
  301. package/src/kernel/runtime/loadSession.ts +8 -1
  302. package/src/kernel/runtime/packVersion.test.ts +61 -0
  303. package/src/kernel/runtime/packVersion.ts +84 -0
  304. package/src/kernel/runtime/readEntity.ts +61 -6
  305. package/src/kernel/runtime/resolveSources.test.ts +90 -7
  306. package/src/kernel/runtime/resolveSources.ts +91 -10
  307. package/src/kernel/runtime/storeReadiness.ts +4 -4
  308. package/src/kernel/runtime/types.ts +12 -0
  309. package/src/kernel/spec/call.test.ts +95 -0
  310. package/src/kernel/spec/call.ts +186 -0
  311. package/src/kernel/spec/emitReference.ts +9 -13
  312. package/src/kernel/spec/emitSurface.ts +9 -1
  313. package/src/kernel/spec/guidance.test.ts +49 -0
  314. package/src/kernel/spec/guidance.ts +68 -0
  315. package/src/kernel/spec/index.ts +4 -0
  316. package/src/kernel/spec/surfaceConformance.test.ts +2 -2
  317. package/src/kernel/spec/types.ts +64 -7
  318. package/src/kernel/spec/wireType.ts +53 -0
  319. package/src/testing/behavioral/errorMatrix.mcp.test.ts +2 -1
  320. package/src/testing/behavioral/journeys.firstInstall.test.ts +72 -2
  321. package/src/testing/behavioral/parity.test.ts +40 -0
  322. package/src/testing/eval/__snapshots__/eval.test.ts.snap +1 -1
  323. package/src/testing/eval/cases/assembly.ts +4 -3
  324. package/src/testing/eval/cases/stable.ts +2 -3
  325. package/src/testing/helpers/callSchema.ts +40 -0
  326. package/src/testing/helpers/parity.ts +35 -2
  327. package/src/testing/setupCallChecking.ts +30 -0
  328. package/dist/src/capabilities/capabilities/hints.js +0 -223
  329. package/dist/src/capabilities/capabilities/hints.js.map +0 -1
  330. package/src/capabilities/capabilities/hints.ts +0 -266
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { BIN_NAME } from "../../constants.js";
16
- import { cliRecovery, PragmaError } from "../../kernel/error/index.js";
16
+ import { callRecovery, PragmaError } from "../../kernel/error/index.js";
17
17
  import { VOCABULARY } from "../../kernel/index.js";
18
18
  import type { PragmaRuntime } from "../../kernel/runtime/index.js";
19
19
  import { asVerb } from "../../kernel/spec/asVerb.js";
@@ -37,6 +37,8 @@ const listVerb: VerbSpec<Record<string, unknown>, PromptListData> = {
37
37
  path: ["prompt", "list"],
38
38
  summary: "List the workflow prompt templates the design system offers.",
39
39
  doc: `Browse the prompt entities the active graph declares (${VOCABULARY.prompt.type} in this distribution) — name, description, and argument names. This distribution's graph carries none today. The same prompts are offered natively over MCP prompts/list; use prompt_lookup for the full template body.`,
40
+ useWhen:
41
+ "when asked which ready-made workflow prompts the design system offers",
40
42
  params: [],
41
43
  output: { formatters: promptListFormatters },
42
44
  examples: [{ cmd: `${BIN_NAME} prompt list` }],
@@ -58,6 +60,9 @@ const lookupVerb: VerbSpec<Record<string, unknown>, PromptLookupData> = {
58
60
  path: ["prompt", "lookup"],
59
61
  summary: "Show one workflow prompt template's body and arguments by name.",
60
62
  doc: "Fetch a single prompt entity's full template body (with {{arg}} placeholders) and its declared arguments. A prompt is addressed by its label; prompt_list names the ones the active graph carries.",
63
+ useWhen:
64
+ "when asked to read or run one workflow prompt by the name prompt_list gave",
65
+ example: { name: "build-a-block" },
61
66
  params: [
62
67
  {
63
68
  kind: "string",
@@ -91,9 +96,10 @@ const lookupVerb: VerbSpec<Record<string, unknown>, PromptLookupData> = {
91
96
  const available = await m.readPrompts(rt);
92
97
  throw PragmaError.notFound("prompt", name, {
93
98
  suggestions: available.map((prompt) => prompt.name),
94
- recovery: cliRecovery("prompt list", "List available prompts.", {
95
- tool: "prompt_list",
96
- }),
99
+ recovery: callRecovery(
100
+ { verb: "prompt list" },
101
+ "List available prompts.",
102
+ ),
97
103
  });
98
104
  }
99
105
  return entry;
@@ -46,12 +46,14 @@ import type {
46
46
  } from "../../kernel/runtime/graphpack/types.js";
47
47
  import { readEntity } from "../../kernel/runtime/readEntity.js";
48
48
  import { resolveSources } from "../../kernel/runtime/resolveSources.js";
49
+ import { renderNextStep } from "../../kernel/spec/call.js";
49
50
  import type {
50
51
  CapabilityModule,
51
52
  McpListable,
52
53
  McpListableRef,
53
54
  McpResourceProvider,
54
55
  } from "../../kernel/spec/types.js";
56
+ import { BUILD_STORE_CALL } from "../shared/calls.js";
55
57
 
56
58
  /**
57
59
  * The weight an unweighted slice carries — "as important as any other".
@@ -181,7 +183,9 @@ function listEntity(
181
183
  }
182
184
 
183
185
  /** The recovery entry a missing/legacy index degrades to (and its read body). */
184
- const SOURCES_RECOVERY = `No enriched entity index. Run \`${BIN_NAME} sources update\` to build it.`;
186
+ // This surface is MCP-only, so the next step is always spelled as a tool call.
187
+ const describeNoIndex = (): string =>
188
+ `No enriched entity index: the store needs building. ${renderNextStep(BUILD_STORE_CALL, "mcp")}`;
185
189
 
186
190
  /** The single entry a server with no usable index advertises. */
187
191
  function sourcesEntry(): ListedResource {
@@ -189,7 +193,7 @@ function sourcesEntry(): ListedResource {
189
193
  uri: SOURCES_URI,
190
194
  name: SOURCES_VARIABLE,
191
195
  title: "Store not indexed",
192
- description: SOURCES_RECOVERY,
196
+ description: describeNoIndex(),
193
197
  mimeType: RECOVERY_MIME_TYPE,
194
198
  };
195
199
  }
@@ -491,7 +495,7 @@ export const resourceProvider: McpResourceProvider = {
491
495
  {
492
496
  uri: url.href,
493
497
  mimeType: RECOVERY_MIME_TYPE,
494
- text: SOURCES_RECOVERY,
498
+ text: describeNoIndex(),
495
499
  },
496
500
  ],
497
501
  };
@@ -511,7 +511,8 @@ describe("resource read — cold-store failure surfaces isError + recovery (D3)"
511
511
  const listed = await harness.listResources();
512
512
  expect(listed.map((r) => r.uri)).toEqual(["pragma:sources"]);
513
513
  const read = await harness.readResource("pragma:sources");
514
- expect(read.text).toMatch(/sources update/);
514
+ // MCP-only surface: the next step is a tool call, and never confirms.
515
+ expect(read.text).toContain("Call `sources_update {}`.");
515
516
  });
516
517
  });
517
518
 
@@ -455,6 +455,9 @@ const setupAllVerb = setupVerb(
455
455
  "all",
456
456
  SELF_CAPABILITY,
457
457
  {
458
+ useWhen:
459
+ "when asked to install or repair the tool's integration: the config file, shell completions, MCP registration, skills and the editor extension",
460
+ example: { scope: "project" },
458
461
  doc: "Shows what each target needs, then applies the ones you keep. Everything is configured in your home directory by default; the scope option moves the run to this project alone, or covers both. Without an attended terminal the plan is printed and nothing is written unless the run is explicitly confirmed.",
459
462
  examples: [
460
463
  { cmd: `${BIN_NAME} setup` },
@@ -479,6 +482,7 @@ const configVerb = setupVerb(
479
482
  "Create your global config file, filled in with the defaults.",
480
483
  "config",
481
484
  SUB_CAPABILITY,
485
+ { useWhen: "when asked to create only the global config file" },
482
486
  );
483
487
 
484
488
  const mcpVerb = setupVerb(
@@ -486,6 +490,10 @@ const mcpVerb = setupVerb(
486
490
  `Register the ${BIN_NAME} MCP server with the AI harnesses on this machine.`,
487
491
  "mcp",
488
492
  SUB_CAPABILITY,
493
+ {
494
+ useWhen:
495
+ "when asked to connect only the MCP server to the AI tools on this machine",
496
+ },
489
497
  );
490
498
 
491
499
  const completionsVerb = setupVerb(
@@ -493,6 +501,7 @@ const completionsVerb = setupVerb(
493
501
  "Install TAB completion for the shell you are running.",
494
502
  "completions",
495
503
  SUB_CAPABILITY,
504
+ { useWhen: "when asked to install only TAB completion for the shell" },
496
505
  );
497
506
 
498
507
  const skillsVerb = setupVerb(
@@ -500,6 +509,10 @@ const skillsVerb = setupVerb(
500
509
  "Link the skills you have installed into every AI harness that reads them.",
501
510
  "skills",
502
511
  SUB_CAPABILITY,
512
+ {
513
+ useWhen:
514
+ "when asked to make only the installed skills visible to the AI tools on this machine",
515
+ },
503
516
  );
504
517
 
505
518
  const lspVerb = setupVerb(
@@ -507,6 +520,9 @@ const lspVerb = setupVerb(
507
520
  "Install the Terrazzo design-token extension into the VS Code-family editors on this machine (on PATH, under /Applications or ~/Applications, or by its user directory).",
508
521
  "lsp",
509
522
  SUB_CAPABILITY,
523
+ {
524
+ useWhen: "when asked to install only the design-token editor extension",
525
+ },
510
526
  );
511
527
 
512
528
  /** The `setup` capability module (run-all self-verb + five CLI-only sub-verbs). */
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The calls more than one capability's dead end points at, so
3
+ * `callRule.test.ts` can hold each to its verb. "Build the store" is the
4
+ * kernel's own constant (`kernel/spec/call.ts#BUILD_STORE_CALL`), re-exported
5
+ * here so capabilities and kernel make the same call.
6
+ */
7
+
8
+ import { BUILD_STORE_CALL } from "../../kernel/spec/call.js";
9
+ import type { Call } from "../../kernel/spec/index.js";
10
+
11
+ export { BUILD_STORE_CALL };
12
+
13
+ /** Link installed skills into the AI harnesses — CLI-only, so it is always spelled as a command. */
14
+ export const LINK_SKILLS_CALL: Call = { verb: "setup skills" };
15
+
16
+ /** Re-run the build showing each file as it parses. `--verbose` is a global CLI flag, so only the command carries it. */
17
+ export const VERBOSE_BUILD_CALL: Call = {
18
+ ...BUILD_STORE_CALL,
19
+ cliFlags: ["--verbose"],
20
+ };
@@ -2,14 +2,16 @@
2
2
  * Formatters for `skill list` and `skill lookup`.
3
3
  */
4
4
 
5
- import { BIN_NAME } from "../../constants.js";
6
- import type { Formatters } from "../../kernel/spec/index.js";
5
+ import { renderNextStep } from "../../kernel/spec/call.js";
6
+ import type { Formatters, Surface } from "../../kernel/spec/index.js";
7
+ import { BUILD_STORE_CALL, LINK_SKILLS_CALL } from "../shared/calls.js";
7
8
  import type { DiscoveredSkill } from "./discover.js";
8
9
  import type { SkillLookup } from "./verbs.js";
9
10
 
10
11
  /** Empty-state guidance (U5) — where skills come from now that packs ship them. */
11
- const EMPTY_PLAIN = `No skills found.\nSkills come from design-system packs — add one to your config's packs, run \`${BIN_NAME} sources update\`, then \`${BIN_NAME} setup skills\`.`;
12
- const EMPTY_LLM = `## Skills (0)\n\nNo skills found. Skills come from design-system packs — add one to the project config's packs, run \`${BIN_NAME} sources update\`, then \`${BIN_NAME} setup skills\`.`;
12
+ function describeEmpty(surface: Surface): string {
13
+ return `No skills found.\nSkills come from design-system packs — add one to the project config's packs, build the store, then link the skills. ${renderNextStep(BUILD_STORE_CALL, surface)} ${renderNextStep(LINK_SKILLS_CALL, surface)}`;
14
+ }
13
15
 
14
16
  export const skillListFormatters: Formatters<DiscoveredSkill[]> = {
15
17
  // Zero skills: plain stdout stays empty — the guidance is `notice`,
@@ -21,10 +23,11 @@ export const skillListFormatters: Formatters<DiscoveredSkill[]> = {
21
23
  `${s.name}${s.frontmatter.prompt ? " (prompt)" : ""} ${s.description}`,
22
24
  )
23
25
  .join("\n"),
24
- notice: (skills) => (skills.length === 0 ? EMPTY_PLAIN : undefined),
26
+ notice: (skills, surface = "cli") =>
27
+ skills.length === 0 ? describeEmpty(surface) : undefined,
25
28
  llm: (skills) =>
26
29
  skills.length === 0
27
- ? EMPTY_LLM
30
+ ? `## Skills (0)\n\n${describeEmpty("cli")}`
28
31
  : [
29
32
  `## Skills (${skills.length})`,
30
33
  "",
@@ -9,7 +9,7 @@
9
9
  import { readFileSync } from "node:fs";
10
10
  import { join } from "node:path";
11
11
  import { BIN_NAME } from "../../constants.js";
12
- import { cliRecovery, PragmaError } from "../../kernel/error/index.js";
12
+ import { callRecovery, PragmaError } from "../../kernel/error/index.js";
13
13
  import { suggestNames } from "../../kernel/project/cli/suggestNames.js";
14
14
  import type { PragmaRuntime } from "../../kernel/runtime/index.js";
15
15
  import { asVerb } from "../../kernel/spec/asVerb.js";
@@ -25,6 +25,7 @@ export interface SkillLookup extends DiscoveredSkill {
25
25
  const listVerb: VerbSpec<Record<string, unknown>, DiscoveredSkill[]> = {
26
26
  path: ["skill", "list"],
27
27
  summary: "List discovered skills (SKILL.md files under the skill roots).",
28
+ useWhen: "when asked which agent skills (guided workflows) are available",
28
29
  params: [],
29
30
  output: { formatters: skillListFormatters },
30
31
  examples: [{ cmd: `${BIN_NAME} skill list` }],
@@ -43,6 +44,8 @@ const listVerb: VerbSpec<Record<string, unknown>, DiscoveredSkill[]> = {
43
44
  const lookupVerb: VerbSpec<Record<string, unknown>, SkillLookup> = {
44
45
  path: ["skill", "lookup"],
45
46
  summary: "Show a skill's metadata and instructions by name.",
47
+ useWhen: "when asked to follow one skill",
48
+ example: { name: "specify-component" },
46
49
  params: [
47
50
  {
48
51
  kind: "string",
@@ -75,9 +78,10 @@ const lookupVerb: VerbSpec<Record<string, unknown>, SkillLookup> = {
75
78
  name,
76
79
  skills.map((skill) => skill.name),
77
80
  ),
78
- recovery: cliRecovery("skill list", "List discovered skills.", {
79
- tool: "skill_list",
80
- }),
81
+ recovery: callRecovery(
82
+ { verb: "skill list" },
83
+ "List discovered skills.",
84
+ ),
81
85
  });
82
86
  }
83
87
  return { ...match, instructions: readInstructions(match.sourcePath) };
@@ -72,7 +72,7 @@ export async function collectStatus(
72
72
  ref: entrySource(entry),
73
73
  }));
74
74
  const decision = resolveSources(layers, runtime.cwd);
75
- const base = { cwd: runtime.cwd, sources };
75
+ const base = { cwd: runtime.cwd, sources, ignoredPack: null };
76
76
 
77
77
  switch (decision.kind) {
78
78
  case "embedded": {
@@ -84,6 +84,11 @@ export async function collectStatus(
84
84
  sourceRef: manifest.sourceRef,
85
85
  builtAt: manifest.createdAt,
86
86
  entityCount: manifest.entityCount ?? null,
87
+ // The upgrade row: this project HAS a pack, built by an older CLI, and
88
+ // the snapshot is answering in its place. Reported straight off the
89
+ // decision — status never re-derives which pack answers, and it must
90
+ // not re-derive which one was passed over either.
91
+ ignoredPack: decision.ignoredPack ?? null,
87
92
  };
88
93
  }
89
94
  case "pack": {
@@ -1,15 +1,16 @@
1
1
  /**
2
- * The `sources` capability barrel — `status` (storeless read) and `update`
3
- * (the resolve/build/point Task).
2
+ * The `sources` capability barrel — `status` (storeless read), `update` (the
3
+ * resolve/build/point Task), and `reset` (drop the pointer update wrote).
4
4
  */
5
5
 
6
6
  import { asVerb } from "../../kernel/spec/asVerb.js";
7
7
  import type { CapabilityModule } from "../../kernel/spec/index.js";
8
+ import { resetVerb } from "./reset.verb.js";
8
9
  import { statusVerb } from "./status.verb.js";
9
10
  import { updateVerb } from "./update.verb.js";
10
11
 
11
12
  /** The `sources` capability module. */
12
13
  export const sourcesModule: CapabilityModule = {
13
14
  name: "sources",
14
- verbs: [asVerb(statusVerb), asVerb(updateVerb)],
15
+ verbs: [asVerb(statusVerb), asVerb(updateVerb), asVerb(resetVerb)],
15
16
  };
@@ -0,0 +1,33 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { resetFormatters } from "./reset.render.js";
3
+
4
+ const REMOVED = {
5
+ removed: true,
6
+ contentHash: "0e82d35c66687b8a",
7
+ answers: "embedded",
8
+ } as const;
9
+
10
+ describe("sources reset formatters", () => {
11
+ it("llm states what was removed and what answers now", () => {
12
+ expect(resetFormatters.llm(REMOVED)).toBe(
13
+ "# sources reset\n- Removed: 0e82d35c66687b8a\n- Answers: embedded",
14
+ );
15
+ expect(
16
+ resetFormatters.llm({
17
+ removed: false,
18
+ contentHash: null,
19
+ answers: "embedded",
20
+ }),
21
+ ).toContain("- Removed: nothing was built");
22
+ });
23
+
24
+ it("plain tells a project with its own packs that reads need an update", () => {
25
+ const out = resetFormatters.plain({ ...REMOVED, answers: "unavailable" });
26
+ expect(out).toContain(
27
+ "Removed this project's pack pointer (was 0e82d35c6668).",
28
+ );
29
+ expect(out).toContain(
30
+ "reads need `pragma sources update` before they can answer",
31
+ );
32
+ });
33
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Formatters for `pragma sources reset` — plain, llm, json.
3
+ *
4
+ * Two outcomes, and the difference matters to a reader: a pointer was removed,
5
+ * or there was none to remove. Neither is an error, so both are rendered as the
6
+ * calm statement they are — and each says what answers reads NOW, because that
7
+ * is the question a reset is asked in service of.
8
+ */
9
+
10
+ import { BIN_NAME } from "../../constants.js";
11
+ import type { Formatters } from "../../kernel/spec/index.js";
12
+ import type { SourcesResetData } from "./types.js";
13
+
14
+ /** What answers this project's reads after the reset, as a sentence. */
15
+ function nowAnswering(data: SourcesResetData): string {
16
+ return data.answers === "embedded"
17
+ ? `The snapshot shipped with the CLI answers reads; run \`${BIN_NAME} sources update\` to build from your configured packs again.`
18
+ : `This project declares its own packs, so reads need \`${BIN_NAME} sources update\` before they can answer.`;
19
+ }
20
+
21
+ export const resetFormatters: Formatters<SourcesResetData> = {
22
+ plain(data) {
23
+ if (!data.removed) {
24
+ return `No pack is built for this project — nothing to reset. ${nowAnswering(data)}`;
25
+ }
26
+ return [
27
+ `Removed this project's pack pointer (was ${(data.contentHash ?? "").slice(0, 12)}).`,
28
+ nowAnswering(data),
29
+ ].join("\n");
30
+ },
31
+
32
+ llm(data) {
33
+ return [
34
+ `# sources reset`,
35
+ `- Removed: ${data.removed ? (data.contentHash ?? "") : "nothing was built"}`,
36
+ `- Answers: ${data.answers}`,
37
+ ].join("\n");
38
+ },
39
+
40
+ json(data) {
41
+ return JSON.stringify(data);
42
+ },
43
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The `sources reset` verb — drop this project's built pack.
3
+ *
4
+ * A mutation (`mutates: true`) that needs neither the network nor the store:
5
+ * like `sources update` it must not boot the store first (a project whose pack
6
+ * it is about to unpoint may not have a bootable one at all), and unlike update
7
+ * it never leaves the machine. Plan-first comes from the projectors, exactly as
8
+ * it does for update — `--dry-run` previews on the CLI, and
9
+ * over MCP a call without `confirm` returns the plan and writes nothing.
10
+ *
11
+ * `destructive: true`: it removes state a user built on purpose. It deletes
12
+ * no graph data and `sources update` brings the pack back from the cache, but
13
+ * the annotation is what tells an agent's host to ask first, and "your project
14
+ * stops reading the pack it was reading" deserves the ask.
15
+ */
16
+
17
+ import type { Task } from "@canonical/task";
18
+ import { BIN_NAME } from "../../constants.js";
19
+ import type { VerbSpec } from "../../kernel/spec/index.js";
20
+ import { resetFormatters } from "./reset.render.js";
21
+ import type { SourcesResetData } from "./types.js";
22
+
23
+ /** The `sources reset` verb spec. */
24
+ export const resetVerb: VerbSpec<Record<string, unknown>, SourcesResetData> = {
25
+ path: ["sources", "reset"],
26
+ summary: "Remove this project's built pack.",
27
+ doc: "Deletes the pointer that names the pack this project reads, so reads answer from the snapshot shipped with the CLI again; a project that declares its own packs cannot answer reads until the next `sources update`. The cached pack files are left alone — they are shared with any other project built from the same sources, and a later update reuses them. Reports calmly when nothing is built.",
28
+ useWhen:
29
+ "to discard locally built data and return to the data shipped with the tool",
30
+ params: [],
31
+ output: { formatters: resetFormatters },
32
+ examples: [
33
+ {
34
+ cmd: `${BIN_NAME} sources reset`,
35
+ note: "drop the built pack and read the shipped snapshot",
36
+ },
37
+ {
38
+ cmd: `${BIN_NAME} sources reset --dry-run`,
39
+ note: "show what would be removed",
40
+ },
41
+ ],
42
+ capability: {
43
+ needsStore: false,
44
+ mutates: true,
45
+ needsNetwork: false,
46
+ destructive: true,
47
+ mcp: {
48
+ expose: true,
49
+ annotations: { readOnlyHint: false, openWorldHint: false },
50
+ },
51
+ },
52
+ // `run` really returns `Promise<Task<R>>` — the body reads config and the
53
+ // pointer before its effects are known — presented through the `Task<R>` arm
54
+ // by the same honest cast `sources update` uses (see `VerbSpec.run`).
55
+ run: (_params, runtime) =>
56
+ import("./runReset.js").then((module) =>
57
+ module.buildResetTask(runtime),
58
+ ) as unknown as Task<SourcesResetData>,
59
+ };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Build the `sources reset` Task — drop this project's built pack.
3
+ *
4
+ * The counterpart of `sources update`: update points the project at a pack it
5
+ * built, reset takes the pointer away, so reads go back to what the config
6
+ * resolves to on its own (the snapshot shipped with the CLI, or — for a project
7
+ * that declares its own packs — nothing until it builds them again). It is the
8
+ * verb a user needs after an upgrade passes over a pack an older CLI built and
9
+ * they would rather remove it than rebuild it.
10
+ *
11
+ * THE POINTER, AND ONLY THE POINTER. The pack cache is content-addressed and
12
+ * SHARED: another project on this machine may point at the same hash, and the
13
+ * embedded snapshot is materialized into that same cache under its own hash, so
14
+ * a per-project verb that deleted pack directories would be deleting bytes it
15
+ * does not own. The pointer is the whole of a project's store state — one line
16
+ * naming a hash — so removing it is exactly, and only, "this project no longer
17
+ * reads a pack of its own". What stays behind is a cache doing its job: a later
18
+ * `sources update` over the same sources finds the pack complete and reuses it
19
+ * without a rebuild. (No `--all` for the same reason it has no flags at all:
20
+ * evicting the shared cache, or the git-ref checkouts beside it, is a different
21
+ * job from resetting one project, and this verb would be the wrong owner.)
22
+ *
23
+ * Nothing built is not a failure: the verb reports that it found nothing and
24
+ * exits 0, the way `config unset` does for a field that was never set. There is
25
+ * no state to correct — the project already reads what a reset would leave it
26
+ * reading.
27
+ */
28
+
29
+ import { $, deleteFile, gen, type Task } from "@canonical/task";
30
+ import type { PragmaRuntime } from "../../kernel/runtime/index.js";
31
+ import { activePackPath, readActivePack } from "../../kernel/runtime/paths.js";
32
+ import type { SourcesResetData } from "./types.js";
33
+
34
+ /**
35
+ * Build the Task that removes the project's active-pack pointer.
36
+ *
37
+ * @param runtime - The per-invocation runtime.
38
+ * @returns A Task yielding what was removed and what answers reads now.
39
+ * @note Impure — reads config and the pointer; the Task deletes the pointer.
40
+ */
41
+ export async function buildResetTask(
42
+ runtime: PragmaRuntime,
43
+ ): Promise<Task<SourcesResetData>> {
44
+ const layers = await runtime.loadConfig();
45
+ const priorHash = readActivePack(runtime.cwd);
46
+ const path = activePackPath(runtime.cwd);
47
+ const data: SourcesResetData = {
48
+ removed: priorHash !== undefined,
49
+ contentHash: priorHash ?? null,
50
+ answers: layers.origins.packs === "default" ? "embedded" : "unavailable",
51
+ };
52
+
53
+ return gen(function* () {
54
+ // No pointer, no effect: a Task with nothing in it is what "nothing to do"
55
+ // looks like, and it keeps `--dry-run` honest (an empty plan, not a delete
56
+ // of a file that is not there).
57
+ if (priorHash !== undefined) {
58
+ // No undo is declared: an undo re-plans from the disk, where the pointer
59
+ // is already gone. The way back is `sources update`, which reuses the
60
+ // cached pack.
61
+ yield* $(deleteFile(path));
62
+ }
63
+ return data;
64
+ });
65
+ }
@@ -31,7 +31,7 @@ import {
31
31
  writeFile,
32
32
  } from "@canonical/task";
33
33
  import { VERSION } from "../../constants.js";
34
- import { cliRecovery, PragmaError } from "../../kernel/error/index.js";
34
+ import { callRecovery, PragmaError } from "../../kernel/error/index.js";
35
35
  // DIRECT LEAF IMPORT, not `graphpack/index.js`. The barrel re-exports
36
36
  // `embedded.ts`, which statically imports the ~1.9 MB generated pack — and
37
37
  // with per-file `tsc` output ESM evaluates that re-export when this module
@@ -49,10 +49,11 @@ import {
49
49
  redactUrl,
50
50
  resolvePackage,
51
51
  } from "../../kernel/runtime/refs/index.js";
52
+ import { existingGlobalSkillDirs } from "../setup/operations/setupSkills.js";
52
53
  // The global scope's EXISTING link directories, from the module that owns the
53
54
  // scope covenant — so `sources update` cannot drift away from what
54
55
  // `setup skills --global` links, or widen the scope on its own.
55
- import { existingGlobalSkillDirs } from "../setup/operations/setupSkills.js";
56
+ import { VERBOSE_BUILD_CALL } from "../shared/calls.js";
56
57
  import { globalSkillRoots, installedSkillsDir } from "../skill/discover.js";
57
58
  import { planHarnessSkillLinks, planSkillInstall } from "./installSkills.js";
58
59
  import type { SourcesUpdateData } from "./types.js";
@@ -200,8 +201,8 @@ export async function buildUpdateTask(
200
201
  ? "No packs are configured, so there are no sources to build a store from. The embedded pack answers reads until you add a pack."
201
202
  : `The ${entries.length} configured pack(s) resolved 0 RDF sources (no definitions/**.ttl or data/**.ttl). Refusing to build an empty store.`,
202
203
  {
203
- recovery: cliRecovery(
204
- "sources update --verbose",
204
+ recovery: callRecovery(
205
+ VERBOSE_BUILD_CALL,
205
206
  "Add a pack that ships `.ttl` under definitions/ or data/, then re-run.",
206
207
  ),
207
208
  },
@@ -270,8 +271,8 @@ export async function buildUpdateTask(
270
271
  throw PragmaError.configError(
271
272
  `None of the ${inputs.length} configured source(s) can be parsed — nothing to build.`,
272
273
  {
273
- recovery: cliRecovery(
274
- "sources update --verbose",
274
+ recovery: callRecovery(
275
+ VERBOSE_BUILD_CALL,
275
276
  "Fix the reported sources, then re-run.",
276
277
  ),
277
278
  },
@@ -303,8 +304,8 @@ export async function buildUpdateTask(
303
304
  throw PragmaError.configError(
304
305
  `The configured sources parsed to 0 RDF triples, so the store would be empty. Refusing to build an empty store.`,
305
306
  {
306
- recovery: cliRecovery(
307
- "sources update --verbose",
307
+ recovery: callRecovery(
308
+ VERBOSE_BUILD_CALL,
308
309
  "Check that the pack sources actually contain RDF triples, then re-run.",
309
310
  ),
310
311
  },
@@ -496,9 +497,9 @@ export async function classifySourceBuildError(
496
497
  ? `Pack source "${culprit.path}" cannot be parsed`
497
498
  : "The configured packs cannot be built into a store";
498
499
  return PragmaError.configError(`${where}: ${detail}`, {
499
- recovery: cliRecovery(
500
- "sources update --verbose",
501
- "Re-run with --verbose to see each file as it parses. If a pack ships malformed RDF, report it to that pack's maintainer.",
500
+ recovery: callRecovery(
501
+ VERBOSE_BUILD_CALL,
502
+ "A verbose re-run shows each file as it parses. If a pack ships malformed RDF, report it to that pack's maintainer.",
502
503
  ),
503
504
  });
504
505
  }