@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
@@ -2,7 +2,7 @@ import chalk from "chalk";
2
2
  import { formatHeading } from "#pipeline";
3
3
  import compactUri from "../../shared/compactUri.js";
4
4
  import type { Formatters } from "../../shared/formatters.js";
5
- import { PREFIX_MAP } from "../../shared/prefixes.js";
5
+ import { DEFAULT_PREFIX_MAP } from "../../shared/prefixes.js";
6
6
  import type { InspectResult } from "../../shared/types/index.js";
7
7
 
8
8
  /**
@@ -15,13 +15,13 @@ import type { InspectResult } from "../../shared/types/index.js";
15
15
  const formatters: Formatters<InspectResult> = {
16
16
  plain(result) {
17
17
  const lines: string[] = [];
18
- lines.push(formatHeading(compactUri(result.uri, PREFIX_MAP)));
18
+ lines.push(formatHeading(compactUri(result.uri, DEFAULT_PREFIX_MAP)));
19
19
 
20
20
  for (const g of result.groups) {
21
21
  lines.push("");
22
- lines.push(chalk.bold(compactUri(g.predicate, PREFIX_MAP)));
22
+ lines.push(chalk.bold(compactUri(g.predicate, DEFAULT_PREFIX_MAP)));
23
23
  for (const o of g.objects) {
24
- lines.push(` ${compactUri(o, PREFIX_MAP)}`);
24
+ lines.push(` ${compactUri(o, DEFAULT_PREFIX_MAP)}`);
25
25
  }
26
26
  }
27
27
 
@@ -30,13 +30,13 @@ const formatters: Formatters<InspectResult> = {
30
30
 
31
31
  llm(result) {
32
32
  const lines = [
33
- `## ${compactUri(result.uri, PREFIX_MAP)} (${result.uri})`,
33
+ `## ${compactUri(result.uri, DEFAULT_PREFIX_MAP)} (${result.uri})`,
34
34
  "",
35
35
  ];
36
36
  for (const g of result.groups) {
37
- lines.push(`**${compactUri(g.predicate, PREFIX_MAP)}:**`);
37
+ lines.push(`**${compactUri(g.predicate, DEFAULT_PREFIX_MAP)}:**`);
38
38
  for (const o of g.objects) {
39
- lines.push(` - ${compactUri(o, PREFIX_MAP)}`);
39
+ lines.push(` - ${compactUri(o, DEFAULT_PREFIX_MAP)}`);
40
40
  }
41
41
  }
42
42
  return lines.join("\n");
@@ -0,0 +1,87 @@
1
+ import type { QueryResult } from "@canonical/ke";
2
+ import { describe, expect, it } from "vitest";
3
+ import formatters from "./query.js";
4
+
5
+ const selectResult = {
6
+ type: "select",
7
+ bindings: [
8
+ { s: "a", n: "1" },
9
+ { s: "b", n: "2" },
10
+ ],
11
+ } as unknown as QueryResult;
12
+
13
+ const emptySelect = {
14
+ type: "select",
15
+ bindings: [],
16
+ } as unknown as QueryResult;
17
+
18
+ const askResult = { type: "ask", result: true } as unknown as QueryResult;
19
+
20
+ const constructResult = {
21
+ type: "construct",
22
+ triples: [
23
+ { subject: "s1", predicate: "p1", object: "line one\nline two" },
24
+ { subject: "s2", predicate: "p2", object: "o2" },
25
+ ],
26
+ } as unknown as QueryResult;
27
+
28
+ const emptyConstruct = {
29
+ type: "construct",
30
+ triples: [],
31
+ } as unknown as QueryResult;
32
+
33
+ describe("graph query formatters — plain", () => {
34
+ it("renders SELECT as a tab table", () => {
35
+ const text = formatters.plain(selectResult);
36
+ expect(text.split("\n")).toEqual(["s\tn", "a\t1", "b\t2"]);
37
+ });
38
+
39
+ it("reports no results for an empty SELECT", () => {
40
+ expect(formatters.plain(emptySelect)).toBe("No results.");
41
+ });
42
+
43
+ it("renders ASK as a boolean", () => {
44
+ expect(formatters.plain(askResult)).toBe("ASK: true");
45
+ });
46
+
47
+ it("renders CONSTRUCT as one-line triples", () => {
48
+ const text = formatters.plain(constructResult);
49
+ expect(text).toContain("s1\tp1\tline one line two");
50
+ expect(text).toContain("s2\tp2\to2");
51
+ });
52
+
53
+ it("reports no triples for an empty CONSTRUCT", () => {
54
+ expect(formatters.plain(emptyConstruct)).toBe("No triples.");
55
+ });
56
+ });
57
+
58
+ describe("graph query formatters — llm", () => {
59
+ it("renders SELECT as a Markdown table", () => {
60
+ const text = formatters.llm(selectResult);
61
+ expect(text).toContain("| s | n |");
62
+ expect(text).toContain("| --- | --- |");
63
+ expect(text).toContain("| a | 1 |");
64
+ });
65
+
66
+ it("renders an empty SELECT as italic no-results", () => {
67
+ expect(formatters.llm(emptySelect)).toBe("_No results._");
68
+ });
69
+
70
+ it("renders ASK as bold", () => {
71
+ expect(formatters.llm(askResult)).toBe("**ASK** → true");
72
+ });
73
+
74
+ it("renders CONSTRUCT triples as a bullet list", () => {
75
+ const text = formatters.llm(constructResult);
76
+ expect(text).toContain("- s1\tp1\tline one line two");
77
+ });
78
+ });
79
+
80
+ describe("graph query formatters — json", () => {
81
+ it("serializes the raw result", () => {
82
+ expect(JSON.parse(formatters.json(askResult))).toMatchObject({
83
+ type: "ask",
84
+ result: true,
85
+ });
86
+ });
87
+ });
@@ -1,12 +1,33 @@
1
1
  import type { QueryResult } from "@canonical/ke";
2
2
  import type { Formatters } from "../../shared/formatters.js";
3
3
 
4
+ /**
5
+ * Render CONSTRUCT triples as readable `subject predicate object` lines,
6
+ * collapsing any newlines in literal objects so each triple stays on one line.
7
+ */
8
+ function formatTriples(
9
+ triples: ReadonlyArray<{
10
+ subject: string;
11
+ predicate: string;
12
+ object: string;
13
+ }>,
14
+ ): string {
15
+ if (triples.length === 0) return "No triples.";
16
+ return triples
17
+ .map((t) => {
18
+ const object = t.object.replace(/\s*\n\s*/g, " ").trim();
19
+ return `${t.subject}\t${t.predicate}\t${object}`;
20
+ })
21
+ .join("\n");
22
+ }
23
+
4
24
  /**
5
25
  * Formatters for `pragma graph query` output.
6
26
  *
7
- * - **plain**: tab-separated table for SELECT results, `ASK: true/false` for ASK
8
- * queries, JSON fallback for CONSTRUCT.
9
- * - **llm**: indented JSON for all query types.
27
+ * - **plain**: tab-separated table for SELECT, `ASK: true/false` for ASK, and
28
+ * readable triple lines for CONSTRUCT.
29
+ * - **llm**: condensed Markdown (table for SELECT, one line for ASK, a triple
30
+ * list for CONSTRUCT) rather than a raw JSON dump.
10
31
  * - **json**: serialized {@link QueryResult} as indented JSON.
11
32
  */
