@canonical/pragma-cli 0.29.0 → 0.31.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 (410) hide show
  1. package/README.md +128 -47
  2. package/dist/pragma +0 -0
  3. package/package.json +15 -13
  4. package/src/completions/constants.ts +7 -0
  5. package/src/completions/handleQuery.test.ts +32 -0
  6. package/src/completions/handleQuery.ts +20 -1
  7. package/src/completions/queryCompletions.test.ts +5 -0
  8. package/src/completions/queryCompletions.ts +17 -3
  9. package/src/completions/querySocket.test.ts +31 -0
  10. package/src/completions/querySocket.ts +36 -9
  11. package/src/config/defaultConfig.test.ts +33 -0
  12. package/src/config/defaultConfig.ts +59 -0
  13. package/src/config/defaults.json +17 -0
  14. package/src/config/findProjectConfigPath.test.ts +53 -0
  15. package/src/config/findProjectConfigPath.ts +36 -0
  16. package/src/config/index.ts +17 -2
  17. package/src/config/mergeConfigFileUpdate.ts +58 -0
  18. package/src/config/parseConfigValues.ts +217 -0
  19. package/src/config/readConfig.test.ts +104 -13
  20. package/src/config/readConfig.ts +12 -153
  21. package/src/config/readConfigLayers.test.ts +109 -0
  22. package/src/config/readConfigLayers.ts +118 -0
  23. package/src/config/resolveGlobalConfigPath.ts +13 -0
  24. package/src/config/resolveWriteConfigPath.test.ts +53 -0
  25. package/src/config/resolveWriteConfigPath.ts +31 -0
  26. package/src/config/types.ts +83 -1
  27. package/src/config/writeConfig.ts +25 -55
  28. package/src/constants.ts +3 -1
  29. package/src/domains/block/commands/list.ts +5 -90
  30. package/src/domains/block/commands/lookup.ts +8 -167
  31. package/src/domains/block/commands/sample.ts +2 -1
  32. package/src/domains/block/formatters/list.test.ts +3 -3
  33. package/src/domains/block/formatters/lookup.test.ts +5 -5
  34. package/src/domains/block/mcp/specs.ts +16 -196
  35. package/src/domains/block/orchestration/enrichBlocks.ts +6 -3
  36. package/src/domains/block/orchestration/resolveBlockLookup.ts +2 -1
  37. package/src/domains/block/stories.test.ts +28 -0
  38. package/src/domains/block/stories.ts +260 -0
  39. package/src/domains/config/commands/channel.test.ts +30 -3
  40. package/src/domains/config/commands/channel.ts +25 -8
  41. package/src/domains/config/commands/configScope.ts +46 -0
  42. package/src/domains/config/commands/framework.test.ts +32 -1
  43. package/src/domains/config/commands/framework.ts +26 -8
  44. package/src/domains/config/commands/show.ts +5 -45
  45. package/src/domains/config/commands/tier.test.ts +20 -2
  46. package/src/domains/config/commands/tier.ts +25 -8
  47. package/src/domains/config/commands/trace.test.ts +19 -2
  48. package/src/domains/config/commands/trace.ts +6 -3
  49. package/src/domains/config/formatters/channel.test.ts +20 -6
  50. package/src/domains/config/formatters/channel.ts +14 -11
  51. package/src/domains/config/formatters/framework.ts +14 -11
  52. package/src/domains/config/formatters/show.test.ts +27 -0
  53. package/src/domains/config/formatters/show.ts +27 -4
  54. package/src/domains/config/formatters/tier.test.ts +26 -10
  55. package/src/domains/config/formatters/tier.ts +19 -11
  56. package/src/domains/config/formatters/trace.ts +7 -7
  57. package/src/domains/config/mcp/specs.ts +33 -53
  58. package/src/domains/config/operations/show.test.ts +18 -0
  59. package/src/domains/config/operations/show.ts +7 -1
  60. package/src/domains/config/operations/types.ts +7 -0
  61. package/src/domains/config/operations/validateTier.test.ts +9 -0
  62. package/src/domains/config/operations/validateTier.ts +10 -2
  63. package/src/domains/config/stories.ts +42 -0
  64. package/src/domains/config/tasks/index.ts +1 -0
  65. package/src/domains/config/tasks/setChannel.ts +13 -28
  66. package/src/domains/config/tasks/setFramework.ts +11 -30
  67. package/src/domains/config/tasks/setTier.ts +10 -29
  68. package/src/domains/config/tasks/setTrace.ts +10 -28
  69. package/src/domains/config/tasks/writeConfigField.ts +41 -0
  70. package/src/domains/create/generatorPack/bundled.ts +49 -0
  71. package/src/domains/create/generatorPack/compileGeneratorPack.test.ts +159 -0
  72. package/src/domains/create/generatorPack/compileGeneratorPack.ts +312 -0
  73. package/src/domains/create/index.ts +13 -7
  74. package/src/domains/create/mcp/specs.ts +6 -161
  75. package/src/domains/create/renderGeneratorUi.test.ts +103 -0
  76. package/src/domains/create/renderGeneratorUi.ts +65 -0
  77. package/src/domains/doctor/formatters/doctor.test.ts +50 -2
  78. package/src/domains/doctor/formatters/doctor.ts +90 -38
  79. package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
  80. package/src/domains/doctor/operations/checks/checkMcpCommands.ts +133 -0
  81. package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
  82. package/src/domains/doctor/operations/checks/checkPackageRefs.ts +32 -26
  83. package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +1 -1
  84. package/src/domains/doctor/operations/checks/index.ts +1 -0
  85. package/src/domains/doctor/operations/checks.test.ts +160 -7
  86. package/src/domains/doctor/operations/runChecks.test.ts +15 -6
  87. package/src/domains/doctor/operations/runChecks.ts +2 -0
  88. package/src/domains/doctor/operations/types.ts +23 -1
  89. package/src/domains/graph/commands/inspect.test.ts +2 -2
  90. package/src/domains/graph/commands/query.test.ts +5 -3
  91. package/src/domains/graph/formatters/inspect.ts +7 -7
  92. package/src/domains/graph/formatters/query.test.ts +87 -0
  93. package/src/domains/graph/formatters/query.ts +42 -5
  94. package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
  95. package/src/domains/graph/helpers/resolveUri.ts +28 -21
  96. package/src/domains/graph/operations/inspectUri.test.ts +5 -5
  97. package/src/domains/graphql/commands/build.test.ts +5 -3
  98. package/src/domains/graphql/commands/build.ts +8 -16
  99. package/src/domains/graphql/commands/check.test.ts +5 -3
  100. package/src/domains/graphql/commands/check.ts +7 -13
  101. package/src/domains/graphql/commands/index.ts +1 -0
  102. package/src/domains/graphql/commands/serve.test.ts +46 -0
  103. package/src/domains/graphql/commands/serve.ts +141 -0
  104. package/src/domains/graphql/constants.ts +10 -0
  105. package/src/domains/graphql/helpers/gatherSources.test.ts +92 -0
  106. package/src/domains/graphql/helpers/gatherSources.ts +58 -0
  107. package/src/domains/graphql/helpers/index.ts +2 -0
  108. package/src/domains/graphql/helpers/parsePrefixes.test.ts +3 -3
  109. package/src/domains/graphql/helpers/parsePrefixes.ts +3 -3
  110. package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +9 -0
  111. package/src/domains/graphql/helpers/resolveSourceFiles.ts +24 -3
  112. package/src/domains/graphql/helpers/routeGraphql.test.ts +43 -0
  113. package/src/domains/graphql/helpers/routeGraphql.ts +28 -0
  114. package/src/domains/graphql/index.ts +9 -6
  115. package/src/domains/graphql/operations/compileSchema.test.ts +23 -47
  116. package/src/domains/graphql/operations/compileSchema.ts +23 -25
  117. package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
  118. package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
  119. package/src/domains/graphql/operations/ensureSchemaArtifact.test.ts +167 -0
  120. package/src/domains/graphql/operations/ensureSchemaArtifact.ts +178 -0
  121. package/src/domains/graphql/operations/index.ts +10 -0
  122. package/src/domains/info/formatters/upgrade.test.ts +7 -4
  123. package/src/domains/info/formatters/upgrade.ts +3 -1
  124. package/src/domains/info/operations/collectEntityCounts.test.ts +156 -0
  125. package/src/domains/info/operations/collectEntityCounts.ts +123 -0
  126. package/src/domains/info/operations/collectInfo.test.ts +14 -3
  127. package/src/domains/info/operations/collectInfo.ts +12 -15
  128. package/src/domains/info/operations/index.ts +1 -0
  129. package/src/domains/info/types.ts +13 -0
  130. package/src/domains/llm/capabilities.test.ts +24 -4
  131. package/src/domains/llm/commands/capabilities.ts +12 -3
  132. package/src/domains/llm/commands/llm.ts +5 -1
  133. package/src/domains/llm/data/commandReference.ts +20 -11
  134. package/src/domains/llm/data/decisionTrees.ts +10 -5
  135. package/src/domains/llm/data/toolCatalog.ts +55 -18
  136. package/src/domains/llm/formatters/orientation.ts +5 -1
  137. package/src/domains/llm/llmCommand.test.ts +11 -3
  138. package/src/domains/llm/mcp/specs.ts +3 -4
  139. package/src/domains/llm/operations/collectContext.test.ts +64 -0
  140. package/src/domains/llm/operations/collectContext.ts +7 -17
  141. package/src/domains/modifier/commands/list.ts +5 -38
  142. package/src/domains/modifier/commands/lookup.ts +8 -79
  143. package/src/domains/modifier/commands/sample.ts +2 -1
  144. package/src/domains/modifier/mcp/specs.ts +15 -94
  145. package/src/domains/modifier/operations/lookup.ts +5 -3
  146. package/src/domains/modifier/orchestration/resolveModifierLookup.ts +2 -1
  147. package/src/domains/modifier/stories.test.ts +20 -0
  148. package/src/domains/modifier/stories.ts +86 -0
  149. package/src/domains/ontology/commands/list.test.ts +5 -3
  150. package/src/domains/ontology/commands/list.ts +5 -58
  151. package/src/domains/ontology/commands/show.test.ts +85 -9
  152. package/src/domains/ontology/commands/show.ts +6 -58
  153. package/src/domains/ontology/formatters/index.ts +1 -0
  154. package/src/domains/ontology/formatters/list.ts +37 -12
  155. package/src/domains/ontology/formatters/show.ts +361 -64
  156. package/src/domains/ontology/helpers/buildClassTree.ts +89 -0
  157. package/src/domains/ontology/helpers/completeClassNames.ts +43 -0
  158. package/src/domains/ontology/helpers/expandOntologyIris.ts +79 -0
  159. package/src/domains/ontology/helpers/index.ts +14 -0
  160. package/src/domains/ontology/helpers/queryClasses.ts +32 -16
  161. package/src/domains/ontology/helpers/queryProperties.ts +39 -6
  162. package/src/domains/ontology/helpers/queryTboxFacts.ts +160 -0
  163. package/src/domains/ontology/mcp/specs.ts +7 -84
  164. package/src/domains/ontology/operations/listOntologies.test.ts +80 -3
  165. package/src/domains/ontology/operations/listOntologies.ts +126 -30
  166. package/src/domains/ontology/operations/showOntology.test.ts +131 -12
  167. package/src/domains/ontology/operations/showOntology.ts +289 -7
  168. package/src/domains/ontology/operations/showOntologyRaw.test.ts +4 -2
  169. package/src/domains/ontology/stories.test.ts +36 -0
  170. package/src/domains/ontology/stories.ts +153 -0
  171. package/src/domains/refs/operations/updateRefs.ts +2 -38
  172. package/src/domains/setup/commands/index.ts +1 -0
  173. package/src/domains/setup/commands/setup.ts +70 -0
  174. package/src/domains/setup/commands/skills.test.ts +6 -2
  175. package/src/domains/setup/commands/skills.ts +6 -2
  176. package/src/domains/setup/helpers/runSetupTask.test.ts +148 -150
  177. package/src/domains/setup/helpers/runSetupTask.ts +62 -70
  178. package/src/domains/setup/index.ts +7 -3
  179. package/src/domains/setup/operations/setupLsp.test.ts +3 -2
  180. package/src/domains/setup/operations/setupLsp.ts +7 -2
  181. package/src/domains/setup/operations/setupMcp.test.ts +6 -1
  182. package/src/domains/shared/bootStore.bareCore.test.ts +63 -0
  183. package/src/domains/shared/bootStore.test.ts +82 -0
  184. package/src/domains/shared/bootStore.ts +57 -18
  185. package/src/domains/shared/compactUri.test.ts +11 -0
  186. package/src/domains/shared/compactUri.ts +10 -5
  187. package/src/domains/shared/context.ts +2 -2
  188. package/src/domains/shared/contracts.ts +11 -0
  189. package/src/domains/shared/createInteractivePromptSession.test.ts +439 -0
  190. package/src/domains/shared/createInteractivePromptSession.ts +236 -0
  191. package/src/domains/shared/emptyErrorRecovery.test.ts +23 -26
  192. package/src/domains/shared/extractLocalName.test.ts +3 -3
  193. package/src/domains/shared/formatters.ts +23 -2
  194. package/src/domains/shared/listTiers.ts +40 -0
  195. package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
  196. package/src/domains/shared/loaders/bundledLoader.ts +158 -12
  197. package/src/domains/shared/loaders/gitLoader.ts +1 -2
  198. package/src/domains/shared/loaders/index.ts +4 -1
  199. package/src/domains/shared/loaders/localLoader.ts +2 -4
  200. package/src/domains/shared/loaders/readPackageDir.test.ts +58 -0
  201. package/src/domains/shared/loaders/readPackageDir.ts +82 -9
  202. package/src/domains/shared/loaders/storyAssetsPlugin.test.ts +84 -0
  203. package/src/domains/shared/loaders/storyAssetsPlugin.ts +46 -0
  204. package/src/domains/shared/lookupMany.test.ts +135 -0
  205. package/src/domains/shared/lookupMany.ts +50 -2
  206. package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
  207. package/src/domains/shared/mergeAndParseRefs.ts +44 -0
  208. package/src/domains/shared/namespaces.ts +13 -5
  209. package/src/domains/shared/packages.ts +10 -17
  210. package/src/domains/shared/parseSampleCount.test.ts +47 -0
  211. package/src/domains/shared/parseSampleCount.ts +45 -0
  212. package/src/domains/shared/prefixes.test.ts +211 -0
  213. package/src/domains/shared/prefixes.ts +182 -15
  214. package/src/domains/shared/renderers.ts +5 -5
  215. package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
  216. package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
  217. package/src/domains/shared/resolveLookupExitCode.test.ts +48 -0
  218. package/src/domains/shared/resolveLookupExitCode.ts +42 -0
  219. package/src/domains/shared/runtime.ts +4 -63
  220. package/src/domains/shared/semanticPackage.test.ts +89 -0
  221. package/src/domains/shared/semanticPackage.ts +34 -3
  222. package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
  223. package/src/domains/shared/stories/compileLookupCommand.ts +102 -0
  224. package/src/domains/shared/stories/compileLookupTool.test.ts +105 -0
  225. package/src/domains/shared/stories/compileLookupTool.ts +96 -0
  226. package/src/domains/shared/stories/compileReadCommand.test.ts +121 -0
  227. package/src/domains/shared/stories/compileReadCommand.ts +48 -0
  228. package/src/domains/shared/stories/compileReadTool.test.ts +64 -0
  229. package/src/domains/shared/stories/compileReadTool.ts +38 -0
  230. package/src/domains/shared/stories/condense.test.ts +18 -0
  231. package/src/domains/shared/stories/condense.ts +15 -0
  232. package/src/domains/shared/stories/index.ts +20 -0
  233. package/src/domains/shared/stories/normalizeNames.test.ts +20 -0
  234. package/src/domains/shared/stories/normalizeNames.ts +22 -0
  235. package/src/domains/shared/stories/pack/applyPackFilters.test.ts +151 -0
  236. package/src/domains/shared/stories/pack/applyPackFilters.ts +111 -0
  237. package/src/domains/shared/stories/pack/applyPackSearch.test.ts +57 -0
  238. package/src/domains/shared/stories/pack/applyPackSearch.ts +41 -0
  239. package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +81 -0
  240. package/src/domains/shared/stories/pack/buildLookupQuery.ts +154 -0
  241. package/src/domains/shared/stories/pack/bundled/index.ts +23 -0
  242. package/src/domains/shared/stories/pack/bundled/standardPack.ts +164 -0
  243. package/src/domains/shared/stories/pack/bundled/tierPack.ts +50 -0
  244. package/src/domains/shared/stories/pack/collectPackStories.test.ts +406 -0
  245. package/src/domains/shared/stories/pack/collectPackStories.ts +158 -0
  246. package/src/domains/shared/stories/pack/compilePackCommands.ts +50 -0
  247. package/src/domains/shared/stories/pack/compilePackStories.test.ts +751 -0
  248. package/src/domains/shared/stories/pack/compilePackStories.ts +724 -0
  249. package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +55 -0
  250. package/src/domains/shared/stories/pack/index.ts +42 -0
  251. package/src/domains/shared/stories/pack/reservedVerbs.test.ts +213 -0
  252. package/src/domains/shared/stories/pack/reservedVerbs.ts +170 -0
  253. package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
  254. package/src/domains/shared/stories/pack/standardParity.test.ts +381 -0
  255. package/src/domains/shared/stories/pack/types.ts +224 -0
  256. package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +742 -0
  257. package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +859 -0
  258. package/src/domains/shared/stories/projectCliParameters.test.ts +59 -0
  259. package/src/domains/shared/stories/projectCliParameters.ts +57 -0
  260. package/src/domains/shared/stories/projectToolParams.test.ts +50 -0
  261. package/src/domains/shared/stories/projectToolParams.ts +32 -0
  262. package/src/domains/shared/stories/requirePragmaContext.test.ts +23 -0
  263. package/src/domains/shared/stories/requirePragmaContext.ts +23 -0
  264. package/src/domains/shared/stories/resolveLookupDetailed.test.ts +57 -0
  265. package/src/domains/shared/stories/resolveLookupDetailed.ts +27 -0
  266. package/src/domains/shared/stories/types.ts +179 -0
  267. package/src/domains/shared/suggestions/expandGlob.ts +1 -0
  268. package/src/domains/shared/suggestions/suggestNames.ts +43 -10
  269. package/src/domains/shared/types/index.ts +5 -9
  270. package/src/domains/shared/types/ontology.ts +119 -24
  271. package/src/domains/shared/types/standard.ts +9 -52
  272. package/src/domains/skill/commands/index.ts +3 -1
  273. package/src/domains/skill/commands/list.test.ts +6 -2
  274. package/src/domains/skill/commands/list.ts +5 -63
  275. package/src/domains/skill/commands/lookup.test.ts +118 -0
  276. package/src/domains/skill/commands/lookup.ts +14 -0
  277. package/src/domains/skill/formatters/index.ts +1 -0
  278. package/src/domains/skill/formatters/lookup.test.ts +46 -0
  279. package/src/domains/skill/formatters/lookup.ts +57 -0
  280. package/src/domains/skill/helpers/resolveSkillSources.ts +0 -1
  281. package/src/domains/skill/index.ts +7 -3
  282. package/src/domains/skill/mcp/specs.ts +10 -29
  283. package/src/domains/skill/operations/discover.test.ts +61 -30
  284. package/src/domains/skill/operations/discover.ts +28 -37
  285. package/src/domains/skill/operations/index.ts +2 -1
  286. package/src/domains/skill/operations/list.test.ts +15 -7
  287. package/src/domains/skill/operations/lookup.test.ts +91 -0
  288. package/src/domains/skill/operations/lookup.ts +70 -0
  289. package/src/domains/skill/stories.test.ts +43 -0
  290. package/src/domains/skill/stories.ts +103 -0
  291. package/src/domains/skill/types.ts +8 -0
  292. package/src/domains/token/commands/lookup.test.ts +8 -0
  293. package/src/domains/token/commands/lookup.ts +12 -0
  294. package/src/domains/token/commands/sample.ts +2 -1
  295. package/src/domains/token/featureFlag.ts +17 -0
  296. package/src/domains/token/index.ts +5 -0
  297. package/src/domains/token/mcp/specs.ts +18 -2
  298. package/src/domains/token/orchestration/resolveTokenLookup.ts +2 -1
  299. package/src/domains/trace/commands/resolveTraceLimit.test.ts +31 -0
  300. package/src/domains/trace/commands/show.ts +30 -4
  301. package/src/domains/trace/tracePlugin.test.ts +1 -1
  302. package/src/index.ts +1 -13
  303. package/src/mcp/registerResources.test.ts +382 -74
  304. package/src/mcp/registerResources.ts +5 -348
  305. package/src/mcp/resources/buildGraphIndex.ts +167 -0
  306. package/src/mcp/resources/buildResourceList.test.ts +97 -0
  307. package/src/mcp/resources/buildResourceList.ts +176 -0
  308. package/src/mcp/resources/classifyEntity.test.ts +40 -0
  309. package/src/mcp/resources/classifyEntity.ts +27 -0
  310. package/src/mcp/resources/constants.ts +105 -0
  311. package/src/mcp/resources/displayPredicates.ts +62 -0
  312. package/src/mcp/resources/pickFirstValue.test.ts +29 -0
  313. package/src/mcp/resources/pickFirstValue.ts +26 -0
  314. package/src/mcp/resources/pickPrimaryType.test.ts +41 -0
  315. package/src/mcp/resources/pickPrimaryType.ts +26 -0
  316. package/src/mcp/resources/rankUriCompletions.test.ts +52 -0
  317. package/src/mcp/resources/rankUriCompletions.ts +64 -0
  318. package/src/mcp/resources/readEntity.ts +169 -0
  319. package/src/mcp/resources/registerResources.ts +126 -0
  320. package/src/mcp/resources/types.ts +128 -0
  321. package/src/mcp/tools/index.ts +22 -5
  322. package/src/mcp/tools/registerTools.test.ts +167 -34
  323. package/src/mcp/types.ts +4 -0
  324. package/src/pipeline/collectCommands.test.ts +151 -1
  325. package/src/pipeline/collectCommands.ts +35 -13
  326. package/src/pipeline/createProgram.test.ts +5 -1
  327. package/src/pipeline/createProgram.ts +2 -2
  328. package/src/pipeline/firstRun.test.ts +80 -0
  329. package/src/pipeline/firstRun.ts +99 -0
  330. package/src/pipeline/parseGlobalFlags.test.ts +102 -1
  331. package/src/pipeline/parseGlobalFlags.ts +98 -9
  332. package/src/pipeline/resolveCommandKind.test.ts +12 -0
  333. package/src/pipeline/resolveCommandKind.ts +4 -0
  334. package/src/pipeline/rootHelp.test.ts +87 -0
  335. package/src/pipeline/rootHelp.ts +265 -0
  336. package/src/pipeline/runCli.orchestration.test.ts +28 -12
  337. package/src/pipeline/runCli.test.ts +17 -4
  338. package/src/pipeline/runCli.ts +202 -25
  339. package/src/testing/cli.ts +30 -2
  340. package/src/testing/createTestMcpClient.ts +4 -1
  341. package/src/testing/dsFixtures.ts +21 -4
  342. package/src/testing/index.ts +7 -0
  343. package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
  344. package/src/testing/integration/cli-user-stories.test.ts +63 -0
  345. package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
  346. package/src/testing/integration/edge-cases.test.ts +62 -50
  347. package/src/testing/integration/executor-execution.test.ts +103 -0
  348. package/src/testing/integration/executor-golden.test.ts +145 -0
  349. package/src/testing/integration/mcp-surface.test.ts +40 -15
  350. package/src/testing/integration/parity.test.ts +136 -82
  351. package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
  352. package/src/testing/setupXdgIsolation.ts +26 -0
  353. package/src/testing/standardParityFixtures.ts +35 -0
  354. package/src/testing/store.ts +4 -4
  355. package/src/testing/storyFixtures.ts +63 -0
  356. package/src/domains/create/commands/component.test.ts +0 -166
  357. package/src/domains/create/commands/component.ts +0 -123
  358. package/src/domains/create/commands/index.ts +0 -3
  359. package/src/domains/create/commands/package.test.ts +0 -35
  360. package/src/domains/create/commands/package.ts +0 -21
  361. package/src/domains/create/generators.ts +0 -8
  362. package/src/domains/standard/commands/categories.test.ts +0 -70
  363. package/src/domains/standard/commands/categories.ts +0 -48
  364. package/src/domains/standard/commands/index.ts +0 -6
  365. package/src/domains/standard/commands/list.test.ts +0 -105
  366. package/src/domains/standard/commands/list.ts +0 -90
  367. package/src/domains/standard/commands/lookup.test.ts +0 -135
  368. package/src/domains/standard/commands/lookup.ts +0 -99
  369. package/src/domains/standard/commands/sample.ts +0 -57
  370. package/src/domains/standard/formatters/categories.test.ts +0 -44
  371. package/src/domains/standard/formatters/categories.ts +0 -38
  372. package/src/domains/standard/formatters/index.ts +0 -10
  373. package/src/domains/standard/formatters/list.test.ts +0 -169
  374. package/src/domains/standard/formatters/list.ts +0 -184
  375. package/src/domains/standard/formatters/lookup.test.ts +0 -95
  376. package/src/domains/standard/formatters/lookup.ts +0 -101
  377. package/src/domains/standard/formatters/sample.ts +0 -15
  378. package/src/domains/standard/formatters/types.ts +0 -31
  379. package/src/domains/standard/index.ts +0 -40
  380. package/src/domains/standard/mcp/index.ts +0 -2
  381. package/src/domains/standard/mcp/specs.ts +0 -244
  382. package/src/domains/standard/operations/categories.test.ts +0 -61
  383. package/src/domains/standard/operations/categories.ts +0 -38
  384. package/src/domains/standard/operations/index.ts +0 -6
  385. package/src/domains/standard/operations/list.test.ts +0 -75
  386. package/src/domains/standard/operations/list.ts +0 -64
  387. package/src/domains/standard/operations/lookup.test.ts +0 -58
  388. package/src/domains/standard/operations/lookup.ts +0 -151
  389. package/src/domains/standard/operations/sample.ts +0 -35
  390. package/src/domains/standard/orchestration/buildStandardFilters.ts +0 -11
  391. package/src/domains/standard/orchestration/index.ts +0 -4
  392. package/src/domains/standard/orchestration/resolveStandardList.ts +0 -45
  393. package/src/domains/standard/orchestration/resolveStandardLookup.ts +0 -32
  394. package/src/domains/standard/orchestration/standardEmptyError.test.ts +0 -33
  395. package/src/domains/standard/orchestration/standardEmptyError.ts +0 -29
  396. package/src/domains/standard/standardConfig.ts +0 -42
  397. package/src/domains/standard/types.ts +0 -15
  398. package/src/domains/tier/commands/index.ts +0 -3
  399. package/src/domains/tier/commands/list.test.ts +0 -67
  400. package/src/domains/tier/commands/list.ts +0 -59
  401. package/src/domains/tier/formatters/index.ts +0 -3
  402. package/src/domains/tier/formatters/list.test.ts +0 -33
  403. package/src/domains/tier/formatters/list.ts +0 -45
  404. package/src/domains/tier/index.ts +0 -17
  405. package/src/domains/tier/mcp/index.ts +0 -2
  406. package/src/domains/tier/mcp/specs.ts +0 -38
  407. package/src/domains/tier/operations/index.ts +0 -3
  408. package/src/domains/tier/operations/list.test.ts +0 -32
  409. package/src/domains/tier/operations/list.ts +0 -33
  410. package/src/pipeline/runInteractiveCommand.ts +0 -198
