@canonical/pragma-cli 0.34.0 → 0.36.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 (832) hide show
  1. package/README.md +153 -30
  2. package/bundled-skills/add-standard/SKILL.md +338 -0
  3. package/bundled-skills/adoption-a1-styles/SKILL.md +269 -0
  4. package/bundled-skills/adoption-a2-components/SKILL.md +291 -0
  5. package/bundled-skills/adoption-a3-forms/SKILL.md +260 -0
  6. package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +406 -0
  7. package/bundled-skills/anatomy-author/SKILL.md +1226 -0
  8. package/bundled-skills/design-auditor/SKILL.md +455 -0
  9. package/bundled-skills/implement-component/SKILL.md +333 -0
  10. package/bundled-skills/specify-component/SKILL.md +331 -0
  11. package/bundled-skills/specify-pattern/SKILL.md +292 -0
  12. package/dist/.build-ok +0 -0
  13. package/dist/package.json +84 -0
  14. package/dist/pragma.conf.js +1016 -0
  15. package/dist/pragma.conf.js.map +1 -0
  16. package/dist/src/bin.js +356 -0
  17. package/dist/src/bin.js.map +1 -0
  18. package/dist/src/capabilities/capabilities/capabilities.render.js +70 -0
  19. package/dist/src/capabilities/capabilities/capabilities.render.js.map +1 -0
  20. package/dist/src/capabilities/capabilities/capabilities.verb.js +59 -0
  21. package/dist/src/capabilities/capabilities/capabilities.verb.js.map +1 -0
  22. package/dist/src/capabilities/capabilities/catalog.js +130 -0
  23. package/dist/src/capabilities/capabilities/catalog.js.map +1 -0
  24. package/dist/src/capabilities/capabilities/hints.js +195 -0
  25. package/dist/src/capabilities/capabilities/hints.js.map +1 -0
  26. package/dist/src/capabilities/capabilities/index.js +11 -0
  27. package/dist/src/capabilities/capabilities/index.js.map +1 -0
  28. package/dist/src/capabilities/capabilities/types.js +11 -0
  29. package/dist/src/capabilities/capabilities/types.js.map +1 -0
  30. package/dist/src/capabilities/colophon/collectColophon.js +83 -0
  31. package/dist/src/capabilities/colophon/collectColophon.js.map +1 -0
  32. package/dist/src/capabilities/colophon/colophon.render.js +59 -0
  33. package/dist/src/capabilities/colophon/colophon.render.js.map +1 -0
  34. package/dist/src/capabilities/colophon/colophon.verb.js +43 -0
  35. package/dist/src/capabilities/colophon/colophon.verb.js.map +1 -0
  36. package/dist/src/capabilities/colophon/index.js +5 -0
  37. package/dist/src/capabilities/colophon/index.js.map +1 -0
  38. package/dist/src/capabilities/colophon/markdownTerminal.js +90 -0
  39. package/dist/src/capabilities/colophon/markdownTerminal.js.map +1 -0
  40. package/dist/src/capabilities/colophon/types.js +10 -0
  41. package/dist/src/capabilities/colophon/types.js.map +1 -0
  42. package/dist/src/capabilities/config/collectConfigShow.js +59 -0
  43. package/dist/src/capabilities/config/collectConfigShow.js.map +1 -0
  44. package/dist/src/capabilities/config/field.render.js +22 -0
  45. package/dist/src/capabilities/config/field.render.js.map +1 -0
  46. package/dist/src/capabilities/config/fields.js +46 -0
  47. package/dist/src/capabilities/config/fields.js.map +1 -0
  48. package/dist/src/capabilities/config/get.verb.js +61 -0
  49. package/dist/src/capabilities/config/get.verb.js.map +1 -0
  50. package/dist/src/capabilities/config/index.js +5 -0
  51. package/dist/src/capabilities/config/index.js.map +1 -0
  52. package/dist/src/capabilities/config/runField.js +59 -0
  53. package/dist/src/capabilities/config/runField.js.map +1 -0
  54. package/dist/src/capabilities/config/runGet.js +28 -0
  55. package/dist/src/capabilities/config/runGet.js.map +1 -0
  56. package/dist/src/capabilities/config/runSet.js +53 -0
  57. package/dist/src/capabilities/config/runSet.js.map +1 -0
  58. package/dist/src/capabilities/config/set.verb.js +66 -0
  59. package/dist/src/capabilities/config/set.verb.js.map +1 -0
  60. package/dist/src/capabilities/config/show.render.js +84 -0
  61. package/dist/src/capabilities/config/show.render.js.map +1 -0
  62. package/dist/src/capabilities/config/show.verb.js +44 -0
  63. package/dist/src/capabilities/config/show.verb.js.map +1 -0
  64. package/dist/src/capabilities/config/types.js +5 -0
  65. package/dist/src/capabilities/config/types.js.map +1 -0
  66. package/dist/src/capabilities/config/unset.verb.js +49 -0
  67. package/dist/src/capabilities/config/unset.verb.js.map +1 -0
  68. package/dist/src/capabilities/create/cliProjection.js +195 -0
  69. package/dist/src/capabilities/create/cliProjection.js.map +1 -0
  70. package/dist/src/capabilities/create/constants.js +47 -0
  71. package/dist/src/capabilities/create/constants.js.map +1 -0
  72. package/dist/src/capabilities/create/create.render.js +100 -0
  73. package/dist/src/capabilities/create/create.render.js.map +1 -0
  74. package/dist/src/capabilities/create/create.verb.js +438 -0
  75. package/dist/src/capabilities/create/create.verb.js.map +1 -0
  76. package/dist/src/capabilities/create/createHelp.js +47 -0
  77. package/dist/src/capabilities/create/createHelp.js.map +1 -0
  78. package/dist/src/capabilities/create/createSurface.generated.js +394 -0
  79. package/dist/src/capabilities/create/createSurface.generated.js.map +1 -0
  80. package/dist/src/capabilities/create/generatorToVerbSpec.js +106 -0
  81. package/dist/src/capabilities/create/generatorToVerbSpec.js.map +1 -0
  82. package/dist/src/capabilities/create/index.js +18 -0
  83. package/dist/src/capabilities/create/index.js.map +1 -0
  84. package/dist/src/capabilities/create/messages.js +16 -0
  85. package/dist/src/capabilities/create/messages.js.map +1 -0
  86. package/dist/src/capabilities/create/mount.js +294 -0
  87. package/dist/src/capabilities/create/mount.js.map +1 -0
  88. package/dist/src/capabilities/create/pathJail.js +65 -0
  89. package/dist/src/capabilities/create/pathJail.js.map +1 -0
  90. package/dist/src/capabilities/create/pickGenerator.js +53 -0
  91. package/dist/src/capabilities/create/pickGenerator.js.map +1 -0
  92. package/dist/src/capabilities/create/types.js +2 -0
  93. package/dist/src/capabilities/create/types.js.map +1 -0
  94. package/dist/src/capabilities/distribution.js +40 -0
  95. package/dist/src/capabilities/distribution.js.map +1 -0
  96. package/dist/src/capabilities/doctor/checks/checkKeStore.js +40 -0
  97. package/dist/src/capabilities/doctor/checks/checkKeStore.js.map +1 -0
  98. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +21 -0
  99. package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -0
  100. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +148 -0
  101. package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -0
  102. package/dist/src/capabilities/doctor/checks/checkPragmaVersion.js +19 -0
  103. package/dist/src/capabilities/doctor/checks/checkPragmaVersion.js.map +1 -0
  104. package/dist/src/capabilities/doctor/checks/checkShellCompletions.js +199 -0
  105. package/dist/src/capabilities/doctor/checks/checkShellCompletions.js.map +1 -0
  106. package/dist/src/capabilities/doctor/checks/harnessInventory.js +195 -0
  107. package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -0
  108. package/dist/src/capabilities/doctor/checks/index.js +27 -0
  109. package/dist/src/capabilities/doctor/checks/index.js.map +1 -0
  110. package/dist/src/capabilities/doctor/checks/mcpCommand.js +57 -0
  111. package/dist/src/capabilities/doctor/checks/mcpCommand.js.map +1 -0
  112. package/dist/src/capabilities/doctor/checks/targetHealth.js +349 -0
  113. package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -0
  114. package/dist/src/capabilities/doctor/doctor.render.js +164 -0
  115. package/dist/src/capabilities/doctor/doctor.render.js.map +1 -0
  116. package/dist/src/capabilities/doctor/doctor.verb.js +49 -0
  117. package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -0
  118. package/dist/src/capabilities/doctor/index.js +5 -0
  119. package/dist/src/capabilities/doctor/index.js.map +1 -0
  120. package/dist/src/capabilities/doctor/runChecks.js +86 -0
  121. package/dist/src/capabilities/doctor/runChecks.js.map +1 -0
  122. package/dist/src/capabilities/doctor/types.js +5 -0
  123. package/dist/src/capabilities/doctor/types.js.map +1 -0
  124. package/dist/src/capabilities/graph/index.js +19 -0
  125. package/dist/src/capabilities/graph/index.js.map +1 -0
  126. package/dist/src/capabilities/graph/inspect.render.js +76 -0
  127. package/dist/src/capabilities/graph/inspect.render.js.map +1 -0
  128. package/dist/src/capabilities/graph/inspect.verb.js +53 -0
  129. package/dist/src/capabilities/graph/inspect.verb.js.map +1 -0
  130. package/dist/src/capabilities/graph/query.render.js +73 -0
  131. package/dist/src/capabilities/graph/query.render.js.map +1 -0
  132. package/dist/src/capabilities/graph/query.verb.js +49 -0
  133. package/dist/src/capabilities/graph/query.verb.js.map +1 -0
  134. package/dist/src/capabilities/graph/runQuery.js +41 -0
  135. package/dist/src/capabilities/graph/runQuery.js.map +1 -0
  136. package/dist/src/capabilities/index.js +56 -0
  137. package/dist/src/capabilities/index.js.map +1 -0
  138. package/dist/src/capabilities/info/collectInfo.js +72 -0
  139. package/dist/src/capabilities/info/collectInfo.js.map +1 -0
  140. package/dist/src/capabilities/info/index.js +5 -0
  141. package/dist/src/capabilities/info/index.js.map +1 -0
  142. package/dist/src/capabilities/info/info.render.js +57 -0
  143. package/dist/src/capabilities/info/info.render.js.map +1 -0
  144. package/dist/src/capabilities/info/info.verb.js +42 -0
  145. package/dist/src/capabilities/info/info.verb.js.map +1 -0
  146. package/dist/src/capabilities/info/types.js +5 -0
  147. package/dist/src/capabilities/info/types.js.map +1 -0
  148. package/dist/src/capabilities/meta/complete.verb.js +43 -0
  149. package/dist/src/capabilities/meta/complete.verb.js.map +1 -0
  150. package/dist/src/capabilities/meta/index.js +13 -0
  151. package/dist/src/capabilities/meta/index.js.map +1 -0
  152. package/dist/src/capabilities/meta/mcp.verb.js +34 -0
  153. package/dist/src/capabilities/meta/mcp.verb.js.map +1 -0
  154. package/dist/src/capabilities/ontology/index.js +21 -0
  155. package/dist/src/capabilities/ontology/index.js.map +1 -0
  156. package/dist/src/capabilities/ontology/queries.js +123 -0
  157. package/dist/src/capabilities/ontology/queries.js.map +1 -0
  158. package/dist/src/capabilities/ontology/render.js +66 -0
  159. package/dist/src/capabilities/ontology/render.js.map +1 -0
  160. package/dist/src/capabilities/ontology/verbs.js +181 -0
  161. package/dist/src/capabilities/ontology/verbs.js.map +1 -0
  162. package/dist/src/capabilities/prompt/index.js +16 -0
  163. package/dist/src/capabilities/prompt/index.js.map +1 -0
  164. package/dist/src/capabilities/prompt/prompt.render.js +78 -0
  165. package/dist/src/capabilities/prompt/prompt.render.js.map +1 -0
  166. package/dist/src/capabilities/prompt/types.js +10 -0
  167. package/dist/src/capabilities/prompt/types.js.map +1 -0
  168. package/dist/src/capabilities/prompt/verbs.js +93 -0
  169. package/dist/src/capabilities/prompt/verbs.js.map +1 -0
  170. package/dist/src/capabilities/resources/index.js +10 -0
  171. package/dist/src/capabilities/resources/index.js.map +1 -0
  172. package/dist/src/capabilities/resources/provider.js +423 -0
  173. package/dist/src/capabilities/resources/provider.js.map +1 -0
  174. package/dist/src/capabilities/setup/buildPlan.js +172 -0
  175. package/dist/src/capabilities/setup/buildPlan.js.map +1 -0
  176. package/dist/src/capabilities/setup/index.js +5 -0
  177. package/dist/src/capabilities/setup/index.js.map +1 -0
  178. package/dist/src/capabilities/setup/mode.js +53 -0
  179. package/dist/src/capabilities/setup/mode.js.map +1 -0
  180. package/dist/src/capabilities/setup/operations/index.js +39 -0
  181. package/dist/src/capabilities/setup/operations/index.js.map +1 -0
  182. package/dist/src/capabilities/setup/operations/setupCompletions.js +160 -0
  183. package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -0
  184. package/dist/src/capabilities/setup/operations/setupConfig.js +101 -0
  185. package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -0
  186. package/dist/src/capabilities/setup/operations/setupGenerator.js +390 -0
  187. package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -0
  188. package/dist/src/capabilities/setup/operations/setupLsp.js +329 -0
  189. package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -0
  190. package/dist/src/capabilities/setup/operations/setupMcp.js +253 -0
  191. package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -0
  192. package/dist/src/capabilities/setup/operations/setupSkills.js +594 -0
  193. package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -0
  194. package/dist/src/capabilities/setup/plan.js +128 -0
  195. package/dist/src/capabilities/setup/plan.js.map +1 -0
  196. package/dist/src/capabilities/setup/plan.render.js +271 -0
  197. package/dist/src/capabilities/setup/plan.render.js.map +1 -0
  198. package/dist/src/capabilities/setup/setup.render.js +54 -0
  199. package/dist/src/capabilities/setup/setup.render.js.map +1 -0
  200. package/dist/src/capabilities/setup/setup.verb.js +387 -0
  201. package/dist/src/capabilities/setup/setup.verb.js.map +1 -0
  202. package/dist/src/capabilities/setup/shell.js +196 -0
  203. package/dist/src/capabilities/setup/shell.js.map +1 -0
  204. package/dist/src/capabilities/setup/targets.js +328 -0
  205. package/dist/src/capabilities/setup/targets.js.map +1 -0
  206. package/dist/src/capabilities/setup/types.js +5 -0
  207. package/dist/src/capabilities/setup/types.js.map +1 -0
  208. package/dist/src/capabilities/shared/assertExecOk.js +137 -0
  209. package/dist/src/capabilities/shared/assertExecOk.js.map +1 -0
  210. package/dist/src/capabilities/shared/index.js +27 -0
  211. package/dist/src/capabilities/shared/index.js.map +1 -0
  212. package/dist/src/capabilities/shared/packageManager.js +349 -0
  213. package/dist/src/capabilities/shared/packageManager.js.map +1 -0
  214. package/dist/src/capabilities/shared/registry.js +55 -0
  215. package/dist/src/capabilities/shared/registry.js.map +1 -0
  216. package/dist/src/capabilities/skill/discover.js +281 -0
  217. package/dist/src/capabilities/skill/discover.js.map +1 -0
  218. package/dist/src/capabilities/skill/index.js +10 -0
  219. package/dist/src/capabilities/skill/index.js.map +1 -0
  220. package/dist/src/capabilities/skill/render.js +49 -0
  221. package/dist/src/capabilities/skill/render.js.map +1 -0
  222. package/dist/src/capabilities/skill/verbs.js +83 -0
  223. package/dist/src/capabilities/skill/verbs.js.map +1 -0
  224. package/dist/src/capabilities/sources/collectStatus.js +103 -0
  225. package/dist/src/capabilities/sources/collectStatus.js.map +1 -0
  226. package/dist/src/capabilities/sources/index.js +13 -0
  227. package/dist/src/capabilities/sources/index.js.map +1 -0
  228. package/dist/src/capabilities/sources/installSkills.js +309 -0
  229. package/dist/src/capabilities/sources/installSkills.js.map +1 -0
  230. package/dist/src/capabilities/sources/runUpdate.js +460 -0
  231. package/dist/src/capabilities/sources/runUpdate.js.map +1 -0
  232. package/dist/src/capabilities/sources/status.render.js +64 -0
  233. package/dist/src/capabilities/sources/status.render.js.map +1 -0
  234. package/dist/src/capabilities/sources/status.verb.js +40 -0
  235. package/dist/src/capabilities/sources/status.verb.js.map +1 -0
  236. package/dist/src/capabilities/sources/types.js +6 -0
  237. package/dist/src/capabilities/sources/types.js.map +1 -0
  238. package/dist/src/capabilities/sources/update.render.js +34 -0
  239. package/dist/src/capabilities/sources/update.render.js.map +1 -0
  240. package/dist/src/capabilities/sources/update.verb.js +55 -0
  241. package/dist/src/capabilities/sources/update.verb.js.map +1 -0
  242. package/dist/src/capabilities/upgrade/index.js +5 -0
  243. package/dist/src/capabilities/upgrade/index.js.map +1 -0
  244. package/dist/src/capabilities/upgrade/runUpgrade.js +135 -0
  245. package/dist/src/capabilities/upgrade/runUpgrade.js.map +1 -0
  246. package/dist/src/capabilities/upgrade/types.js +5 -0
  247. package/dist/src/capabilities/upgrade/types.js.map +1 -0
  248. package/dist/src/capabilities/upgrade/upgrade.render.js +52 -0
  249. package/dist/src/capabilities/upgrade/upgrade.render.js.map +1 -0
  250. package/dist/src/capabilities/upgrade/upgrade.verb.js +52 -0
  251. package/dist/src/capabilities/upgrade/upgrade.verb.js.map +1 -0
  252. package/dist/src/capabilities/version/index.js +10 -0
  253. package/dist/src/capabilities/version/index.js.map +1 -0
  254. package/dist/src/capabilities/version/version.verb.js +36 -0
  255. package/dist/src/capabilities/version/version.verb.js.map +1 -0
  256. package/dist/src/constants.js +87 -0
  257. package/dist/src/constants.js.map +1 -0
  258. package/dist/src/index.js +12 -0
  259. package/dist/src/index.js.map +1 -0
  260. package/dist/src/kernel/completion/complete.js +66 -0
  261. package/dist/src/kernel/completion/complete.js.map +1 -0
  262. package/dist/src/kernel/completion/emitScripts.js +92 -0
  263. package/dist/src/kernel/completion/emitScripts.js.map +1 -0
  264. package/dist/src/kernel/completion/entitySource.js +285 -0
  265. package/dist/src/kernel/completion/entitySource.js.map +1 -0
  266. package/dist/src/kernel/completion/index.js +14 -0
  267. package/dist/src/kernel/completion/index.js.map +1 -0
  268. package/dist/src/kernel/completion/model.js +301 -0
  269. package/dist/src/kernel/completion/model.js.map +1 -0
  270. package/dist/src/kernel/completion/parse.js +253 -0
  271. package/dist/src/kernel/completion/parse.js.map +1 -0
  272. package/dist/src/kernel/completion/rank.js +101 -0
  273. package/dist/src/kernel/completion/rank.js.map +1 -0
  274. package/dist/src/kernel/completion/resolve.js +100 -0
  275. package/dist/src/kernel/completion/resolve.js.map +1 -0
  276. package/dist/src/kernel/completion/templates/bash.js +209 -0
  277. package/dist/src/kernel/completion/templates/bash.js.map +1 -0
  278. package/dist/src/kernel/completion/templates/fish.js +214 -0
  279. package/dist/src/kernel/completion/templates/fish.js.map +1 -0
  280. package/dist/src/kernel/completion/templates/index.js +23 -0
  281. package/dist/src/kernel/completion/templates/index.js.map +1 -0
  282. package/dist/src/kernel/completion/templates/shared.js +98 -0
  283. package/dist/src/kernel/completion/templates/shared.js.map +1 -0
  284. package/dist/src/kernel/completion/templates/zsh.js +201 -0
  285. package/dist/src/kernel/completion/templates/zsh.js.map +1 -0
  286. package/dist/src/kernel/completion/types.js +13 -0
  287. package/dist/src/kernel/completion/types.js.map +1 -0
  288. package/dist/src/kernel/config/defaults.js +17 -0
  289. package/dist/src/kernel/config/defaults.js.map +1 -0
  290. package/dist/src/kernel/config/evaluateProjectConfig.js +126 -0
  291. package/dist/src/kernel/config/evaluateProjectConfig.js.map +1 -0
  292. package/dist/src/kernel/config/findProjectConfig.js +43 -0
  293. package/dist/src/kernel/config/findProjectConfig.js.map +1 -0
  294. package/dist/src/kernel/config/firstRun.js +34 -0
  295. package/dist/src/kernel/config/firstRun.js.map +1 -0
  296. package/dist/src/kernel/config/globalConfig.js +79 -0
  297. package/dist/src/kernel/config/globalConfig.js.map +1 -0
  298. package/dist/src/kernel/config/index.js +16 -0
  299. package/dist/src/kernel/config/index.js.map +1 -0
  300. package/dist/src/kernel/config/paths.js +35 -0
  301. package/dist/src/kernel/config/paths.js.map +1 -0
  302. package/dist/src/kernel/config/readConfig.js +78 -0
  303. package/dist/src/kernel/config/readConfig.js.map +1 -0
  304. package/dist/src/kernel/config/schema.js +130 -0
  305. package/dist/src/kernel/config/schema.js.map +1 -0
  306. package/dist/src/kernel/config/types.js +19 -0
  307. package/dist/src/kernel/config/types.js.map +1 -0
  308. package/dist/src/kernel/config/writeConfigField.js +59 -0
  309. package/dist/src/kernel/config/writeConfigField.js.map +1 -0
  310. package/dist/src/kernel/copy.js +43 -0
  311. package/dist/src/kernel/copy.js.map +1 -0
  312. package/dist/src/kernel/error/PragmaError.js +149 -0
  313. package/dist/src/kernel/error/PragmaError.js.map +1 -0
  314. package/dist/src/kernel/error/constants.js +40 -0
  315. package/dist/src/kernel/error/constants.js.map +1 -0
  316. package/dist/src/kernel/error/fromTaskError.js +96 -0
  317. package/dist/src/kernel/error/fromTaskError.js.map +1 -0
  318. package/dist/src/kernel/error/index.js +13 -0
  319. package/dist/src/kernel/error/index.js.map +1 -0
  320. package/dist/src/kernel/error/recovery.js +52 -0
  321. package/dist/src/kernel/error/recovery.js.map +1 -0
  322. package/dist/src/kernel/error/renderError.js +115 -0
  323. package/dist/src/kernel/error/renderError.js.map +1 -0
  324. package/dist/src/kernel/error/serialize.js +25 -0
  325. package/dist/src/kernel/error/serialize.js.map +1 -0
  326. package/dist/src/kernel/error/types.js +9 -0
  327. package/dist/src/kernel/error/types.js.map +1 -0
  328. package/dist/src/kernel/index.js +34 -0
  329. package/dist/src/kernel/index.js.map +1 -0
  330. package/dist/src/kernel/interactivity.js +68 -0
  331. package/dist/src/kernel/interactivity.js.map +1 -0
  332. package/dist/src/kernel/packs/collect.js +187 -0
  333. package/dist/src/kernel/packs/collect.js.map +1 -0
  334. package/dist/src/kernel/packs/compile.js +304 -0
  335. package/dist/src/kernel/packs/compile.js.map +1 -0
  336. package/dist/src/kernel/packs/disclosure.js +76 -0
  337. package/dist/src/kernel/packs/disclosure.js.map +1 -0
  338. package/dist/src/kernel/packs/glob.js +38 -0
  339. package/dist/src/kernel/packs/glob.js.map +1 -0
  340. package/dist/src/kernel/packs/graphql/buildLookupDocument.js +258 -0
  341. package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -0
  342. package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js +157 -0
  343. package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js.map +1 -0
  344. package/dist/src/kernel/packs/graphql/index.js +20 -0
  345. package/dist/src/kernel/packs/graphql/index.js.map +1 -0
  346. package/dist/src/kernel/packs/graphql/nameMap.js +63 -0
  347. package/dist/src/kernel/packs/graphql/nameMap.js.map +1 -0
  348. package/dist/src/kernel/packs/index.js +34 -0
  349. package/dist/src/kernel/packs/index.js.map +1 -0
  350. package/dist/src/kernel/packs/iri.js +110 -0
  351. package/dist/src/kernel/packs/iri.js.map +1 -0
  352. package/dist/src/kernel/packs/renderPack.js +129 -0
  353. package/dist/src/kernel/packs/renderPack.js.map +1 -0
  354. package/dist/src/kernel/packs/resolveEntity.js +274 -0
  355. package/dist/src/kernel/packs/resolveEntity.js.map +1 -0
  356. package/dist/src/kernel/packs/runBodies.js +140 -0
  357. package/dist/src/kernel/packs/runBodies.js.map +1 -0
  358. package/dist/src/kernel/packs/sample.js +56 -0
  359. package/dist/src/kernel/packs/sample.js.map +1 -0
  360. package/dist/src/kernel/packs/schema.js +421 -0
  361. package/dist/src/kernel/packs/schema.js.map +1 -0
  362. package/dist/src/kernel/packs/sparql/applyFilters.js +167 -0
  363. package/dist/src/kernel/packs/sparql/applyFilters.js.map +1 -0
  364. package/dist/src/kernel/packs/sparql/applySearch.js +25 -0
  365. package/dist/src/kernel/packs/sparql/applySearch.js.map +1 -0
  366. package/dist/src/kernel/packs/sparql/buildLookupQuery.js +480 -0
  367. package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -0
  368. package/dist/src/kernel/packs/sparql/escape.js +21 -0
  369. package/dist/src/kernel/packs/sparql/escape.js.map +1 -0
  370. package/dist/src/kernel/packs/sparql/index.js +31 -0
  371. package/dist/src/kernel/packs/sparql/index.js.map +1 -0
  372. package/dist/src/kernel/packs/sparql/runSelect.js +101 -0
  373. package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -0
  374. package/dist/src/kernel/packs/types.js +30 -0
  375. package/dist/src/kernel/packs/types.js.map +1 -0
  376. package/dist/src/kernel/packs/uniqueness.js +30 -0
  377. package/dist/src/kernel/packs/uniqueness.js.map +1 -0
  378. package/dist/src/kernel/project/cli/buildProgram.js +263 -0
  379. package/dist/src/kernel/project/cli/buildProgram.js.map +1 -0
  380. package/dist/src/kernel/project/cli/constants.js +27 -0
  381. package/dist/src/kernel/project/cli/constants.js.map +1 -0
  382. package/dist/src/kernel/project/cli/dispatch.js +420 -0
  383. package/dist/src/kernel/project/cli/dispatch.js.map +1 -0
  384. package/dist/src/kernel/project/cli/exitCodes.js +66 -0
  385. package/dist/src/kernel/project/cli/exitCodes.js.map +1 -0
  386. package/dist/src/kernel/project/cli/globalFlags.js +219 -0
  387. package/dist/src/kernel/project/cli/globalFlags.js.map +1 -0
  388. package/dist/src/kernel/project/cli/helpFormat.js +58 -0
  389. package/dist/src/kernel/project/cli/helpFormat.js.map +1 -0
  390. package/dist/src/kernel/project/cli/index.js +14 -0
  391. package/dist/src/kernel/project/cli/index.js.map +1 -0
  392. package/dist/src/kernel/project/cli/rootHelp.js +227 -0
  393. package/dist/src/kernel/project/cli/rootHelp.js.map +1 -0
  394. package/dist/src/kernel/project/cli/suggest.js +75 -0
  395. package/dist/src/kernel/project/cli/suggest.js.map +1 -0
  396. package/dist/src/kernel/project/cli/suggestNames.js +96 -0
  397. package/dist/src/kernel/project/cli/suggestNames.js.map +1 -0
  398. package/dist/src/kernel/project/cli/verbHelp.js +131 -0
  399. package/dist/src/kernel/project/cli/verbHelp.js.map +1 -0
  400. package/dist/src/kernel/project/mcp/buildServer.js +67 -0
  401. package/dist/src/kernel/project/mcp/buildServer.js.map +1 -0
  402. package/dist/src/kernel/project/mcp/envelope.js +37 -0
  403. package/dist/src/kernel/project/mcp/envelope.js.map +1 -0
  404. package/dist/src/kernel/project/mcp/index.js +8 -0
  405. package/dist/src/kernel/project/mcp/index.js.map +1 -0
  406. package/dist/src/kernel/project/mcp/instructions.js +44 -0
  407. package/dist/src/kernel/project/mcp/instructions.js.map +1 -0
  408. package/dist/src/kernel/project/mcp/mcpError.js +42 -0
  409. package/dist/src/kernel/project/mcp/mcpError.js.map +1 -0
  410. package/dist/src/kernel/project/mcp/prompts/index.js +36 -0
  411. package/dist/src/kernel/project/mcp/prompts/index.js.map +1 -0
  412. package/dist/src/kernel/project/mcp/prompts/provider.js +98 -0
  413. package/dist/src/kernel/project/mcp/prompts/provider.js.map +1 -0
  414. package/dist/src/kernel/project/mcp/prompts/source.js +154 -0
  415. package/dist/src/kernel/project/mcp/prompts/source.js.map +1 -0
  416. package/dist/src/kernel/project/mcp/registerVerb.js +315 -0
  417. package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -0
  418. package/dist/src/kernel/project/mcp/serve.js +35 -0
  419. package/dist/src/kernel/project/mcp/serve.js.map +1 -0
  420. package/dist/src/kernel/render/compactUri.js +24 -0
  421. package/dist/src/kernel/render/compactUri.js.map +1 -0
  422. package/dist/src/kernel/render/contracts.js +10 -0
  423. package/dist/src/kernel/render/contracts.js.map +1 -0
  424. package/dist/src/kernel/render/disclosure.js +34 -0
  425. package/dist/src/kernel/render/disclosure.js.map +1 -0
  426. package/dist/src/kernel/render/envelope.js +30 -0
  427. package/dist/src/kernel/render/envelope.js.map +1 -0
  428. package/dist/src/kernel/render/formatters.js +27 -0
  429. package/dist/src/kernel/render/formatters.js.map +1 -0
  430. package/dist/src/kernel/render/index.js +15 -0
  431. package/dist/src/kernel/render/index.js.map +1 -0
  432. package/dist/src/kernel/render/prefixes.js +46 -0
  433. package/dist/src/kernel/render/prefixes.js.map +1 -0
  434. package/dist/src/kernel/render/renderers.js +468 -0
  435. package/dist/src/kernel/render/renderers.js.map +1 -0
  436. package/dist/src/kernel/render/style.js +105 -0
  437. package/dist/src/kernel/render/style.js.map +1 -0
  438. package/dist/src/kernel/render/turtle.js +194 -0
  439. package/dist/src/kernel/render/turtle.js.map +1 -0
  440. package/dist/src/kernel/render/vocabulary.js +174 -0
  441. package/dist/src/kernel/render/vocabulary.js.map +1 -0
  442. package/dist/src/kernel/render/writeStdout.js +43 -0
  443. package/dist/src/kernel/render/writeStdout.js.map +1 -0
  444. package/dist/src/kernel/runtime/boot.js +49 -0
  445. package/dist/src/kernel/runtime/boot.js.map +1 -0
  446. package/dist/src/kernel/runtime/facade.js +39 -0
  447. package/dist/src/kernel/runtime/facade.js.map +1 -0
  448. package/dist/src/kernel/runtime/graphpack/build.js +122 -0
  449. package/dist/src/kernel/runtime/graphpack/build.js.map +1 -0
  450. package/dist/src/kernel/runtime/graphpack/buildIndex.js +303 -0
  451. package/dist/src/kernel/runtime/graphpack/buildIndex.js.map +1 -0
  452. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +6 -0
  453. package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -0
  454. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +4 -0
  455. package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -0
  456. package/dist/src/kernel/runtime/graphpack/embedded/pack.stories.generated.js +4 -0
  457. package/dist/src/kernel/runtime/graphpack/embedded/pack.stories.generated.js.map +1 -0
  458. package/dist/src/kernel/runtime/graphpack/embedded.js +82 -0
  459. package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -0
  460. package/dist/src/kernel/runtime/graphpack/hash.js +38 -0
  461. package/dist/src/kernel/runtime/graphpack/hash.js.map +1 -0
  462. package/dist/src/kernel/runtime/graphpack/index.js +11 -0
  463. package/dist/src/kernel/runtime/graphpack/index.js.map +1 -0
  464. package/dist/src/kernel/runtime/graphpack/manifest.js +145 -0
  465. package/dist/src/kernel/runtime/graphpack/manifest.js.map +1 -0
  466. package/dist/src/kernel/runtime/graphpack/read.js +92 -0
  467. package/dist/src/kernel/runtime/graphpack/read.js.map +1 -0
  468. package/dist/src/kernel/runtime/graphpack/schemas.js +70 -0
  469. package/dist/src/kernel/runtime/graphpack/schemas.js.map +1 -0
  470. package/dist/src/kernel/runtime/graphpack/stories.js +68 -0
  471. package/dist/src/kernel/runtime/graphpack/stories.js.map +1 -0
  472. package/dist/src/kernel/runtime/graphpack/types.js +55 -0
  473. package/dist/src/kernel/runtime/graphpack/types.js.map +1 -0
  474. package/dist/src/kernel/runtime/index.js +8 -0
  475. package/dist/src/kernel/runtime/index.js.map +1 -0
  476. package/dist/src/kernel/runtime/loadSession.js +34 -0
  477. package/dist/src/kernel/runtime/loadSession.js.map +1 -0
  478. package/dist/src/kernel/runtime/paths.js +78 -0
  479. package/dist/src/kernel/runtime/paths.js.map +1 -0
  480. package/dist/src/kernel/runtime/probe.js +37 -0
  481. package/dist/src/kernel/runtime/probe.js.map +1 -0
  482. package/dist/src/kernel/runtime/readEntity.js +363 -0
  483. package/dist/src/kernel/runtime/readEntity.js.map +1 -0
  484. package/dist/src/kernel/runtime/refs/gitOps.js +65 -0
  485. package/dist/src/kernel/runtime/refs/gitOps.js.map +1 -0
  486. package/dist/src/kernel/runtime/refs/index.js +29 -0
  487. package/dist/src/kernel/runtime/refs/index.js.map +1 -0
  488. package/dist/src/kernel/runtime/refs/parseRef.js +70 -0
  489. package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -0
  490. package/dist/src/kernel/runtime/refs/resolve.js +332 -0
  491. package/dist/src/kernel/runtime/refs/resolve.js.map +1 -0
  492. package/dist/src/kernel/runtime/resolveSources.js +62 -0
  493. package/dist/src/kernel/runtime/resolveSources.js.map +1 -0
  494. package/dist/src/kernel/runtime/store.js +75 -0
  495. package/dist/src/kernel/runtime/store.js.map +1 -0
  496. package/dist/src/kernel/runtime/storeReadiness.js +51 -0
  497. package/dist/src/kernel/runtime/storeReadiness.js.map +1 -0
  498. package/dist/src/kernel/runtime/types.js +11 -0
  499. package/dist/src/kernel/runtime/types.js.map +1 -0
  500. package/dist/src/kernel/spec/asVerb.js +21 -0
  501. package/dist/src/kernel/spec/asVerb.js.map +1 -0
  502. package/dist/src/kernel/spec/emitReference.js +578 -0
  503. package/dist/src/kernel/spec/emitReference.js.map +1 -0
  504. package/dist/src/kernel/spec/emitSurface.js +202 -0
  505. package/dist/src/kernel/spec/emitSurface.js.map +1 -0
  506. package/dist/src/kernel/spec/index.js +11 -0
  507. package/dist/src/kernel/spec/index.js.map +1 -0
  508. package/dist/src/kernel/spec/surfaceConformance.js +103 -0
  509. package/dist/src/kernel/spec/surfaceConformance.js.map +1 -0
  510. package/dist/src/kernel/spec/types.js +14 -0
  511. package/dist/src/kernel/spec/types.js.map +1 -0
  512. package/dist/src/kernel/spec/validate.js +110 -0
  513. package/dist/src/kernel/spec/validate.js.map +1 -0
  514. package/dist/src/kernel/vocabulary.js +97 -0
  515. package/dist/src/kernel/vocabulary.js.map +1 -0
  516. package/dist/src/types.js +11 -0
  517. package/dist/src/types.js.map +1 -0
  518. package/package.json +22 -23
  519. package/pragma.conf.ts +486 -90
  520. package/src/bin.ts +274 -82
  521. package/src/capabilities/block.parity.test.ts +29 -12
  522. package/src/capabilities/block.shipped.exec.test.ts +282 -0
  523. package/src/capabilities/block.tierRank.exec.test.ts +300 -0
  524. package/src/capabilities/capabilities/capabilities.render.ts +1 -1
  525. package/src/capabilities/capabilities/capabilities.verb.ts +1 -1
  526. package/src/capabilities/capabilities/catalog.ts +3 -3
  527. package/src/capabilities/capabilities/hints.ts +32 -7
  528. package/src/capabilities/capabilities/index.ts +1 -1
  529. package/src/capabilities/colophon/collectColophon.ts +35 -24
  530. package/src/capabilities/colophon/colophon.render.ts +24 -1
  531. package/src/capabilities/colophon/colophon.test.ts +42 -21
  532. package/src/capabilities/colophon/colophon.verb.ts +4 -4
  533. package/src/capabilities/config/collectConfigShow.test.ts +1 -0
  534. package/src/capabilities/config/collectConfigShow.ts +3 -3
  535. package/src/capabilities/config/field.render.ts +4 -5
  536. package/src/capabilities/config/fields.ts +17 -10
  537. package/src/capabilities/config/get.verb.ts +70 -0
  538. package/src/capabilities/config/getUnset.test.ts +264 -0
  539. package/src/capabilities/config/index.ts +5 -1
  540. package/src/capabilities/config/runField.ts +40 -22
  541. package/src/capabilities/config/runGet.ts +34 -0
  542. package/src/capabilities/config/runSet.ts +35 -9
  543. package/src/capabilities/config/set.test.ts +48 -14
  544. package/src/capabilities/config/set.verb.ts +8 -7
  545. package/src/capabilities/config/show.render.ts +1 -1
  546. package/src/capabilities/config/show.verb.ts +9 -6
  547. package/src/capabilities/config/types.ts +18 -4
  548. package/src/capabilities/config/unset.verb.ts +58 -0
  549. package/src/capabilities/create/byteEquality.subprocess.test.ts +2 -3
  550. package/src/capabilities/create/byteEquality.test.ts +25 -11
  551. package/src/capabilities/create/cliProjection.ts +227 -0
  552. package/src/capabilities/create/constants.ts +36 -61
  553. package/src/capabilities/create/create.mcp.test.ts +89 -5
  554. package/src/capabilities/create/create.render.ts +71 -7
  555. package/src/capabilities/create/create.test.ts +433 -219
  556. package/src/capabilities/create/create.verb.ts +297 -328
  557. package/src/capabilities/create/createGrammar.test.ts +865 -0
  558. package/src/capabilities/create/createHelp.ts +71 -0
  559. package/src/capabilities/create/createSurface.generated.ts +400 -0
  560. package/src/capabilities/create/crossCli.subprocess.test.ts +745 -0
  561. package/src/capabilities/create/cwdJail.test.ts +24 -5
  562. package/src/capabilities/create/generatorToVerbSpec.test.ts +186 -0
  563. package/src/capabilities/create/generatorToVerbSpec.ts +13 -11
  564. package/src/capabilities/create/index.ts +7 -4
  565. package/src/capabilities/create/messages.ts +18 -0
  566. package/src/capabilities/create/mount.ts +391 -0
  567. package/src/capabilities/create/pathJail.test.ts +90 -0
  568. package/src/capabilities/create/pathJail.ts +8 -5
  569. package/src/capabilities/create/pickGenerator.ts +23 -35
  570. package/src/capabilities/create/shippedCreate.subprocess.test.ts +164 -0
  571. package/src/capabilities/create/types.ts +20 -0
  572. package/src/capabilities/distribution.parity.test.ts +4 -0
  573. package/src/capabilities/distribution.test.ts +3 -1
  574. package/src/capabilities/distribution.ts +10 -15
  575. package/src/capabilities/doctor/checks/checkKeStore.ts +7 -5
  576. package/src/capabilities/doctor/checks/checkPackageRefs.ts +75 -8
  577. package/src/capabilities/doctor/checks/checkPragmaVersion.ts +2 -2
  578. package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +76 -29
  579. package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -17
  580. package/src/capabilities/doctor/checks/harnessInventory.test.ts +219 -0
  581. package/src/capabilities/doctor/checks/harnessInventory.ts +298 -0
  582. package/src/capabilities/doctor/checks/index.ts +27 -0
  583. package/src/capabilities/doctor/checks/mcpCommand.test.ts +100 -0
  584. package/src/capabilities/doctor/checks/mcpCommand.ts +69 -0
  585. package/src/capabilities/doctor/checks/targetHealth.ts +444 -0
  586. package/src/capabilities/doctor/doctor.render.test.ts +125 -38
  587. package/src/capabilities/doctor/doctor.render.ts +74 -74
  588. package/src/capabilities/doctor/doctor.test.ts +338 -37
  589. package/src/capabilities/doctor/doctor.verb.ts +8 -3
  590. package/src/capabilities/doctor/runChecks.ts +65 -63
  591. package/src/capabilities/doctor/types.ts +22 -15
  592. package/src/capabilities/emptyRecovery.test.ts +21 -8
  593. package/src/capabilities/graph/examples.exec.test.ts +107 -0
  594. package/src/capabilities/graph/index.ts +1 -1
  595. package/src/capabilities/graph/inspect.render.ts +70 -22
  596. package/src/capabilities/graph/inspect.test.ts +260 -5
  597. package/src/capabilities/graph/inspect.verb.ts +18 -6
  598. package/src/capabilities/graph/query.render.ts +15 -3
  599. package/src/capabilities/graph/query.verb.ts +3 -3
  600. package/src/capabilities/graph/runQuery.ts +2 -3
  601. package/src/capabilities/index.ts +3 -1
  602. package/src/capabilities/info/collectInfo.ts +13 -5
  603. package/src/capabilities/info/info.render.ts +7 -3
  604. package/src/capabilities/info/info.test.ts +37 -1
  605. package/src/capabilities/info/info.verb.ts +1 -1
  606. package/src/capabilities/info/types.ts +10 -2
  607. package/src/capabilities/lazy.test.ts +32 -0
  608. package/src/capabilities/meta/complete.verb.ts +1 -1
  609. package/src/capabilities/meta/index.ts +1 -1
  610. package/src/capabilities/meta/mcp.verb.ts +10 -8
  611. package/src/capabilities/ontology/index.ts +15 -11
  612. package/src/capabilities/ontology/ontology.test.ts +6 -55
  613. package/src/capabilities/ontology/queries.ts +2 -2
  614. package/src/capabilities/ontology/render.ts +3 -4
  615. package/src/capabilities/ontology/verbs.ts +27 -68
  616. package/src/capabilities/prompt/index.ts +2 -2
  617. package/src/capabilities/prompt/prompt.render.ts +6 -2
  618. package/src/capabilities/prompt/types.ts +1 -1
  619. package/src/capabilities/prompt/verbs.ts +4 -5
  620. package/src/capabilities/reference.test.ts +63 -0
  621. package/src/capabilities/renderVocabularySync.test.ts +82 -0
  622. package/src/capabilities/resources/provider.ts +342 -85
  623. package/src/capabilities/resources/resources.test.ts +355 -59
  624. package/src/capabilities/scopeTypeSync.test.ts +29 -15
  625. package/src/capabilities/setup/buildPlan.ts +240 -0
  626. package/src/capabilities/setup/index.ts +7 -7
  627. package/src/capabilities/setup/mode.ts +74 -0
  628. package/src/capabilities/setup/operations/index.ts +79 -0
  629. package/src/capabilities/setup/operations/setupCompletions.ts +97 -24
  630. package/src/capabilities/setup/operations/setupConfig.ts +124 -0
  631. package/src/capabilities/setup/operations/setupGenerator.ts +478 -334
  632. package/src/capabilities/setup/operations/setupLsp.ts +420 -67
  633. package/src/capabilities/setup/operations/setupMcp.ts +238 -127
  634. package/src/capabilities/setup/operations/setupSkills.ts +667 -105
  635. package/src/capabilities/setup/plan.render.ts +336 -0
  636. package/src/capabilities/setup/plan.ts +241 -0
  637. package/src/capabilities/setup/setup.mcp.correctness.test.ts +432 -0
  638. package/src/capabilities/setup/setup.render.test.ts +297 -75
  639. package/src/capabilities/setup/setup.render.ts +45 -77
  640. package/src/capabilities/setup/setup.test.ts +1819 -225
  641. package/src/capabilities/setup/setup.verb.ts +288 -78
  642. package/src/capabilities/setup/shell.test.ts +86 -0
  643. package/src/capabilities/setup/shell.ts +137 -11
  644. package/src/capabilities/setup/targets.ts +435 -0
  645. package/src/capabilities/setup/types.ts +23 -70
  646. package/src/capabilities/shared/assertExecOk.ts +68 -10
  647. package/src/capabilities/shared/index.ts +43 -0
  648. package/src/capabilities/shared/packageManager.test.ts +470 -0
  649. package/src/capabilities/shared/packageManager.ts +425 -34
  650. package/src/capabilities/skill/bundledSkills.test.ts +347 -0
  651. package/src/capabilities/skill/discover.ts +131 -10
  652. package/src/capabilities/skill/index.ts +1 -1
  653. package/src/capabilities/skill/render.ts +10 -9
  654. package/src/capabilities/skill/skill.test.ts +22 -7
  655. package/src/capabilities/skill/verbs.ts +3 -4
  656. package/src/capabilities/sources/collectStatus.ts +7 -2
  657. package/src/capabilities/sources/index.ts +1 -1
  658. package/src/capabilities/sources/installSkills.ts +265 -10
  659. package/src/capabilities/sources/runUpdate.ts +131 -23
  660. package/src/capabilities/sources/sources.test.ts +382 -2
  661. package/src/capabilities/sources/status.render.ts +1 -1
  662. package/src/capabilities/sources/status.verb.ts +1 -1
  663. package/src/capabilities/sources/update.render.ts +1 -1
  664. package/src/capabilities/sources/update.verb.ts +4 -4
  665. package/src/capabilities/surface.test.ts +136 -19
  666. package/src/capabilities/upgrade/runUpgrade.ts +53 -14
  667. package/src/capabilities/upgrade/types.ts +10 -2
  668. package/src/capabilities/upgrade/upgrade.render.ts +13 -7
  669. package/src/capabilities/upgrade/upgrade.test.ts +75 -3
  670. package/src/capabilities/upgrade/upgrade.verb.ts +1 -1
  671. package/src/capabilities/version/index.ts +12 -0
  672. package/src/capabilities/version/version.test.ts +66 -0
  673. package/src/capabilities/version/version.verb.ts +39 -0
  674. package/src/constants.ts +36 -1
  675. package/src/identity.test.ts +57 -29
  676. package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +15 -13
  677. package/src/kernel/completion/complete.test.ts +12 -2
  678. package/src/kernel/completion/complete.ts +1 -1
  679. package/src/kernel/completion/emitScripts.ts +1 -1
  680. package/src/kernel/completion/entitySource.test.ts +16 -3
  681. package/src/kernel/completion/entitySource.ts +21 -8
  682. package/src/kernel/completion/model.test.ts +164 -12
  683. package/src/kernel/completion/model.ts +94 -14
  684. package/src/kernel/completion/parse.test.ts +4 -7
  685. package/src/kernel/completion/parse.ts +15 -0
  686. package/src/kernel/completion/resolve.test.ts +0 -1
  687. package/src/kernel/completion/safety.test.ts +50 -35
  688. package/src/kernel/completion/shellDrive.test.ts +28 -9
  689. package/src/kernel/completion/templates/bash.ts +7 -2
  690. package/src/kernel/completion/templates/index.ts +23 -0
  691. package/src/kernel/completion/types.ts +7 -0
  692. package/src/kernel/config/defaults.test.ts +27 -3
  693. package/src/kernel/config/defaults.ts +4 -3
  694. package/src/kernel/config/evaluateProjectConfig.ts +31 -8
  695. package/src/kernel/config/firstRun.test.ts +44 -38
  696. package/src/kernel/config/firstRun.ts +24 -88
  697. package/src/kernel/config/index.ts +1 -1
  698. package/src/kernel/config/readConfig.test.ts +6 -3
  699. package/src/kernel/config/readConfig.ts +1 -1
  700. package/src/kernel/config/schema.ts +3 -1
  701. package/src/kernel/config/types.ts +3 -1
  702. package/src/kernel/copy.test.ts +34 -4
  703. package/src/kernel/copy.ts +54 -0
  704. package/src/kernel/error/PragmaError.test.ts +5 -2
  705. package/src/kernel/error/PragmaError.ts +4 -2
  706. package/src/kernel/error/constants.ts +7 -5
  707. package/src/kernel/error/fromTaskError.ts +28 -6
  708. package/src/kernel/error/recovery.ts +14 -0
  709. package/src/kernel/error/renderError.ts +42 -1
  710. package/src/kernel/error/types.ts +21 -1
  711. package/src/kernel/index.ts +35 -0
  712. package/src/kernel/interactivity.test.ts +76 -0
  713. package/src/kernel/interactivity.ts +69 -0
  714. package/src/kernel/packs/collect.ts +12 -16
  715. package/src/kernel/packs/compile.test.ts +222 -1
  716. package/src/kernel/packs/compile.ts +93 -3
  717. package/src/kernel/packs/disclosure.ts +2 -2
  718. package/src/kernel/packs/graphql/buildLookupDocument.ts +1 -1
  719. package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +3 -4
  720. package/src/kernel/packs/graphql/index.ts +20 -0
  721. package/src/kernel/packs/index.ts +40 -0
  722. package/src/kernel/packs/iri.test.ts +73 -0
  723. package/src/kernel/packs/iri.ts +66 -14
  724. package/src/kernel/packs/renderPack.ts +25 -6
  725. package/src/kernel/packs/resolveEntity.test.ts +274 -0
  726. package/src/kernel/packs/resolveEntity.ts +200 -42
  727. package/src/kernel/packs/runBodies.ts +86 -22
  728. package/src/kernel/packs/sample.ts +1 -1
  729. package/src/kernel/packs/schema.ts +78 -5
  730. package/src/kernel/packs/sparql/applyFilters.ts +136 -16
  731. package/src/kernel/packs/sparql/buildLookupQuery.test.ts +290 -0
  732. package/src/kernel/packs/sparql/buildLookupQuery.ts +367 -17
  733. package/src/kernel/packs/sparql/index.ts +37 -0
  734. package/src/kernel/packs/sparql/runSelect.test.ts +1 -1
  735. package/src/kernel/packs/sparql/runSelect.ts +3 -4
  736. package/src/kernel/packs/toolDescription.test.ts +77 -4
  737. package/src/kernel/packs/types.ts +136 -0
  738. package/src/kernel/packs/uniqueness.ts +1 -1
  739. package/src/kernel/project/cli/buildProgram.test.ts +218 -12
  740. package/src/kernel/project/cli/buildProgram.ts +84 -18
  741. package/src/kernel/project/cli/constants.ts +34 -0
  742. package/src/kernel/project/cli/dispatch.test.ts +160 -2
  743. package/src/kernel/project/cli/dispatch.ts +226 -45
  744. package/src/kernel/project/cli/exitCodes.ts +1 -1
  745. package/src/kernel/project/cli/globalFlags.test.ts +117 -1
  746. package/src/kernel/project/cli/globalFlags.ts +134 -31
  747. package/src/kernel/project/cli/helpFormat.ts +14 -2
  748. package/src/kernel/project/cli/rootHelp.ts +74 -12
  749. package/src/kernel/project/cli/suggest.test.ts +33 -1
  750. package/src/kernel/project/cli/suggest.ts +25 -1
  751. package/src/kernel/project/cli/verbHelp.test.ts +30 -0
  752. package/src/kernel/project/cli/verbHelp.ts +23 -7
  753. package/src/kernel/project/mcp/buildServer.ts +7 -4
  754. package/src/kernel/project/mcp/envelope.ts +2 -2
  755. package/src/kernel/project/mcp/instructions.ts +2 -2
  756. package/src/kernel/project/mcp/mcpError.ts +1 -1
  757. package/src/kernel/project/mcp/parity.test.ts +5 -2
  758. package/src/kernel/project/mcp/prompts/index.ts +37 -0
  759. package/src/kernel/project/mcp/prompts/source.ts +2 -2
  760. package/src/kernel/project/mcp/registerVerb.ts +55 -10
  761. package/src/kernel/project/mcp/serve.ts +2 -2
  762. package/src/kernel/render/__snapshots__/renderers.test.ts.snap +7 -4
  763. package/src/kernel/render/contracts.ts +21 -0
  764. package/src/kernel/render/envelope.ts +2 -3
  765. package/src/kernel/render/formatters.ts +1 -1
  766. package/src/kernel/render/renderers.test.ts +243 -6
  767. package/src/kernel/render/renderers.ts +222 -20
  768. package/src/kernel/render/style.test.ts +75 -24
  769. package/src/kernel/render/style.ts +59 -6
  770. package/src/kernel/render/turtle.ts +222 -0
  771. package/src/kernel/render/vocabulary.ts +276 -0
  772. package/src/kernel/runtime/graphpack/buildIndex.ts +1 -1
  773. package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +3 -3
  774. package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
  775. package/src/kernel/runtime/graphpack/embedded.ts +3 -3
  776. package/src/kernel/runtime/graphpack/manifest.ts +1 -1
  777. package/src/kernel/runtime/graphpack/read.ts +1 -2
  778. package/src/kernel/runtime/loadSession.ts +1 -1
  779. package/src/kernel/runtime/probe.ts +6 -6
  780. package/src/kernel/runtime/readEntity.ts +472 -28
  781. package/src/kernel/runtime/refs/index.ts +39 -0
  782. package/src/kernel/runtime/refs/parseRef.ts +2 -2
  783. package/src/kernel/runtime/refs/resolve.ts +4 -4
  784. package/src/kernel/runtime/storeReadiness.ts +1 -2
  785. package/src/kernel/runtime/types.ts +15 -1
  786. package/src/kernel/runtime/wasmEmbed.test.ts +37 -39
  787. package/src/kernel/spec/emitReference.ts +105 -30
  788. package/src/kernel/spec/emitSurface.ts +48 -6
  789. package/src/kernel/spec/surfaceConformance.test.ts +4 -2
  790. package/src/kernel/spec/types.ts +277 -4
  791. package/src/testing/PARITY_GAPS.ts +9 -3
  792. package/src/testing/behavioral/docExamples.test.ts +16 -0
  793. package/src/testing/behavioral/errorMatrix.mcp.test.ts +112 -9
  794. package/src/testing/behavioral/firstRun.e2e.test.ts +24 -24
  795. package/src/testing/behavioral/journeys.cli.test.ts +1 -1
  796. package/src/testing/behavioral/journeys.defaultPack.test.ts +7 -7
  797. package/src/testing/behavioral/journeys.firstInstall.test.ts +7 -2
  798. package/src/testing/behavioral/journeys.implementation.test.ts +206 -0
  799. package/src/testing/behavioral/journeys.interactiveTty.e2e.test.ts +2 -2
  800. package/src/testing/behavioral/journeys.packageStories.test.ts +10 -7
  801. package/src/testing/behavioral/mcpServe.e2e.test.ts +57 -2
  802. package/src/testing/behavioral/mcpSurface.test.ts +1 -1
  803. package/src/testing/behavioral/rootCli.e2e.test.ts +26 -2
  804. package/src/testing/eval/__snapshots__/eval.test.ts.snap +26 -1
  805. package/src/testing/eval/cases/effectful.ts +3 -2
  806. package/src/testing/eval/cases/readNouns.ts +245 -9
  807. package/src/testing/fixtures/blockGraph.ts +104 -10
  808. package/src/testing/fixtures/graph/canonical.ts +182 -13
  809. package/src/testing/fixtures/graph/defaultPack.ts +1 -1
  810. package/src/testing/helpers/blankCanonicalRanges.ts +36 -0
  811. package/src/testing/helpers/projectMcp.ts +32 -6
  812. package/src/testing/helpers/runCli.ts +35 -18
  813. package/src/testing/perf/budgets.test.ts +20 -9
  814. package/src/testing/perf/budgets.ts +58 -9
  815. package/src/testing/perf/codegen.test.ts +126 -0
  816. package/src/testing/perf/globalSetup.test.ts +286 -0
  817. package/src/testing/perf/globalSetup.ts +505 -23
  818. package/src/testing/perf/measure.test.ts +38 -0
  819. package/src/testing/perf/measure.ts +23 -4
  820. package/src/testing/setupXdgIsolation.ts +81 -21
  821. package/src/testing/tempRoot.globalSetup.ts +122 -0
  822. package/dist/pragma +0 -0
  823. package/src/capabilities/create/compiledCreate.subprocess.test.ts +0 -189
  824. package/src/capabilities/create/templates.embedded.generated.ts +0 -28
  825. package/src/capabilities/doctor/checks/checkConfigFile.ts +0 -42
  826. package/src/capabilities/doctor/checks/checkMcpCommands.ts +0 -114
  827. package/src/capabilities/doctor/checks/checkMcpConfigured.ts +0 -68
  828. package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +0 -61
  829. package/src/capabilities/doctor/checks/deriveBand.test.ts +0 -42
  830. package/src/capabilities/doctor/checks/deriveBand.ts +0 -28
  831. package/src/capabilities/shared/bands.ts +0 -16
  832. package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +0 -11