12
33
  const formatters: Formatters<QueryResult> = {
@@ -22,11 +43,27 @@ const formatters: Formatters<QueryResult> = {
22
43
  if (result.type === "ask") {
23
44
  return `ASK: ${String(result.result)}`;
24
45
  }
25
- return JSON.stringify(result, null, 2);
46
+ return formatTriples(result.triples);
26
47
  },
27
48
 
28
49
  llm(result) {
29
- return JSON.stringify(result, null, 2);
50
+ if (result.type === "select") {
51
+ if (result.bindings.length === 0) return "_No results._";
52
+ const cols = Object.keys(result.bindings[0] ?? {});
53
+ const header = `| ${cols.join(" | ")} |`;
54
+ const divider = `| ${cols.map(() => "---").join(" | ")} |`;
55
+ const rows = result.bindings.map(
56
+ (b) => `| ${cols.map((c) => b[c] ?? "").join(" | ")} |`,
57
+ );
58
+ return [header, divider, ...rows].join("\n");
59
+ }
60
+ if (result.type === "ask") {
61
+ return `**ASK** → ${String(result.result)}`;
62
+ }
63
+ return formatTriples(result.triples)
64
+ .split("\n")
65
+ .map((line) => (line.includes("\t") ? `- ${line}` : line))
66
+ .join("\n");
30
67
  },
31
68
 
32
69
  json(result) {
@@ -0,0 +1,50 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { PragmaError } from "#error";
3
+ import resolveUri from "./resolveUri.js";
4
+
5
+ const prefixes = {
6
+ ds: "https://ds.canonical.com/",
7
+ cs: "http://pragma.canonical.com/codestandards#",
8
+ } as const;
9
+
10
+ describe("resolveUri", () => {
11
+ it("expands a registered prefix", () => {
12
+ expect(resolveUri("ds:UIBlock", prefixes)).toBe(
13
+ "https://ds.canonical.com/UIBlock",
14
+ );
15
+ });
16
+
17
+ it("passes through a full http(s) IRI", () => {
18
+ expect(resolveUri("https://ds.canonical.com/global", prefixes)).toBe(
19
+ "https://ds.canonical.com/global",
20
+ );
21
+ });
22
+
23
+ it("passes through a urn: IRI", () => {
24
+ expect(resolveUri("urn:isbn:0451450523", prefixes)).toBe(
25
+ "urn:isbn:0451450523",
26
+ );
27
+ });
28
+
29
+ it("passes through a foreign scheme:// IRI", () => {
30
+ expect(resolveUri("ftp://example.org/thing", prefixes)).toBe(
31
+ "ftp://example.org/thing",
32
+ );
33
+ });
34
+
35
+ it("throws for an unknown prefix", () => {
36
+ expect(() => resolveUri("unknown:something", prefixes)).toThrow(
37
+ PragmaError,
38
+ );
39
+ });
40
+
41
+ it("throws for a bare string without a prefix", () => {
42
+ expect(() => resolveUri("button", prefixes)).toThrow(PragmaError);
43
+ });
44
+
45
+ it("throws for an IRI with unsafe characters", () => {
46
+ expect(() =>
47
+ resolveUri("https://example.com/<injected>", prefixes),
48
+ ).toThrow(PragmaError);
49
+ });
50
+ });
@@ -6,12 +6,20 @@ import { PragmaError } from "#error";
6
6
  */
7
7
  const UNSAFE_IRI_PATTERN = /[<>"{}|\\^`\s]/;
8
8
 
9
+ /**
10
+ * Matches a general absolute IRI: any scheme with an authority (`scheme://…`,
11
+ * covering http, https, ftp, ws, and foreign schemes) or a `urn:` opaque IRI.
12
+ * Broader than an http(s)-only check so foreign ontologies resolve.
13
+ */
14
+ const ABSOLUTE_IRI_PATTERN = /^(?:[A-Za-z][A-Za-z0-9+.-]*:\/\/|urn:)\S/i;
15
+
9
16
  /**
10
17
  * Resolves a potentially prefixed URI (e.g. `ds:UIBlock`) to a full URI.
11
18
  *
12
- * If the URI is already a full URI (starts with `http`), validates IRI safety
13
- * and returns it as-is. Otherwise, expands the prefix using the provided
14
- * prefix map.
19
+ * A registered prefix always wins: `ds:UIBlock` expands via the prefix map.
20
+ * Otherwise a general absolute IRI (`scheme://…` or `urn:…`) is validated and
21
+ * returned as-is, so foreign ontologies are not rejected as unknown prefixes.
22
+ * Any other `token:rest` is treated as an unknown prefix.
15
23
  *
16
24
  * @param uri - A full or prefixed URI string.
17
25
  * @param prefixes - Registered prefix-to-namespace mapping from the store.
@@ -22,11 +30,6 @@ export default function resolveUri(
22
30
  uri: string,
23
31
  prefixes: Readonly<Record<string, string>>,
24
32
  ): string {
25
- if (uri.startsWith("http://") || uri.startsWith("https://")) {
26
- assertSafeIri(uri);
27
- return uri;
28
- }
29
-
30
33
  const colonIdx = uri.indexOf(":");
31
34
  if (colonIdx === -1) {
32
35
  throw PragmaError.invalidInput("uri", uri, {
@@ -38,23 +41,27 @@ export default function resolveUri(
38
41
  }
39
42
 
40
43
  const prefix = uri.slice(0, colonIdx);
41
- const localName = uri.slice(colonIdx + 1);
42
44
  const namespace = prefixes[prefix];
43
45
 
44
- if (namespace === undefined) {
45
- throw PragmaError.invalidInput("prefix", prefix, {
46
- validOptions: Object.keys(prefixes),
47
- recovery: {
48
- message: "List known ontology prefixes.",
49
- cli: "pragma ontology list",
50
- mcp: { tool: "ontology_list" },
51
- },
52
- });
46
+ if (namespace !== undefined) {
47
+ const resolved = `${namespace}${uri.slice(colonIdx + 1)}`;
48
+ assertSafeIri(resolved);
49
+ return resolved;
50
+ }
51
+
52
+ if (ABSOLUTE_IRI_PATTERN.test(uri)) {
53
+ assertSafeIri(uri);
54
+ return uri;
53
55
  }
54
56
 
55
- const resolved = `${namespace}${localName}`;
56
- assertSafeIri(resolved);
57
- return resolved;
57
+ throw PragmaError.invalidInput("prefix", prefix, {
58
+ validOptions: Object.keys(prefixes),
59
+ recovery: {
60
+ message: "List known ontology prefixes.",
61
+ cli: "pragma ontology list",
62
+ mcp: { tool: "ontology_list" },
63
+ },
64
+ });
58
65
  }
59
66
 
60
67
  /**
@@ -2,7 +2,7 @@ import type { Store } from "@canonical/ke";
2
2
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
3
  import { PragmaError } from "#error";
4
4
  import { createTestStore, DS_ALL_TTL } from "#testing";
5
- import { P, PREFIX_MAP } from "../../shared/prefixes.js";
5
+ import { DEFAULT_PREFIX_MAP, P } from "../../shared/prefixes.js";
6
6
  import inspectUri from "./inspectUri.js";
7
7
 
8
8
  let store: Store;
@@ -19,7 +19,7 @@ afterAll(() => cleanup());
19
19
  describe("inspectUri", () => {
20
20
  it("returns grouped triples for a known URI", async () => {
21
21
  const result = await inspectUri(store, `${P.ds}global.component.button`);
22
- expect(result.uri).toBe(`${PREFIX_MAP.ds}global.component.button`);
22
+ expect(result.uri).toBe(`${DEFAULT_PREFIX_MAP.ds}global.component.button`);
23
23
  expect(result.groups.length).toBeGreaterThan(0);
24
24
 
25
25
  const predicates = result.groups.map((g) => g.predicate);
@@ -30,15 +30,15 @@ describe("inspectUri", () => {
30
30
 
31
31
  it("resolves prefixed URIs", async () => {
32
32
  const result = await inspectUri(store, `${P.ds}global.component.button`);
33
- expect(result.uri).toBe(`${PREFIX_MAP.ds}global.component.button`);
33
+ expect(result.uri).toBe(`${DEFAULT_PREFIX_MAP.ds}global.component.button`);
34
34
  });
35
35
 
36
36
  it("accepts full URIs", async () => {
37
37
  const result = await inspectUri(
38
38
  store,
39
- `${PREFIX_MAP.ds}global.component.button`,
39
+ `${DEFAULT_PREFIX_MAP.ds}global.component.button`,
40
40
  );
41
- expect(result.uri).toBe(`${PREFIX_MAP.ds}global.component.button`);
41
+ expect(result.uri).toBe(`${DEFAULT_PREFIX_MAP.ds}global.component.button`);
42
42
  expect(result.groups.length).toBeGreaterThan(0);
43
43
  });
44
44
 
@@ -181,13 +181,15 @@ describe("graphql build command", () => {
181
181
  expect(printed).toContain("C003");
182
182
  });
183
183
 
184
- it("throws structured error when sources are missing", async () => {
184
+ it("throws a structured error when explicit sources match nothing", async () => {
185
185
  const ctx = makeCtx();
186
186
 
187
- await expect(buildCommand.execute({}, ctx)).rejects.toMatchObject({
187
+ await expect(
188
+ buildCommand.execute({ sources: ["no-such-*.ttl"] }, ctx),
189
+ ).rejects.toMatchObject({
188
190
  code: "INVALID_INPUT",
189
191
  recovery: {
190
- message: "Provide at least one TTL file or glob pattern.",
192
+ message: "No files matched the given paths or glob patterns.",
191
193
  },
192
194
  });
193
195
  });
@@ -7,16 +7,13 @@ import {
7
7
  createOutputResult,
8
8
  } from "@canonical/cli-core";
9
9
  import { serializeExtraction } from "@canonical/ke-graphql";
10
- import { PragmaError } from "#error";
11
10
  import { selectFormatter } from "../../shared/formatters.js";
11
+ import { DEFAULT_EXTRACTION_PATH, DEFAULT_SDL_PATH } from "../constants.js";
12
12
  import { reportFormatters } from "../formatters/index.js";
13
- import { parsePrefixes } from "../helpers/index.js";
13
+ import { gatherSources, parsePrefixes } from "../helpers/index.js";
14
14
  import { compileSchema } from "../operations/index.js";
15
15
  import type { GraphqlCompileReport } from "../types.js";
16
16
 
17
- const DEFAULT_SDL_PATH = "./schema.graphql";
18
- const DEFAULT_EXTRACTION_PATH = "./extraction.json";
19
-
20
17
  /** Narrow an unknown param to a string array. */
21
18
  function readStringArray(value: unknown): string[] {
22
19
  return Array.isArray(value)
@@ -37,10 +34,10 @@ const buildCommand: CommandDefinition = {
37
34
  parameters: [
38
35
  {
39
36
  name: "sources",
40
- description: "TTL source files or glob patterns",
37
+ description:
38
+ "TTL files or globs (default: the configured semantic packages)",
41
39
  type: "multiselect",
42
40
  positional: true,
43
- required: true,
44
41
  },
45
42
  {
46
43
  name: "sdl",
@@ -68,15 +65,10 @@ const buildCommand: CommandDefinition = {
68
65
  ],
69
66
  },
70
67
  async execute(params, ctx): Promise<CommandResult> {
71
- const sources = readStringArray(params.sources);
72
- if (sources.length === 0) {
73
- throw PragmaError.invalidInput("sources", "(empty)", {
74
- recovery: {
75
- message: "Provide at least one TTL file or glob pattern.",
76
- },
77
- });
78
- }
79
-
68
+ const sources = await gatherSources(
69
+ readStringArray(params.sources),
70
+ ctx.cwd,
71
+ );
80
72
  const prefixes = parsePrefixes(readStringArray(params.prefix));
81
73
  const outcome = await compileSchema({ sources, prefixes, cwd: ctx.cwd });
82
74
  const format = selectFormatter(ctx, reportFormatters);
@@ -126,13 +126,15 @@ describe("graphql check command", () => {
126
126
  expect(parsed.artifacts).toBeUndefined();
127
127
  });
128
128
 
129
- it("throws structured error when sources are missing", async () => {
129
+ it("throws a structured error when explicit sources match nothing", async () => {
130
130
  const ctx = makeCtx();
131
131
 
132
- await expect(checkCommand.execute({}, ctx)).rejects.toMatchObject({
132
+ await expect(
133
+ checkCommand.execute({ sources: ["no-such-*.ttl"] }, ctx),
134
+ ).rejects.toMatchObject({
133
135
  code: "INVALID_INPUT",
134
136
  recovery: {
135
- message: "Provide at least one TTL file or glob pattern.",
137
+ message: "No files matched the given paths or glob patterns.",
136
138
  },
137
139
  });
138
140
  });
@@ -4,10 +4,9 @@ import {
4
4
  createExitResult,
5
5
  createOutputResult,
6
6
  } from "@canonical/cli-core";
7
- import { PragmaError } from "#error";
8
7
  import { selectFormatter } from "../../shared/formatters.js";
9
8
  import { reportFormatters } from "../formatters/index.js";
10
- import { parsePrefixes } from "../helpers/index.js";
9
+ import { gatherSources, parsePrefixes } from "../helpers/index.js";
11
10
  import { compileSchema } from "../operations/index.js";
12
11
  import type { GraphqlCompileReport } from "../types.js";
13
12
 
@@ -31,10 +30,10 @@ const checkCommand: CommandDefinition = {
31
30
  parameters: [
32
31
  {
33
32
  name: "sources",
34
- description: "TTL source files or glob patterns",
33
+ description:
34
+ "TTL files or globs (default: the configured semantic packages)",
35
35
  type: "multiselect",
36
36
  positional: true,
37
- required: true,
38
37
  },
39
38
  {
40
39
  name: "prefix",
@@ -49,15 +48,10 @@ const checkCommand: CommandDefinition = {
49
48
  ],
50
49
  },
51
50
  async execute(params, ctx): Promise<CommandResult> {
52
- const sources = readStringArray(params.sources);
53
- if (sources.length === 0) {
54
- throw PragmaError.invalidInput("sources", "(empty)", {
55
- recovery: {
56
- message: "Provide at least one TTL file or glob pattern.",
57
- },
58
- });
59
- }
60
-
51
+ const sources = await gatherSources(
52
+ readStringArray(params.sources),
53
+ ctx.cwd,
54
+ );
61
55
  const prefixes = parsePrefixes(readStringArray(params.prefix));
62
56
  const outcome = await compileSchema({ sources, prefixes, cwd: ctx.cwd });
63
57
 
@@ -2,3 +2,4 @@
2
2
 
3
3
  export { default as buildCommand } from "./build.js";
4
4
  export { default as checkCommand } from "./check.js";
5
+ export { default as serveCommand } from "./serve.js";
@@ -0,0 +1,46 @@
1
+ import { afterEach, describe, expect, it } from "vitest";
2
+ import { PragmaError } from "#error";
3
+ import type { PragmaContext } from "../../shared/context.js";
4
+ import serveCommand, { readPort } from "./serve.js";
5
+
6
+ describe("readPort", () => {
7
+ it("parses a valid port", () => {
8
+ expect(readPort("4001")).toBe(4001);
9
+ });
10
+
11
+ it("uses the default when the flag is absent", () => {
12
+ expect(readPort(undefined)).toBe(4000);
13
+ expect(readPort("")).toBe(4000);
14
+ });
15
+
16
+ it("rejects an out-of-range or unparseable provided port", () => {
17
+ for (const value of ["0", "70000", "not-a-port"]) {
18
+ expect(() => readPort(value)).toThrowError(PragmaError);
19
+ try {
20
+ readPort(value);
21
+ } catch (error) {
22
+ expect((error as PragmaError).code).toBe("INVALID_INPUT");
23
+ }
24
+ }
25
+ });
26
+ });
27
+
28
+ describe("graphql serve command", () => {
29
+ const ctx = { cwd: process.cwd() } as PragmaContext;
30
+ const original = (globalThis as Record<string, unknown>).Bun;
31
+
32
+ afterEach(() => {
33
+ (globalThis as Record<string, unknown>).Bun = original;
34
+ });
35
+
36
+ it("requires the Bun runtime", async () => {
37
+ (globalThis as Record<string, unknown>).Bun = undefined;
38
+
39
+ await expect(serveCommand.execute({}, ctx)).rejects.toMatchObject({
40
+ code: "STORE_ERROR",
41
+ recovery: {
42
+ message: "Run the compiled `pragma` binary or use `bun run`.",
43
+ },
44
+ });
45
+ });
46
+ });