@@ -18,8 +18,9 @@ describe("setupLsp", () => {
18
18
  it("logs info messages before and after exec", () => {
19
19
  const result = dryRun(setupLsp("/project"));
20
20
  const logs = result.effects.filter((e) => e._tag === "Log");
21
- expect(logs.some((l) => l.message.includes("Installing"))).toBe(true);
22
- expect(logs.some((l) => l.message.includes("✓"))).toBe(true);
21
+ expect(logs.some((l) => l.message.includes("Ensuring"))).toBe(true);
22
+ // Reports an idempotent "up to date" outcome, not a fresh install claim.
23
+ expect(logs.some((l) => l.message.includes("up to date"))).toBe(true);
23
24
  });
24
25
 
25
26
  it("collects effects without execution", () => {
@@ -10,8 +10,13 @@ import { $, exec, gen, info, type Task } from "@canonical/task";
10
10
  */
11
11
  export default function setupLsp(root: string): Task<void> {
12
12
  return gen(function* () {
13
- yield* $(info("Installing Terrazzo LSP extension for VS Code..."));
13
+ yield* $(
14
+ info("Ensuring the Terrazzo LSP VS Code extension is installed..."),
15
+ );
16
+ // The extension installer is idempotent — it installs if missing and is a
17
+ // no-op if already present — so this reports "ensured", not a fresh install
18
+ // (pragma does not inspect VS Code's extension state to tell them apart).
14
19
  yield* $(exec("bunx", ["@canonical/terrazzo-lsp-extension"], root));
15
- yield* $(info("✓ Terrazzo LSP extension installed."));
20
+ yield* $(info("✓ Terrazzo LSP extension is installed (up to date)."));
16
21
  });
17
22
  }
@@ -10,7 +10,12 @@ const mockExists =
10
10
  function mocks(
11
11
  existsPredicate: (path: string) => boolean,
12
12
  ): Map<string, (effect: Effect) => unknown> {
13
- return new Map([["Exists", mockExists(existsPredicate)]]);
13
+ return new Map<string, (effect: Effect) => unknown>([
14
+ ["Exists", mockExists(existsPredicate)],
15
+ // An existing config reads back as an empty-but-valid JSON object, so a
16
+ // write merges into it rather than failing closed on the dry-run placeholder.
17
+ ["ReadFile", () => "{}"],
18
+ ]);
14
19
  }
15
20
 
16
21
  describe("setupMcp", () => {
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Bare-core boot — pragma must serve the generic `graph`, `graphql`, and
3
+ * `ontology` surfaces with zero semantic packages loaded. This pins the P0
4
+ * invariant that the core no longer depends on the design-system packages:
5
+ * a store booted with no packages resolves generic queries and each
6
+ * generic operation returns cleanly instead of crashing.
7
+ */
8
+
9
+ import type { Store } from "@canonical/ke";
10
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
11
+ import { EX_NAMESPACE, GRAPHQL_CLEAN_TTL } from "#testing";
12
+ import inspectUri from "../graph/operations/inspectUri.js";
13
+ import compileSchema from "../graphql/operations/compileSchema.js";
14
+ import listOntologies from "../ontology/operations/listOntologies.js";
15
+ import { bootStore } from "./bootStore.js";
16
+ import { PREFIX_MAP, resolvePrefixes } from "./prefixes.js";
17
+
18
+ let store: Store;
19
+
20
+ beforeAll(async () => {
21
+ // The `sources` override boots with zero resolved packages (bare core).
22
+ const boot = await bootStore({ sources: [] });
23
+ store = boot.store;
24
+ expect(boot.packages).toEqual([]);
25
+ });
26
+
27
+ afterAll(() => store?.dispose());
28
+
29
+ describe("bare-core boot", () => {
30
+ it("carries the generic core prefixes on the store", () => {
31
+ expect(store.prefixes.rdf).toBe(PREFIX_MAP.rdf);
32
+ expect(store.prefixes.owl).toBe(PREFIX_MAP.owl);
33
+ });
34
+
35
+ it("serves generic SPARQL without any packages loaded", async () => {
36
+ const result = await store.query(
37
+ "SELECT (COUNT(*) AS ?n) WHERE { ?s ?p ?o }",
38
+ );
39
+ expect(result.type).toBe("select");
40
+ });
41
+
42
+ it("serves `ontology` — listOntologies returns cleanly, not a crash", async () => {
43
+ await expect(listOntologies(store)).resolves.toEqual([]);
44
+ });
45
+
46
+ it("serves `graph` — inspecting an unknown URI reports not-found, not a crash", async () => {
47
+ await expect(
48
+ inspectUri(store, "https://example.org/nothing"),
49
+ ).rejects.toMatchObject({ code: "ENTITY_NOT_FOUND" });
50
+ });
51
+
52
+ it("serves `graphql` — compiles a generic ontology with core-only prefixes", async () => {
53
+ const outcome = await compileSchema({
54
+ sources: [
55
+ { content: GRAPHQL_CLEAN_TTL, format: "turtle", path: "x.ttl" },
56
+ ],
57
+ // Package-style prefix layered over the bare core — no DS packages.
58
+ prefixes: resolvePrefixes([{ prefixes: { ex: EX_NAMESPACE } }]),
59
+ });
60
+ expect(outcome.status).toBe("ok");
61
+ expect(outcome.compiled?.sdl).toContain("type Thing");
62
+ });
63
+ });
@@ -0,0 +1,82 @@
1
+ import { createStore } from "@canonical/ke";
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { createGraphLoaderPlugin } from "./bootStore.js";
4
+
5
+ const PREFIXES = { ds: "https://ds.canonical.com/" };
6
+
7
+ const goodGraph = (path: string, subject: string) => ({
8
+ path,
9
+ content: `@prefix ds: <https://ds.canonical.com/>.\nds:${subject} a ds:Component.\n`,
10
+ format: "turtle" as const,
11
+ });
12
+
13
+ /** Mirrors the malformed `ds:hasSubcomponent ds:global..` shipped by upstream. */
14
+ const badGraph = (path: string) => ({
15
+ path,
16
+ content:
17
+ "@prefix ds: <https://ds.canonical.com/>.\nds:global.component.broken a ds:Component;\n ds:hasSubcomponent ds:global...\n",
18
+ format: "turtle" as const,
19
+ });
20
+
21
+ async function countTriples(
22
+ graphs: readonly ReturnType<typeof goodGraph>[],
23
+ ): Promise<number> {
24
+ const store = await createStore({
25
+ sources: [],
26
+ prefixes: PREFIXES,
27
+ plugins: [createGraphLoaderPlugin(graphs)],
28
+ });
29
+ // Always dispose the WASM-backed store so it can't leak across tests.
30
+ try {
31
+ const result = await store.query(
32
+ "SELECT (COUNT(*) AS ?n) WHERE { ?s ?p ?o }",
33
+ );
34
+ return Number(
35
+ result.type === "select" ? (result.bindings[0]?.n ?? "0") : "0",
36
+ );
37
+ } finally {
38
+ store.dispose();
39
+ }
40
+ }
41
+
42
+ let stderrSpy: ReturnType<typeof vi.spyOn>;
43
+
44
+ beforeEach(() => {
45
+ stderrSpy = vi.spyOn(process.stderr, "write").mockImplementation(() => true);
46
+ });
47
+
48
+ afterEach(() => {
49
+ stderrSpy.mockRestore();
50
+ });
51
+
52
+ const stderrText = (): string =>
53
+ stderrSpy.mock.calls.map((call) => String(call[0])).join("");
54
+
55
+ describe("createGraphLoaderPlugin", () => {
56
+ it("loads every graph when all are well-formed", async () => {
57
+ const count = await countTriples([
58
+ goodGraph("a.ttl", "global.component.a"),
59
+ goodGraph("b.ttl", "global.component.b"),
60
+ ]);
61
+ expect(count).toBe(2);
62
+ expect(stderrText()).toBe("");
63
+ });
64
+
65
+ it("skips a malformed graph but still boots and loads the good ones", async () => {
66
+ const count = await countTriples([
67
+ goodGraph("a.ttl", "global.component.a"),
68
+ badGraph("data/global/component/broken.ttl"),
69
+ goodGraph("b.ttl", "global.component.b"),
70
+ ]);
71
+ // The two good graphs load; the malformed one is skipped, not fatal.
72
+ expect(count).toBe(2);
73
+ });
74
+
75
+ it("warns with the offending file path and parse error", async () => {
76
+ await countTriples([badGraph("data/global/component/broken.ttl")]);
77
+ const text = stderrText();
78
+ expect(text).toContain("skipping malformed graph");
79
+ expect(text).toContain("data/global/component/broken.ttl");
80
+ expect(text).toContain("Check the TTL syntax");
81
+ });
82
+ });
@@ -23,7 +23,7 @@ import {
23
23
  createLocalLoader,
24
24
  } from "./loaders/index.js";
25
25
  import { DEFAULT_PACKAGES } from "./packages.js";
26
- import { PREFIX_MAP } from "./prefixes.js";
26
+ import { resolvePrefixes } from "./prefixes.js";
27
27
  import type { GraphContent, SemanticPackage } from "./semanticPackage.js";
28
28
  import { resolveSemanticPackages } from "./semanticPackage.js";
29
29
 
@@ -38,6 +38,8 @@ export interface BootStoreOptions {
38
38
  refs?: ReadonlyArray<PackageRef>;
39
39
  /** Enable query tracing (from config). Env var PRAGMA_TRACE=1 overrides. */
40
40
  trace?: boolean;
41
+ /** Additional namespace prefixes merged over the built-in prefix map. */
42
+ prefixes?: Readonly<Record<string, string>>;
41
43
  }
42
44
 
43
45
  export interface BootResult {
@@ -60,11 +62,13 @@ export async function bootStore(
60
62
  options: BootStoreOptions = {},
61
63
  ): Promise<BootResult> {
62
64
  try {
63
- // Testing/programmatic override — use explicit sources
65
+ // Testing/programmatic override — use explicit sources. No packages are
66
+ // resolved, so the prefix map is the core base plus the transitional DS
67
+ // fallback and any caller override.
64
68
  if (options.sources) {
65
69
  const store = await createStore({
66
70
  sources: options.sources,
67
- prefixes: PREFIX_MAP,
71
+ prefixes: resolvePrefixes([], options.prefixes),
68
72
  cache: options.cache,
69
73
  cwd: options.cwd,
70
74
  });
@@ -87,19 +91,11 @@ export async function bootStore(
87
91
  // Collect all graph content from resolved packages
88
92
  const allGraphs = packages.flatMap((pkg) => pkg.graphs);
89
93
 
90
- // Use a ke plugin to load graph content during store creation.
91
- // The onReady hook has access to ctx.load() which loads raw content.
92
- const graphLoaderPlugin = definePlugin({
93
- name: "pragma-graph-loader",
94
- onReady(ctx) {
95
- for (const graph of allGraphs) {
96
- ctx.load(graph.content, { format: graph.format });
97
- }
98
- },
99
- });
100
-
101
- // biome-ignore lint: Plugin generic variance requires explicit unknown
102
- const plugins: Plugin<any>[] = [graphLoaderPlugin];
94
+ // `Plugin<T>` is invariant in its API type and createStore expects
95
+ // `Plugin<void>[]`, so heterogeneous plugins (graph loader + trace) can only
96
+ // share an array via `any`. `unknown` does not satisfy `Plugin<void>`.
97
+ // biome-ignore lint/suspicious/noExplicitAny: intentional — see above
98
+ const plugins: Plugin<any>[] = [createGraphLoaderPlugin(allGraphs)];
103
99
  const traceEnabled =
104
100
  process.env.PRAGMA_TRACE === "1" || options.trace === true;
105
101
  if (traceEnabled) {
@@ -108,9 +104,12 @@ export async function bootStore(
108
104
  plugins.push(createTracePlugin({ traceDir: traceDir() }));
109
105
  }
110
106
 
107
+ // Merge every resolved package's declared prefixes (and the transitional
108
+ // DS fallback) over the generic core, then config overrides — so the
109
+ // store and every query see the packages' own namespaces.
111
110
  const store = await createStore({
112
111
  sources: [],
113
- prefixes: PREFIX_MAP,
112
+ prefixes: resolvePrefixes(packages, options.prefixes),
114
113
  cache: options.cache,
115
114
  cwd: options.cwd,
116
115
  plugins,
@@ -124,9 +123,49 @@ export async function bootStore(
124
123
  {
125
124
  recovery: {
126
125
  message:
127
- "Ensure design system packages are installed: bun add -D @canonical/design-system @canonical/code-standards @canonical/anatomy-dsl",
126
+ "If this is a parser error, check the TTL syntax of the source graphs " +
127
+ "(the message above names the line and column). Otherwise ensure design " +
128
+ "system packages are installed: bun add -D @canonical/design-system " +
129
+ "@canonical/code-standards @canonical/anatomy-dsl",
128
130
  },
129
131
  },
130
132
  );
131
133
  }
132
134
  }
135
+
136
+ /**
137
+ * Build the ke plugin that loads resolved graph content into the store.
138
+ *
139
+ * Each graph is loaded independently inside its own try/catch: a single
140
+ * malformed TTL file (e.g. invalid Turtle emitted by an upstream authoring
141
+ * tool) must not abort the entire boot and take the whole CLI down with it.
142
+ * Failed graphs are skipped and surfaced as warnings, mirroring the
143
+ * resilience the story loader already provides ("one bad file cannot break
144
+ * boot"). A store built from N-1 good graphs is far more useful than a store
145
+ * that refuses to boot because of one bad graph.
146
+ *
147
+ * @note Impure — writes warnings to stderr on parse failure.
148
+ */
149
+ export function createGraphLoaderPlugin(
150
+ graphs: readonly GraphContent[],
151
+ ): Plugin {
152
+ return definePlugin({
153
+ name: "pragma-graph-loader",
154
+ onReady(ctx) {
155
+ for (const graph of graphs) {
156
+ try {
157
+ ctx.load(graph.content, { format: graph.format });
158
+ } catch (error) {
159
+ const reason = error instanceof Error ? error.message : String(error);
160
+ // Name the offending file and the parse error, and point at the fix.
161
+ // The store still boots from the remaining graphs, so this is a
162
+ // warning, not a fatal error.
163
+ process.stderr.write(
164
+ `Warning: skipping malformed graph "${graph.path}" — ${reason}. ` +
165
+ "Check the TTL syntax of this source file; the remaining graphs still load.\n",
166
+ );
167
+ }
168
+ }
169
+ },
170
+ });
171
+ }
@@ -18,4 +18,15 @@ describe("compactUri", () => {
18
18
  "https://example.com/thing",
19
19
  );
20
20
  });
21
+
22
+ it("picks the longest matching namespace when namespaces overlap", () => {
23
+ const overlapping = {
24
+ base: "https://ex.org/",
25
+ sub: "https://ex.org/sub/",
26
+ } as const;
27
+ // Both `base` and `sub` are prefixes of the URI; the longer wins.
28
+ expect(compactUri("https://ex.org/sub/Thing", overlapping)).toBe(
29
+ "sub:Thing",
30
+ );
31
+ });
21
32
  });
@@ -1,16 +1,21 @@
1
1
  /**
2
- * Convert a full URI to its compact prefixed form when a matching prefix exists.
3
- * Falls back to the original URI when no namespace matches.
2
+ * Convert a full URI to its compact prefixed form using the longest matching
3
+ * namespace. When two registered namespaces are both prefixes of the URI
4
+ * (e.g. a base namespace and a sub-namespace), the longer — more specific —
5
+ * one wins. Falls back to the original URI when no namespace matches.
4
6
  */
5
7
  export default function compactUri(
6
8
  fullUri: string,
7
9
  prefixes: Readonly<Record<string, string>>,
8
10
  ): string {
11
+ let best: { prefix: string; namespace: string } | undefined;
9
12
  for (const [prefix, namespace] of Object.entries(prefixes)) {
10
- if (fullUri.startsWith(namespace)) {
11
- return `${prefix}:${fullUri.slice(namespace.length)}`;
13
+ if (!fullUri.startsWith(namespace)) continue;
14
+ if (best === undefined || namespace.length > best.namespace.length) {
15
+ best = { prefix, namespace };
12
16
  }
13
17
  }
14
18
 
15
- return fullUri;
19
+ if (best === undefined) return fullUri;
20
+ return `${best.prefix}:${fullUri.slice(best.namespace.length)}`;
16
21
  }
@@ -7,10 +7,10 @@
7
7
  * cli-core remains unaware of Store or FilterConfig.
8
8
  */
9
9
 
10
- import type { GlobalFlags, InteractiveHandler } from "@canonical/cli-core";
10
+ import type { GlobalFlags, PromptSessionFactory } from "@canonical/cli-core";
11
11
  import type { PragmaRuntime } from "./types/index.js";
12
12
 
13
13
  export interface PragmaContext extends PragmaRuntime {
14
14
  readonly globalFlags: GlobalFlags;
15
- readonly interactive?: InteractiveHandler | undefined;
15
+ readonly promptSession?: PromptSessionFactory | undefined;
16
16
  }
@@ -50,6 +50,15 @@ export interface ListResult<T> {
50
50
  | { readonly level: "detailed" };
51
51
  }
52
52
 
53
+ /** Aggregate metadata about a multi-query lookup. */
54
+ export interface LookupResultMeta {
55
+ /**
56
+ * Number of queries that failed with an unexpected (non-Pragma) error.
57
+ * Each such failure is also present in `errors` with code `INTERNAL_ERROR`.
58
+ */
59
+ readonly internalErrorCount: number;
60
+ }
61
+
53
62
  export interface LookupResult<T> {
54
63
  readonly results: readonly T[];
55
64
  readonly errors: readonly {
@@ -58,6 +67,8 @@ export interface LookupResult<T> {
58
67
  message: string;
59
68
  suggestions?: readonly string[];
60
69
  }[];
70
+ /** Populated by `lookupMany`; may be absent on hand-built results. */
71
+ readonly meta?: LookupResultMeta;
61
72
  }
62
73
 
63
74
  export interface ShowContract<T> {