@@ -11,7 +11,7 @@
11
11
  * other param is a kebab-cased flag.
12
12
  */
13
13
 
14
- import type { Task } from "@canonical/task";
14
+ import type { Effect, Task } from "@canonical/task";
15
15
  import type { PragmaRuntime } from "../runtime/types.js";
16
16
 
17
17
  /** MCP tool annotations mirrored onto exposed verbs. */
@@ -111,6 +111,14 @@ export type ParamSpec =
111
111
  default?: unknown;
112
112
  positional?: boolean;
113
113
  complete?: ParamComplete;
114
+ /**
115
+ * A repeatable flag ACCUMULATES: `--category css --category git` is
116
+ * the union, never last-wins (repetition is the sanctioned multi-value
117
+ * form, and silently dropping all but the last value is data loss).
118
+ * CLI-side only: the MCP arg schema keeps its scalar shape, and the
119
+ * run body accepts one value or many.
120
+ */
121
+ repeatable?: true;
114
122
  }
115
123
  | {
116
124
  kind: "enum";
@@ -121,6 +129,8 @@ export type ParamSpec =
121
129
  default?: string;
122
130
  positional?: boolean;
123
131
  complete?: ParamComplete;
132
+ /** See the string variant — repeated occurrences accumulate. */
133
+ repeatable?: true;
124
134
  }
125
135
  | {
126
136
  kind: "string[]";
@@ -131,11 +141,57 @@ export type ParamSpec =
131
141
  complete?: ParamComplete;
132
142
  };
133
143
 
134
- /** The three output modes every verb must render. */
144
+ /**
145
+ * The three output modes every verb must render.
146
+ *
147
+ * `plain` takes an optional {@link RenderContext} — the dispatcher's
148
+ * presentation facts (`--no-headers`, whether stdout is a terminal). Only
149
+ * list-shaped formatters read it; `llm` (the byte-frozen agent contract) and
150
+ * `json` (the envelope) never see it.
151
+ *
152
+ * `notice` is the seam for what the DATA cannot say about itself. Return the
153
+ * calm sentence when the payload would otherwise misrepresent the read; return
154
+ * `undefined` (or omit the member) when it speaks for itself.
155
+ *
156
+ * Two shapes qualify, and they are the same failure. A zero-record result
157
+ * ("empty ≠ silence"): an unbuilt store, a mistyped filter and a genuinely empty
158
+ * result were all `{"ok":true,"data":[],"meta":{}}`. And a result that is one of
159
+ * several it could have been — a `lookup` whose name reached more entities than
160
+ * the one it answers with. A caller shown Launchpad's `Button` has no way to
161
+ * discover the global one from a payload that looks exactly like an unambiguous
162
+ * hit; the notice names the IRIs the answer did not take, which is the only
163
+ * address that reaches them.
164
+ *
165
+ * It was called `emptyNotice` while emptiness was the only case. The channel is
166
+ * unchanged — same key, same three surfaces — so this is one seam covering both,
167
+ * not a second one grown beside it.
168
+ *
169
+ * Three surfaces route it, each in its own register — it is one seam, not a
170
+ * plain-mode courtesy:
171
+ * - `plain`: the dispatcher writes it to STDERR with exit 0, keeping the stdout
172
+ * data stream free of human sentences a pipe would read as records. `--quiet`
173
+ * mutes it (success-path guidance).
174
+ * - `--format json` AND the MCP tool result: it rides the envelope as
175
+ * `meta.notice` (`project/cli/dispatch.ts#renderData`,
176
+ * `project/mcp/registerVerb.ts#emptyMeta` — the same key from the same seam,
177
+ * so the two MACHINE surfaces stay byte-equal). `data` keeps its uniform empty
178
+ * shape; `[]` stays `[]`. Without it an agent could not tell an unbuilt store,
179
+ * a mistyped filter and a genuinely empty result apart — all three were
180
+ * `{"ok":true,"data":[],"meta":{}}`.
181
+ * - `llm` (the byte-frozen agent contract) is the ONE mode that still ignores
182
+ * it: it renders one stream and its bytes are frozen.
183
+ *
184
+ * The formatters themselves never see the notice: `json(d)` renders the data
185
+ * alone, and the ENVELOPE layer carries the notice beside it.
186
+ */
135
187
  export interface Formatters<T> {
136
- readonly plain: (d: T) => string;
188
+ readonly plain: (
189
+ d: T,
190
+ context?: import("../render/contracts.js").RenderContext,
191
+ ) => string;
137
192
  readonly llm: (d: T) => string;
138
193
  readonly json: (d: T) => string;
194
+ readonly notice?: (d: T) => string | undefined;
139
195
  }
140
196
 
141
197
  /** A usage example shown in verb help. */
@@ -176,7 +232,38 @@ export interface VerbSpec<P = Record<string, unknown>, R = unknown> {
176
232
  readonly summary: string;
177
233
  readonly doc?: string;
178
234
  readonly params: readonly ParamSpec[];
179
- readonly output: { schema?: unknown; formatters: Formatters<R> };
235
+ readonly output: {
236
+ schema?: unknown;
237
+ formatters: Formatters<R>;
238
+ /**
239
+ * OPTIONAL dry-run seam. A `--dry-run` normally renders the raw effect
240
+ * dump — one `describeEffect` bullet per effect, absolute paths repeated
241
+ * per line, interpreter internals included — which is debug material, not a
242
+ * preview a user was meant to read. A verb that has stashed structured plan
243
+ * data on the runtime (`PragmaRuntime.planData`) can render that instead.
244
+ *
245
+ * ABSENT BY DEFAULT, and absent is exactly today's render: a verb that does
246
+ * not declare this is untouched. The honest preview still runs underneath
247
+ * either way, so a dry run still fails exactly when the run would.
248
+ *
249
+ * The previewed `effects` and the run's verbosity arrive BESIDE the stashed
250
+ * data, because a plan is not always known before the Task runs: `setup`
251
+ * computes its target table up front and renders that, while `create` has
252
+ * nothing to stash — its plan IS the effects the generator produced, which
253
+ * only exist once the preview interpreter has walked the Task. One seam
254
+ * serves both by handing the renderer everything the branch knows.
255
+ *
256
+ * MAY be async: a renderer whose formatting rules live in another package
257
+ * loads them behind a dynamic `import()` rather than putting them on the
258
+ * capabilities barrel's static graph, which every `--help` and
259
+ * `__complete` spawn pays for. The kernel awaits whatever it returns.
260
+ */
261
+ formatPlan?: (
262
+ planData: unknown,
263
+ effects: readonly Effect[],
264
+ verbose: boolean,
265
+ ) => string | Promise<string>;
266
+ };
180
267
  readonly examples?: readonly Example[];
181
268
  readonly disclosure?: DisclosureSpec;
182
269
  readonly capability: Capability;
@@ -185,6 +272,52 @@ export interface VerbSpec<P = Record<string, unknown>, R = unknown> {
185
272
  readonly hidden?: boolean;
186
273
  }
187
274
 
275
+ /**
276
+ * One slice of the index a module contributes to the MCP resource listing.
277
+ *
278
+ * Deliberately the vocabulary of {@link CompletionSourceRef} — a listing and a
279
+ * completion address the same index by the same three facts (which type, which
280
+ * box, what to yield), and a second vocabulary for that would be a second
281
+ * writing of one decision. The only source a listing can read is the index, so
282
+ * `from` is implied and absent.
283
+ */
284
+ export interface McpListableRef {
285
+ /** Prefixed type filter (e.g. `ds:Component`) — empty = any type. */
286
+ readonly type?: string;
287
+ /** Restrict to schema (`tbox`) or individuals (`abox`); empty = both. */
288
+ readonly box?: "tbox" | "abox";
289
+ /**
290
+ * What the slice yields: `"collection"` lists ONE entry — the class entry
291
+ * for {@link type}, carrying its instance count — while `"entities"` lists
292
+ * every matching entity. Default `"entities"`.
293
+ */
294
+ readonly as?: "collection" | "entities";
295
+ /**
296
+ * Relative importance, 0–1 (default 1). Feeds MCP `annotations.priority` on
297
+ * the listed resource AND breaks ties in URI-completion ranking, so the two
298
+ * judgements about what matters most are ONE declaration rather than two
299
+ * constants in the kernel.
300
+ */
301
+ readonly weight?: number;
302
+ }
303
+
304
+ /**
305
+ * A module's declared contribution to the MCP resource listing.
306
+ *
307
+ * The listing is the UNION of every module's slices. It exists because
308
+ * `resources/list` has no working pagination in the SDK (the high-level
309
+ * `McpServer` list handler ignores `request.params.cursor` and never returns
310
+ * `nextCursor`), so the listing is curated rather than paged: every byte it
311
+ * spends on connect is context the agent cannot spend on the task.
312
+ *
313
+ * DERIVED wherever the module is compiled from a read story — a story already
314
+ * declares the type set it addresses (`PackLookup.type`/`types`), so its
315
+ * listing is read off that declaration, never authored a second time.
316
+ */
317
+ export interface McpListable {
318
+ readonly sources: readonly McpListableRef[];
319
+ }
320
+
188
321
  /**
189
322
  * An MCP resource provider — the ONE non-tool projection a module may add.
190
323
  *
@@ -192,11 +325,16 @@ export interface VerbSpec<P = Record<string, unknown>, R = unknown> {
192
325
  * autocomplete are storeless over the pack index; a read is store-backed and
193
326
  * shares the CLI's entity reader). Resources are NOT tools, so they never enter
194
327
  * the emitted tool surface; the projector calls this per module that declares it.
328
+ *
329
+ * `register` receives the WHOLE effective module set, not just its own module:
330
+ * the listing a provider installs is the union of every module's
331
+ * {@link McpListable}, which no single module can see.
195
332
  */
196
333
  export interface McpResourceProvider {
197
334
  readonly register: (
198
335
  server: import("@modelcontextprotocol/sdk/server/mcp.js").McpServer,
199
336
  rt: PragmaRuntime,
337
+ modules: readonly CapabilityModule[],
200
338
  ) => void;
201
339
  /**
202
340
  * A static declaration of the resource template ids this provider installs
@@ -224,6 +362,132 @@ export interface McpPromptProvider {
224
362
  ) => Promise<void> | void;
225
363
  }
226
364
 
365
+ /** A flag a mounted subcommand offers to completion (full `--token`). */
366
+ export interface CompletionChildFlag {
367
+ /** The full flag token (`--no-with-styles`). */
368
+ readonly flag: string;
369
+ /** Whether the flag consumes a value. */
370
+ readonly takesValue: boolean;
371
+ /** Closed value set for the flag's value, when one exists. */
372
+ readonly values?: readonly string[];
373
+ }
374
+
375
+ /** A positional slot a mounted subcommand offers to completion. */
376
+ export interface CompletionChildPositional {
377
+ /** The slot name (diagnostics only). */
378
+ readonly name: string;
379
+ /** Whether the positional is required. */
380
+ readonly required: boolean;
381
+ /** Closed value set (e.g. tree segments), when one exists. */
382
+ readonly values?: readonly string[];
383
+ /** True when the slot completes file paths natively. */
384
+ readonly files?: boolean;
385
+ }
386
+
387
+ /**
388
+ * The completion surface of one MOUNTED command node: its flags, its
389
+ * positional slots, and any deeper segment children — static data (it must
390
+ * pass the completion safety allowlist), never live module state.
391
+ */
392
+ export interface CompletionChildSpec {
393
+ /** The command token at this node. */
394
+ readonly label: string;
395
+ /** Flags offered at this node. */
396
+ readonly flags: readonly CompletionChildFlag[];
397
+ /** Positional slots at this node, in order. */
398
+ readonly positionals: readonly CompletionChildPositional[];
399
+ /** Deeper segment children (each with its own flags/positionals/children). */
400
+ readonly children?: readonly CompletionChildSpec[];
401
+ }
402
+
403
+ /**
404
+ * The REGISTERED CLI spelling of one mounted verb — the single syntax seam
405
+ * every kernel emitter and gate consumes: the reference emitter (usage line
406
+ * + Args/Flags tables), `emitSurface` (the covenant's mounted-noun flag and
407
+ * positional tokens, L-CIS-2), and the `docExamples` gate's valid-token
408
+ * vocabulary. A mounted tree may register a different surface than the
409
+ * binding-level params suggest (tree segments as subcommands, a
410
+ * default-true boolean registered only as its `--no-` form), and all three
411
+ * surfaces must print what the CLI actually accepts — the module supplies
412
+ * it, the kernel renders it.
413
+ */
414
+ export interface ReferenceCliSyntax {
415
+ /**
416
+ * The usage line after the bin name (e.g.
417
+ * `create application react [app-path] [options]`) — real tree segments,
418
+ * the registered positional token.
419
+ */
420
+ readonly usage: string;
421
+ /**
422
+ * The registered flag token per binding-level param name (e.g.
423
+ * `withStyles` → `--no-with-styles`). A param absent here renders with the
424
+ * default `--<kebab-name>` derivation.
425
+ */
426
+ readonly flagTokens: Readonly<Record<string, string>>;
427
+ /**
428
+ * The registered positional token per binding-level param name (e.g.
429
+ * `componentPath` → `[component-path]`) — the SAME token the usage line
430
+ * carries, so the Arguments table never contradicts its own synopsis. A
431
+ * param absent here renders with the default `<name>`/`[name]` derivation.
432
+ */
433
+ readonly positionalTokens?: Readonly<Record<string, string>>;
434
+ }
435
+
436
+ /** What the program hands a module mounting its own subtree. */
437
+ export interface CliMountHost {
438
+ /** Global flags for this invocation (closed over by mounted actions). */
439
+ readonly globalFlags: import("../runtime/types.js").GlobalFlags;
440
+ /** The binary name (for messages the mounted tree prints). */
441
+ readonly programName: string;
442
+ }
443
+
444
+ /**
445
+ * A module-level CLI projection hook (precedented by `mcpResources`/
446
+ * `mcpPrompts`/`colophon` — module metadata, NOT a `VerbSpec` field, zero
447
+ * covenant impact): the module MOUNTS its noun's subtree onto the Commander
448
+ * parent itself, instead of the generic per-verb attachment. The module's
449
+ * verbs remain the binding-level grammar (surface, MCP, reference,
450
+ * completion labels); the mount owns everything beneath the noun.
451
+ */
452
+ export interface CliProjection {
453
+ /**
454
+ * Load the mount's registration machinery, when it is deferred. The
455
+ * projection hook rides the capabilities barrel, which `--help` and
456
+ * `__complete` import on every spawn — so a mount whose registration needs
457
+ * heavy modules (a Commander adapter, shared decision logic) keeps them
458
+ * behind this async step instead of a static import, and only the one
459
+ * caller that actually builds the command tree (the bin, before
460
+ * `buildProgram`) awaits it. {@link mount} stays synchronous and throws
461
+ * when invoked unprepared, so a future caller cannot silently skip the
462
+ * step.
463
+ */
464
+ readonly prepare?: () => Promise<void>;
465
+ /** Populate this module's noun parent with its subcommands. */
466
+ readonly mount: (
467
+ parent: import("commander").Command,
468
+ host: CliMountHost,
469
+ ) => void;
470
+ /**
471
+ * The completion surface of the mounted tree, keyed by verb label —
472
+ * static data the completion model attaches as segment children.
473
+ */
474
+ readonly completionChildren: () => Readonly<
475
+ Record<string, CompletionChildSpec>
476
+ >;
477
+ /** Markdown inserted under the noun's heading in the generated reference. */
478
+ readonly referenceIntro?: string;
479
+ /**
480
+ * The registered CLI syntax for one of the noun's binding verbs — the
481
+ * MOUNTED spelling the reference must print (usage line with tree
482
+ * segments, flag tokens the CLI actually registers) instead of deriving
483
+ * tokens from binding-level param names the mounted tree may not register.
484
+ * Return `undefined` to keep the default rendering for that verb.
485
+ */
486
+ readonly referenceSyntax?: (
487
+ verbPath: VerbSpec["path"],
488
+ ) => ReferenceCliSyntax | undefined;
489
+ }
490
+
227
491
  /** A capability module: a named bundle of verbs with optional boot/resources/prompts hooks. */
228
492
  export interface CapabilityModule {
229
493
  readonly name: string;
@@ -248,6 +512,15 @@ export interface CapabilityModule {
248
512
  readonly boot?: (rt: PragmaRuntime) => void;
249
513
  /** An optional MCP resource surface (NOT a VerbSpec field — a module hook). */
250
514
  readonly mcpResources?: McpResourceProvider;
515
+ /**
516
+ * The slices of the index this module contributes to the MCP resource
517
+ * listing (NOT a VerbSpec field — a module hook, like `mcpResources`). A
518
+ * story-compiled module gets it DERIVED from its lookup's declared types;
519
+ * only an authored module declares it by hand.
520
+ */
521
+ readonly mcpListable?: McpListable;
251
522
  /** An optional MCP prompt surface (NOT a VerbSpec field — a module hook). */
252
523
  readonly mcpPrompts?: McpPromptProvider;
524
+ /** An optional CLI mount for the module's noun (NOT a VerbSpec field). */
525
+ readonly cliProjection?: CliProjection;
253
526
  }
@@ -42,13 +42,13 @@ export const PARITY_GAPS: readonly ParityGapEntry[] = [
42
42
  id: "read-meta-always-empty",
43
43
  area: "envelope",
44
44
  description:
45
- "`dispatch.ts#executeVerb`'s read branch always renders with `meta: {}` — there is no `meta.count`/`meta.total` field on a list/lookup envelope (verified empirically). An empty (possibly filtered) list is `{ok:true, data:[], meta:{}}`; the only way to know it's empty is `data.length === 0`, not a meta field.",
45
+ "NARROWED: a read envelope still carries no `meta.count`/`meta.total` — the only way to know a list is empty is `data.length === 0`, not a count field. But `meta` is no longer ALWAYS `{}` on a read. A zero-record read now carries the verb's own `notice` as `meta.notice` on BOTH machine surfaces (`project/cli/dispatch.ts#renderData` for `--format json`, `project/mcp/registerVerb.ts#emptyMeta` for MCP — one seam, the same key, so the two stay byte-equal). `data` keeps its uniform empty shape; `[]` is still `[]`. The divergence this entry records is the ABSENCE of counts, not the emptiness of `meta`: without the notice an agent could not tell an unbuilt store, a mistyped filter and a genuinely empty result apart, all three being `{ok:true,data:[],meta:{}}`.",
46
46
  },
47
47
  {
48
48
  id: "no-empty-hook-on-free-filter",
49
49
  area: "pack list / empty-state",
50
50
  description:
51
- "A zero-row pack list — whether narrowed by a declared filter, an unmatched `--search`, or unconditionally empty — returns `ok:true, data:[], meta:{}` at exit 0 with a calm `emptyMessage`/`emptyHint`; pragma v2 never raises a typed EMPTY_RESULTS error for an empty list. (U5 removed the former enum-filter-only `buildListEmptyError` hook, making the empty-state uniform across every list verb.)",
51
+ "STILL TRUE OF EMPTINESS, NARROWED ON BAD ARGUMENTS. A zero-row pack list — narrowed by a declared filter, by an unmatched `--search`, or unconditionally empty — is a SUCCESS: `ok:true, data:[]` at exit 0 with a calm notice (stderr in plain mode, `meta.notice` on the machine surfaces). pragma v2 still never raises EMPTY_RESULTS for an empty list, and U5's removal of the enum-filter-only `buildListEmptyError` hook stands. What is no longer true is that an UNMATCHED free-filter value stays successful: a value-free filter now rejects a value its vocabulary does not admit with INVALID_INPUT and the admissible values as `validOptions`, the same courtesy a declared-`values` filter always extended (`packs/sparql/applyFilters.ts`). The vocabulary is the graph's, not the returned rows' — a filter declares where it lives (`PackFilter.vocabulary`), so a real value that happens to match no row (a category with zero standards, a `ds:ConceptType` no concept uses) is a calm empty list, and only a value the graph does not know is an error.",
52
52
  },
53
53
  {
54
54
  id: "raw-iri-in-data",
@@ -84,7 +84,7 @@ export const PARITY_GAPS: readonly ParityGapEntry[] = [
84
84
  id: "block-lookup-not-tier-scoped",
85
85
  area: "block",
86
86
  description:
87
- "`block lookup` resolves by `ds:name` GLOBALLY, with no tier or channel filtering. A same-named block declared at two tiers cannot be disambiguated by plain name (the old shell's tier-scoped lookup disambiguation has no v2 equivalent) — address it by prefixed IRI instead. Since L-OPEN-9 NOTHING is tier/channel-aware: the hand-written, tier-chain-filtered `block list` was removed with its `tierChain.ts`.",
87
+ "CLOSED, by REVERSAL of the entry it used to be. This gap read: `block lookup` resolves by `ds:name` globally, a same-named block at two tiers cannot be disambiguated by plain name, address it by prefixed IRI instead. That was accepted while the answer was merely arbitrary; it stopped being acceptable once measured — 25 live block names are carried by 2–3 blocks, and EVERY one of them was answered with whichever IRI sorted first and no sign the others existed (`block lookup button` returned Launchpad's Button, because `apps_launchpad…` precedes `global…`). 'Address it by IRI' is not a recovery an agent can reach when nothing tells it there is a second block to address. Two things replace it, and neither is a change of arity — one name still answers with one entity, and a glob is still the declared multi-entity form. (1) The discard is no longer SILENT: the resolve is unlimited, the winner is answered with, and the IRIs it outranked ride the verb's `notice` — the same seam a zero-record read uses (stderr in plain mode, `meta.notice` on `--format json` and MCP), because an ambiguous hit is the same failure as an empty one, a result that misrepresents itself. `LookupOutput.ambiguous` carries them in `data` for the machine surfaces, and is ABSENT (not `[]`) when nothing was ambiguous, so every unambiguous read keeps the payload it had. Note the recovery is not reachable any other way: a glob expands over DISTINCT names, so `block lookup 'Butt*'` returned Launchpad's Button and ButtonLink and the global Button appeared nowhere. (2) The order is a declared, derived RANKING (`PackLookup.scopeWeight` in `pragma.conf.ts`, generated by `packs/sparql/buildLookupQuery.ts#rankingClause`): a tier's depth comes from the `/` count in its OWN `ds:name` (`\"Apps/Launchpad\"` → 2, never from the `_` in `ds:apps_launchpad`), and it MULTIPLIES the existing type weight rather than tiebreaking above it, so a whole component in a nested tier still outranks a global SUBcomponent (`TextInput`). Nothing is enumerated, so a tier added upstream is placed without an edit here; an asserted `ds:tierRank` would take precedence over the derived depth and retire the config declaration with no code change. WHAT REMAINS a gap: `lookup` is still not tier-SCOPED — there is no way to ask for one tier's answer only, the ranking merely decides which comes first — and since L-OPEN-9 nothing is tier/channel-FILTERED (the hand-written `block list` went with its `tierChain.ts`; see `block-list-unfiltered`). Two top-level tiers still cannot be ordered against each other by depth alone, which today leaves `Navigation` (`global` vs `apps`) and `InfoTable` (`global` vs `sites`) decided by the IRI fallback; naming a precedence among the depth-1 tiers is an ontology question, deliberately NOT invented here.",
88
88
  },
89
89
  {
90
90
  id: "block-list-unfiltered",
@@ -182,4 +182,10 @@ export const PARITY_GAPS: readonly ParityGapEntry[] = [
182
182
  description:
183
183
  "The native MCP `prompts/list` (and the `prompt_list`/`prompt_lookup` content tools) project `ds:Prompt` KG entities read from the ACTIVE pack index (`kernel/project/mcp/prompts/source.ts#listPromptSummaries`) — project-supplied data, NOT shipped in the embedded/bundled pack. A bare install (no project-authored `ds:Prompt`) advertises the prompts capability but lists ZERO prompts, never booting the store on the list path. Non-empty listings are exercised only against the seeded fixture graph (`testing/fixtures/graph/canonical.ts`); the storeless empty-by-default case is pinned by `prompts.test.ts` ('lists zero prompts … when no prompt entities exist').",
184
184
  },
185
+ {
186
+ id: "scope-not-band-in-machine-output",
187
+ area: "setup / doctor `--format json`",
188
+ description:
189
+ "A setup plan row and a doctor check carry their config scope under the key `scope` (values `global`/`project`), not `band`. The old shell's type layer said `band` (`ScopeBand`, `PlanRow.band`, `CheckResult.band`) while every user-facing string had already moved to the scope vocabulary the `--global`/`--local` flags use; the type-layer rename (kernel/render/vocabulary.ts) finished the move, and `--format json`/MCP emit the model verbatim, so the machine key moved with it. Any consumer reading `.band` off `setup --format json` or `doctor --format json` reads `.scope` now — `setup.render.test.ts` pins that neither spelling of `band` can return through any render, JSON included.",
190
+ },
185
191
  ] as const;
@@ -45,6 +45,8 @@ function readDoc(relPath: string): string {
45
45
  const HAND_WRITTEN_DOCS = [
46
46
  "../../../README.md",
47
47
  "../../../docs/getting-started.md",
48
+ "../../../docs/design-system.md",
49
+ "../../../docs/setup.md",
48
50
  "../../../docs/mcp-integration.md",
49
51
  "../../../docs/config-model.md",
50
52
  "../../../docs/architecture.md",
@@ -161,7 +163,21 @@ const READ_CASES: readonly ReadCase[] = [
161
163
  params: { name: ["Button"] },
162
164
  },
163
165
  { command: "pragma standard list", key: "standard list", params: {} },
166
+ {
167
+ // The doc's headline example, and the one the roll-up is about: a parent
168
+ // category answering for its whole branch.
169
+ command: "pragma standard list --category testing",
170
+ key: "standard list",
171
+ params: { category: ["testing"] },
172
+ },
173
+ {
174
+ command: "pragma standard categories",
175
+ key: "standard categories",
176
+ params: {},
177
+ },
178
+ { command: "pragma modifier list", key: "modifier list", params: {} },
164
179
  { command: "pragma token list", key: "token list", params: {} },
180
+ { command: "pragma prompt list", key: "prompt list", params: {} },
165
181
  { command: "pragma tier list", key: "tier list", params: {} },
166
182
  { command: "pragma ontology list", key: "ontology list", params: {} },
167
183
  { command: "pragma config show", key: "config show", params: {} },
@@ -11,10 +11,16 @@
11
11
  * a total miss; only a PARTIAL batch reports the miss while staying
12
12
  * `ok:true` (that shape is B1's job, `agentSession.mcp.test.ts`). See
13
13
  * PARITY_GAPS `single-lookup-miss-fails-batch-partial-reports`.
14
- * 2. A filtered list narrowed to zero rows is `{ok:true, data:[], meta:{}}` —
15
- * there is no `meta.count` field on any read envelope (`dispatch.ts`
16
- * always renders reads with `meta:{}`). See PARITY_GAPS
17
- * `read-meta-always-empty`.
14
+ * 2. A filtered list narrowed to zero rows is `{ok:true, data:[]}` — there is
15
+ * still no `meta.count` field on any read envelope, which is the divergence
16
+ * `read-meta-always-empty` now records (it no longer claims `meta` is always
17
+ * `{}`: a zero-record read carries the list's own `notice` as
18
+ * `meta.notice` on both machine surfaces, asserted below).
19
+ * 3. A value-free filter given a value its vocabulary does not admit is
20
+ * INVALID_INPUT, not a successful empty list — the narrowing recorded in
21
+ * PARITY_GAPS `no-empty-hook-on-free-filter`. Emptiness itself is still a
22
+ * success: a value the GRAPH admits but no row carries (a category with zero
23
+ * standards) is a calm empty list, asserted below.
18
24
  */
19
25
 
20
26
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
@@ -88,7 +94,22 @@ describe("lookup miss — total miss fails the call (B3, adapted)", () => {
88
94
  });
89
95
  });
90
96
 
91
- describe("list — a narrowing filter to zero rows is a plain empty list (B3, adapted)", () => {
97
+ /**
98
+ * CHANGED DELIBERATELY. This used to assert that ANY filter value narrowed to a
99
+ * plain `{"ok":true,"data":[],"meta":{}}`, which was written when no value-free
100
+ * filter could tell a typo from an empty answer. It could: the rows it is
101
+ * filtering carry the vocabulary. Over MCP the old shape made a mistyped
102
+ * `--category`, an unbuilt store and a genuinely empty category byte-identical —
103
+ * the silence a model has no way to recover from.
104
+ *
105
+ * A value the graph does not know is now INVALID_INPUT with the admissible
106
+ * values as `validOptions`, exactly as a filter declaring `values` has always
107
+ * behaved; the difference is that the vocabulary is READ FROM THE GRAPH rather
108
+ * than copied into the story. Zero rows for a value that DOES exist stays a calm
109
+ * empty list — that is a real answer, not a bad argument — and "exists" means
110
+ * the graph declares it, not that some returned row happened to carry it.
111
+ */
112
+ describe("list — a filter value the graph does not carry is INVALID_INPUT (B3, adapted)", () => {
92
113
  it("has at least one filtered list verb to sweep", () => {
93
114
  // A guard, not a no-op: if this ever goes empty the sweep below silently
94
115
  // covers nothing, which would be a silent coverage loss worth noticing.
@@ -97,22 +118,104 @@ describe("list — a narrowing filter to zero rows is a plain empty list (B3, ad
97
118
 
98
119
  it.each(
99
120
  filteredListVerbs,
100
- )("$tool: an unmatched filter value narrows to [] (no EMPTY_RESULTS)", async ({
121
+ )("$tool: an unobserved filter value is rejected, naming the observed ones", async ({
101
122
  tool,
102
123
  param,
103
124
  }) => {
104
125
  const result = await mcp.callTool(tool, {
105
126
  [param]: "zzz-definitely-not-a-real-value",
106
127
  });
128
+ expect(result.ok).toBe(false);
129
+ const error = result.error as { code: string; validOptions?: string[] };
130
+ expect(error.code).toBe("INVALID_INPUT");
131
+ expect(error.validOptions?.length).toBeGreaterThan(0);
132
+ expect(error.validOptions).not.toContain("zzz-definitely-not-a-real-value");
133
+ });
134
+
135
+ it.each(
136
+ filteredListVerbs,
137
+ )("$tool: every value the graph DOES carry narrows to a calm list", async ({
138
+ tool,
139
+ param,
140
+ }) => {
141
+ const rejected = await mcp.callTool(tool, { [param]: "zzz-nope" });
142
+ const admissible = (rejected.error as { validOptions: string[] })
143
+ .validOptions;
144
+ expect(admissible.length).toBeGreaterThan(0);
145
+ // EVERY admissible value is accepted, and at least one is populated. Not
146
+ // "the first one returns rows": the vocabulary is the graph's, so it can
147
+ // legitimately contain a value no row carries (a category with zero
148
+ // standards) — that value is a calm empty list, not a rejection, and the
149
+ // sweep would otherwise read a real answer as a failure.
150
+ let populated = 0;
151
+ for (const value of admissible) {
152
+ const result = await mcp.callTool(tool, { [param]: value });
153
+ expect(result.ok).toBe(true);
154
+ if ((result.data as unknown[]).length > 0) populated += 1;
155
+ }
156
+ expect(populated).toBeGreaterThan(0);
157
+ });
158
+
159
+ it("standard_list: a declared category with NO standards is a calm empty list", async () => {
160
+ // The case that separates "the graph is the vocabulary" from "the returned
161
+ // rows are the vocabulary". `standard_categories` publishes every declared
162
+ // slug with its count, zeros included, and tells the agent to pick one —
163
+ // so rejecting a zero-count slug as INVALID_INPUT tells it the slug the
164
+ // tool just handed it was a typo. Validity read off the rows did exactly
165
+ // that, because a category with no standards appears in no row.
166
+ const categories = await mcp.callTool("standard_categories");
167
+ const zero = (categories.data as { name: string; count: string }[]).filter(
168
+ (row) => Number(row.count) === 0,
169
+ );
170
+ expect(zero.length).toBeGreaterThan(0);
171
+ for (const row of zero) {
172
+ const result = await mcp.callTool("standard_list", {
173
+ category: row.name,
174
+ });
175
+ expect(result.ok).toBe(true);
176
+ expect(result.data).toEqual([]);
177
+ // And it is a real empty answer, so it carries the calm notice rather
178
+ // than passing in silence.
179
+ expect((result.meta as { notice?: string }).notice ?? "").not.toBe("");
180
+ }
181
+ });
182
+
183
+ it("standard_list: the rejection names the declared slugs, not just the used ones", async () => {
184
+ const result = await mcp.callTool("standard_list", {
185
+ category: "zzz-definitely-not-a-slug",
186
+ });
187
+ expect(result.ok).toBe(false);
188
+ const error = result.error as { code: string; validOptions: string[] };
189
+ expect(error.code).toBe("INVALID_INPUT");
190
+ const categories = await mcp.callTool("standard_categories");
191
+ const declared = (categories.data as { name: string }[]).map((r) => r.name);
192
+ // Same vocabulary, both surfaces: whatever `standard_categories` lists is
193
+ // what `--category` accepts. Read from `cs:Category`/`cs:slug` on both
194
+ // sides, so the two cannot drift.
195
+ expect([...error.validOptions].sort()).toEqual([...declared].sort());
196
+ });
197
+ });
198
+
199
+ describe("empty ≠ silence on the machine surfaces", () => {
200
+ it("carries the list's empty-state guidance in the envelope meta", async () => {
201
+ // `notice` had exactly one consumer — the CLI dispatcher's stderr — so
202
+ // an agent received `{"ok":true,"data":[],"meta":{}}` and nothing else. The
203
+ // search path is the honest way to reach an empty list without a bad
204
+ // argument.
205
+ const result = await mcp.callTool("standard_list", {
206
+ search: "zzz-nothing-matches-this",
207
+ });
107
208
  expect(result.ok).toBe(true);
108
209
  expect(result.data).toEqual([]);
109
- expect(result.meta).toEqual({});
210
+ const notice = (result.meta as { notice?: string }).notice ?? "";
211
+ expect(notice).toContain("No standard entries found.");
212
+ expect(notice).toContain("pragma standard categories");
110
213
  });
111
214
  });
112
215
 
113
- describe("ontology_show — an unknown prefix is INVALID_INPUT (B3)", () => {
216
+ describe("ontology_lookup — an unknown prefix is INVALID_INPUT (B3)", () => {
114
217
  it("fails with the enumerated valid prefixes", async () => {
115
- const result = await mcp.callTool("ontology_show", { prefix: "nope" });
218
+ const result = await mcp.callTool("ontology_lookup", { prefix: "nope" });
116
219
  expect(result.ok).toBe(false);
117
220
  const error = result.error as { code: string; validOptions: string[] };
118
221
  expect(error.code).toBe("INVALID_INPUT");
@@ -1,40 +1,40 @@
1
1
  /**
2
- * A1 — first-run onboarding, observed through the real compiled binary.
2
+ * First-run onboarding, observed through the real shipped entry.
3
3
  *
4
- * Unit mechanics (`ensureFirstRun`/`firstRunTask`) are PR1-protected
5
- * (`kernel/config/firstRun.test.ts`); this is the e2e pin: a fresh XDG config
6
- * home produces the greeting on STDERR (never stdout — command output must stay
7
- * uncorrupted), seeds `config.json`, and a second run is silent.
4
+ * The contract inverted: onboarding no longer WRITES. A read-only command must
5
+ * leave the config home empty, and the un-set-up hint belongs on the read-only
6
+ * front door — where the machine's state is discovered by looking, not by
7
+ * seeding a file and a marker ahead of any consent.
8
8
  */
9
9
 
10
- import { existsSync, readFileSync } from "node:fs";
10
+ import { existsSync } from "node:fs";
11
11
  import { join } from "node:path";
12
12
  import { describe, expect, it } from "vitest";
13
13
  import { freshXdgEnv, runCli } from "../helpers/runCli.js";
14
14
 
15
- describe("first-run onboarding (A1, e2e)", () => {
16
- it("greets on stderr, seeds config.json, and stays silent on the second run", () => {
15
+ describe("first-run onboarding (e2e)", () => {
16
+ it("hints on the front door and seeds nothing", () => {
17
17
  const env = freshXdgEnv();
18
18
  const configPath = join(env.XDG_CONFIG_HOME, "pragma", "config.json");
19
19
 
20
- const first = runCli(["info"], {
20
+ // A read-only command writes NO config and carries no banner: the greeting
21
+ // used to interleave itself into the output of unrelated runs.
22
+ const read = runCli(["info"], {
21
23
  env: { ...env, PRAGMA_NO_AUTO_LLM: "1" },
22
24
  });
23
- expect(first.exitCode).toBe(0);
24
- expect(first.stderr).toContain("Hello!");
25
- expect(first.stderr).toContain("pre-release");
26
- expect(first.stderr).toContain(configPath);
27
- // Command output stays on stdout, untouched by the greeting.
28
- expect(first.stdout).not.toContain("Hello!");
29
- expect(first.stdout).toContain("pragma v");
25
+ expect(read.exitCode).toBe(0);
26
+ expect(read.stdout).toContain("pragma v");
27
+ expect(read.stderr).not.toContain("pre-release");
28
+ expect(existsSync(configPath)).toBe(false);
30
29
 
31
- expect(existsSync(configPath)).toBe(true);
32
- expect(readFileSync(configPath, "utf-8")).toBe("{}\n");
33
-
34
- const second = runCli(["info"], {
35
- env: { ...env, PRAGMA_NO_AUTO_LLM: "1" },
36
- });
37
- expect(second.exitCode).toBe(0);
38
- expect(second.stderr).toBe("");
30
+ // The front door is a read, so it is where the hint belongs — on stderr,
31
+ // leaving the front door's own output uncorrupted on stdout.
32
+ const door = runCli([], { env: { ...env, PRAGMA_NO_AUTO_LLM: "1" } });
33
+ expect(door.exitCode).toBe(0);
34
+ expect(door.stderr).toContain("pre-release");
35
+ expect(door.stderr).toContain("pragma setup");
36
+ expect(door.stdout).not.toContain("pre-release");
37
+ // Still nothing written: the hint is a probe, not a seed.
38
+ expect(existsSync(configPath)).toBe(false);
39
39
  });
40
40
  });
@@ -4,7 +4,7 @@
4
4
  * BACKING ADAPTATION: the plan lists this as "fixture + spawn"; the PR4 quality
5
5
  * bar (R7 — keep the spawn-e2e layer to exactly A1-A4/A7) overrides that, so
6
6
  * this drives `block list` through the REAL CLI dispatch path (`executeVerb`,
7
- * the same function the compiled binary's `dispatch()` calls) IN-PROCESS
7
+ * the same function the shipped entry's `dispatch()` calls) IN-PROCESS
8
8
  * against the fixture, rather than spawning. It still exercises the true CLI
9
9
  * seam (typed params -> dispatch -> render), just without forking a process.
10
10
  *