@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,49 +2,65 @@ import type { Store } from "@canonical/ke";
2
2
  import { buildQuery } from "../../shared/buildQuery.js";
3
3
  import extractLocalName from "../../shared/extractLocalName.js";
4
4
  import { P } from "../../shared/prefixes.js";
5
- import type { OntologyClass } from "../../shared/types/index.js";
5
+
6
+ /** A class row as stored — full URIs, all superclass edges preserved. */
7
+ export interface RawOntologyClass {
8
+ readonly uri: string;
9
+ readonly label: string;
10
+ readonly comment?: string;
11
+ readonly subClassOf: readonly string[];
12
+ }
6
13
 
7
14
  /**
8
- * Queries all `owl:Class` definitions within a namespace.
9
- *
10
- * Deduplicates by class URI -- when a class has multiple `rdfs:subClassOf`
11
- * values, only the first superclass encountered is kept.
15
+ * Queries all `owl:Class` definitions within a namespace, including their
16
+ * `rdfs:comment` and **every** `rdfs:subClassOf` edge (multiple inheritance
17
+ * is preserved; downstream renderers decide tree placement).
12
18
  *
13
19
  * @note Queries ke store
14
20
  *
15
21
  * @param store - The ke store to query.
16
22
  * @param namespace - The namespace URI to filter classes by.
17
- * @returns An array of {@link OntologyClass} entries.
23
+ * @returns An array of {@link RawOntologyClass} entries, one per class.
18
24
  */
19
25
  export default async function queryClasses(
20
26
  store: Store,
21
27
  namespace: string,
22
- ): Promise<OntologyClass[]> {
28
+ ): Promise<RawOntologyClass[]> {
23
29
  const result = await store.query(
24
30
  buildQuery(`
25
- SELECT ?class ?label ?superclass
31
+ SELECT ?class ?label ?comment ?superclass
26
32
  WHERE {
27
33
  ?class a ${P.owl}Class .
28
34
  FILTER(STRSTARTS(STR(?class), "${namespace}"))
29
35
  OPTIONAL { ?class ${P.rdfs}label ?label }
36
+ OPTIONAL { ?class ${P.rdfs}comment ?comment }
30
37
  OPTIONAL { ?class ${P.rdfs}subClassOf ?superclass }
31
38
  }
32
- ORDER BY ?class
39
+ ORDER BY ?class ?superclass
33
40
  `),
34
41
  );
35
42
 
36
43
  if (result.type !== "select") return [];
37
44
 
38
- const seen = new Map<string, OntologyClass>();
45
+ const seen = new Map<
46
+ string,
47
+ { label: string; comment?: string; supers: Set<string> }
48
+ >();
39
49
  for (const b of result.bindings) {
40
50
  const uri = b.class ?? "";
41
- if (seen.has(uri)) continue;
42
- seen.set(uri, {
43
- uri,
51
+ const entry = seen.get(uri) ?? {
44
52
  label: b.label ?? extractLocalName(uri),
45
- ...(b.superclass ? { superclass: b.superclass } : {}),
46
- });
53
+ ...(b.comment ? { comment: b.comment } : {}),
54
+ supers: new Set<string>(),
55
+ };
56
+ if (b.superclass) entry.supers.add(b.superclass);
57
+ seen.set(uri, entry);
47
58
  }
48
59
 
49
- return [...seen.values()];
60
+ return [...seen.entries()].map(([uri, entry]) => ({
61
+ uri,
62
+ label: entry.label,
63
+ ...(entry.comment ? { comment: entry.comment } : {}),
64
+ subClassOf: [...entry.supers].sort(),
65
+ }));
50
66
  }
@@ -2,11 +2,20 @@ import type { Store } from "@canonical/ke";
2
2
  import { buildQuery } from "../../shared/buildQuery.js";
3
3
  import extractLocalName from "../../shared/extractLocalName.js";
4
4
  import { P } from "../../shared/prefixes.js";
5
- import type { OntologyProperty } from "../../shared/types/index.js";
5
+
6
+ /** A property row as stored — full URIs. */
7
+ export interface RawOntologyProperty {
8
+ readonly uri: string;
9
+ readonly label: string;
10
+ readonly kind: "object" | "datatype";
11
+ readonly domain?: string;
12
+ readonly range?: string;
13
+ readonly functional: boolean;
14
+ }
6
15
 
7
16
  /**
8
17
  * Queries all `owl:ObjectProperty` and `owl:DatatypeProperty` definitions
9
- * within a namespace.
18
+ * within a namespace, marking those also typed `owl:FunctionalProperty`.
10
19
  *
11
20
  * Deduplicates by property URI -- when a property has multiple `rdfs:domain`
12
21
  * or `rdfs:range` values, only the first encountered is kept.
@@ -15,12 +24,12 @@ import type { OntologyProperty } from "../../shared/types/index.js";
15
24
  *
16
25
  * @param store - The ke store to query.
17
26
  * @param namespace - The namespace URI to filter properties by.
18
- * @returns An array of {@link OntologyProperty} entries.
27
+ * @returns An array of {@link RawOntologyProperty} entries.
19
28
  */
20
29
  export default async function queryProperties(
21
30
  store: Store,
22
31
  namespace: string,
23
- ): Promise<OntologyProperty[]> {
32
+ ): Promise<RawOntologyProperty[]> {
24
33
  const result = await store.query(
25
34
  buildQuery(`
26
35
  SELECT ?prop ?label ?domain ?range ?propType
@@ -38,7 +47,9 @@ export default async function queryProperties(
38
47
 
39
48
  if (result.type !== "select") return [];
40
49
 
41
- const seen = new Map<string, OntologyProperty>();
50
+ const functional = await queryFunctionalProperties(store, namespace);
51
+
52
+ const seen = new Map<string, RawOntologyProperty>();
42
53
  for (const b of result.bindings) {
43
54
  const uri = b.prop ?? "";
44
55
  if (seen.has(uri)) continue;
@@ -47,11 +58,33 @@ export default async function queryProperties(
47
58
  label: b.label ?? extractLocalName(uri),
48
59
  ...(b.domain ? { domain: b.domain } : {}),
49
60
  ...(b.range ? { range: b.range } : {}),
50
- type: b.propType?.includes("ObjectProperty")
61
+ kind: b.propType?.includes("ObjectProperty")
51
62
  ? ("object" as const)
52
63
  : ("datatype" as const),
64
+ functional: functional.has(uri),
53
65
  });
54
66
  }
55
67
 
56
68
  return [...seen.values()];
57
69
  }
70
+
71
+ /** URIs within the namespace typed `owl:FunctionalProperty`. */
72
+ async function queryFunctionalProperties(
73
+ store: Store,
74
+ namespace: string,
75
+ ): Promise<Set<string>> {
76
+ const result = await store.query(
77
+ buildQuery(`
78
+ SELECT ?prop
79
+ WHERE {
80
+ ?prop a ${P.owl}FunctionalProperty .
81
+ FILTER(STRSTARTS(STR(?prop), "${namespace}"))
82
+ }
83
+ `),
84
+ );
85
+
86
+ if (result.type !== "select") return new Set();
87
+ return new Set(
88
+ result.bindings.map((b) => b.prop).filter((p): p is string => Boolean(p)),
89
+ );
90
+ }
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Supplementary TBox queries for `ontology show` — instance counts, SHACL
3
+ * shape summaries, the owl:Ontology header, and per-class sample instances.
4
+ *
5
+ * Kept together because each is a single small SELECT feeding the one
6
+ * {@link OntologyDetailed} structure the show operation assembles.
7
+ *
8
+ * @note Every function queries the ke store.
9
+ */
10
+
11
+ import type { Store } from "@canonical/ke";
12
+ import { buildQuery } from "../../shared/buildQuery.js";
13
+ import { P } from "../../shared/prefixes.js";
14
+
15
+ const SH = "http://www.w3.org/ns/shacl#";
16
+
17
+ /**
18
+ * Count instances per class within a namespace.
19
+ *
20
+ * One `GROUP BY ?type` query for the whole namespace — never per class.
21
+ *
22
+ * @returns Map from full class URI to instance count.
23
+ */
24
+ export async function queryInstanceCounts(
25
+ store: Store,
26
+ namespace: string,
27
+ ): Promise<ReadonlyMap<string, number>> {
28
+ const result = await store.query(
29
+ buildQuery(`
30
+ SELECT ?type (COUNT(?s) AS ?n)
31
+ WHERE {
32
+ ?s a ?type .
33
+ FILTER(STRSTARTS(STR(?type), "${namespace}"))
34
+ }
35
+ GROUP BY ?type
36
+ `),
37
+ );
38
+
39
+ if (result.type !== "select") return new Map();
40
+
41
+ const counts = new Map<string, number>();
42
+ for (const b of result.bindings) {
43
+ if (b.type && b.n) counts.set(b.type, Number(b.n));
44
+ }
45
+ return counts;
46
+ }
47
+
48
+ /** A SHACL node-shape summary row — full URIs. */
49
+ export interface RawConstraint {
50
+ readonly shape: string;
51
+ readonly targetClass?: string;
52
+ readonly propertyCount: number;
53
+ }
54
+
55
+ /**
56
+ * Summarize `sh:NodeShape`s whose shape or target class lives in the
57
+ * namespace: target class and number of property constraints.
58
+ */
59
+ export async function queryConstraints(
60
+ store: Store,
61
+ namespace: string,
62
+ ): Promise<RawConstraint[]> {
63
+ const result = await store.query(
64
+ buildQuery(`
65
+ SELECT ?shape ?target (COUNT(?p) AS ?n)
66
+ WHERE {
67
+ ?shape a <${SH}NodeShape> .
68
+ OPTIONAL { ?shape <${SH}targetClass> ?target }
69
+ OPTIONAL { ?shape <${SH}property> ?p }
70
+ FILTER(
71
+ STRSTARTS(STR(?shape), "${namespace}") ||
72
+ STRSTARTS(STR(?target), "${namespace}")
73
+ )
74
+ }
75
+ GROUP BY ?shape ?target
76
+ ORDER BY ?shape
77
+ `),
78
+ );
79
+
80
+ if (result.type !== "select") return [];
81
+
82
+ return result.bindings
83
+ .filter((b) => Boolean(b.shape))
84
+ .map((b) => ({
85
+ shape: b.shape as string,
86
+ ...(b.target ? { targetClass: b.target } : {}),
87
+ propertyCount: Number(b.n ?? 0),
88
+ }));
89
+ }
90
+
91
+ /** owl:Ontology header row — full URIs. */
92
+ export interface RawOntologyMeta {
93
+ readonly title?: string;
94
+ readonly version?: string;
95
+ readonly imports: readonly string[];
96
+ }
97
+
98
+ /**
99
+ * Read the `owl:Ontology` header declared in a namespace, when present:
100
+ * title (rdfs:label), version (owl:versionInfo), and owl:imports.
101
+ */
102
+ export async function queryOntologyMeta(
103
+ store: Store,
104
+ namespace: string,
105
+ ): Promise<RawOntologyMeta | undefined> {
106
+ const result = await store.query(
107
+ buildQuery(`
108
+ SELECT ?ont ?title ?version ?import
109
+ WHERE {
110
+ ?ont a ${P.owl}Ontology .
111
+ FILTER(STRSTARTS(STR(?ont), "${namespace}"))
112
+ OPTIONAL { ?ont ${P.rdfs}label ?title }
113
+ OPTIONAL { ?ont ${P.owl}versionInfo ?version }
114
+ OPTIONAL { ?ont ${P.owl}imports ?import }
115
+ }
116
+ ORDER BY ?ont
117
+ `),
118
+ );
119
+
120
+ if (result.type !== "select" || result.bindings.length === 0) {
121
+ return undefined;
122
+ }
123
+
124
+ const first = result.bindings[0] as (typeof result.bindings)[number];
125
+ const imports = [
126
+ ...new Set(
127
+ result.bindings
128
+ .map((b) => b.import)
129
+ .filter((i): i is string => Boolean(i)),
130
+ ),
131
+ ].sort();
132
+
133
+ return {
134
+ ...(first.title ? { title: first.title } : {}),
135
+ ...(first.version ? { version: first.version } : {}),
136
+ imports,
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Fetch up to `limit` instance URIs of a class, as concrete entry points
142
+ * for `graph inspect` and domain lookups.
143
+ */
144
+ export async function querySampleInstances(
145
+ store: Store,
146
+ classUri: string,
147
+ limit = 3,
148
+ ): Promise<string[]> {
149
+ const result = await store.query(
150
+ buildQuery(`
151
+ SELECT ?s
152
+ WHERE { ?s a <${classUri}> }
153
+ ORDER BY ?s
154
+ LIMIT ${limit}
155
+ `),
156
+ );
157
+
158
+ if (result.type !== "select") return [];
159
+ return result.bindings.map((b) => b.s).filter((s): s is string => Boolean(s));
160
+ }
@@ -1,93 +1,16 @@
1
1
  /**
2
- * MCP tool specs for the ontology domain.
2
+ * MCP tool specs for the ontology domain — ontology_list and
3
+ * ontology_show, compiled from the ontology read stories in
4
+ * `../stories.ts` so both surfaces share formatters and resolution.
3
5
  */
4
6
 
7
+ import { compileReadTool } from "../../shared/stories/index.js";
5
8
  import type { ToolSpec } from "../../shared/ToolSpec.js";
6
- import { listOntologies, showOntology } from "../operations/index.js";
9
+ import { ontologyListStory, ontologyShowStory } from "../stories.js";
7
10
 
8
11
  const specs: readonly ToolSpec[] = [
9
- {
10
- name: "ontology_list",
11
- description:
12
- "List all ontologies loaded in the knowledge graph with class and property counts.",
13
- params: {
14
- condensed: {
15
- type: "boolean",
16
- description: "Token-optimized output",
17
- optional: true,
18
- },
19
- },
20
- readOnly: true,
21
- async execute(rt, { condensed }) {
22
- const result = await listOntologies(rt.store);
23
-
24
- if (condensed) {
25
- const lines = ["## Ontologies", ""];
26
- for (const o of result) {
27
- lines.push(
28
- `- **${o.prefix}:** (${o.namespace}) | classes: ${o.classCount} | properties: ${o.propertyCount}`,
29
- );
30
- }
31
- const text = lines.join("\n");
32
- return {
33
- condensed: true,
34
- text,
35
- tokens: `~${Math.ceil(text.length / 4)}`,
36
- };
37
- }
38
-
39
- return { data: result, meta: { count: result.length } };
40
- },
41
- },
42
- {
43
- name: "ontology_show",
44
- description:
45
- "Show detailed schema for an ontology including classes and properties.",
46
- params: {
47
- prefix: {
48
- type: "string",
49
- description: "Ontology prefix (e.g. 'ds', 'cs')",
50
- optional: false,
51
- },
52
- condensed: {
53
- type: "boolean",
54
- description: "Token-optimized output",
55
- optional: true,
56
- },
57
- },
58
- readOnly: true,
59
- async execute(rt, { prefix, condensed }) {
60
- const result = await showOntology(rt.store, prefix as string);
61
-
62
- if (condensed) {
63
- const lines = [`## ${result.prefix}: (${result.namespace})`, ""];
64
- if (result.classes.length > 0) {
65
- lines.push("### Classes");
66
- for (const c of result.classes) {
67
- const sup = c.superclass ? ` extends ${c.superclass}` : "";
68
- lines.push(`- **${c.label}**${sup}`);
69
- }
70
- lines.push("");
71
- }
72
- if (result.properties.length > 0) {
73
- lines.push("### Properties");
74
- for (const p of result.properties) {
75
- const domain = p.domain ? ` domain: ${p.domain}` : "";
76
- const range = p.range ? ` range: ${p.range}` : "";
77
- lines.push(`- **${p.label}** (${p.type})${domain}${range}`);
78
- }
79
- }
80
- const text = lines.join("\n");
81
- return {
82
- condensed: true,
83
- text,
84
- tokens: `~${Math.ceil(text.length / 4)}`,
85
- };
86
- }
87
-
88
- return { data: result };
89
- },
90
- },
12
+ compileReadTool(ontologyListStory),
13
+ compileReadTool(ontologyShowStory),
91
14
  ];
92
15
 
93
16
  export default specs;
@@ -1,7 +1,7 @@
1
1
  import type { Store } from "@canonical/ke";
2
2
  import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
3
  import { createTestStore, DS_ALL_TTL } from "#testing";
4
- import { PREFIX_MAP } from "../../shared/prefixes.js";
4
+ import { DEFAULT_PREFIX_MAP } from "../../shared/prefixes.js";
5
5
  import listOntologies from "./listOntologies.js";
6
6
 
7
7
  let store: Store;
@@ -22,12 +22,36 @@ describe("listOntologies", () => {
22
22
 
23
23
  const ds = result.find((o) => o.prefix === "ds");
24
24
  expect(ds).toBeDefined();
25
- expect(ds?.namespace).toBe(PREFIX_MAP.ds);
25
+ expect(ds?.namespace).toBe(DEFAULT_PREFIX_MAP.ds);
26
26
  expect(ds?.classCount).toBeGreaterThan(0);
27
- expect(ds?.propertyCount).toBeGreaterThan(0);
27
+ expect(ds?.relationCount).toBeGreaterThan(0);
28
+ expect(ds?.attributeCount).toBeGreaterThan(0);
28
29
  expect(ds?.anatomyCount).toBeGreaterThan(0);
29
30
  });
30
31
 
32
+ it("splits relations from attributes", async () => {
33
+ const result = await listOntologies(store);
34
+ const ds = result.find((o) => o.prefix === "ds");
35
+ // ds:tier is an object property; ds:name is a datatype property.
36
+ expect(ds?.relationCount).toBeGreaterThan(0);
37
+ expect(ds?.attributeCount).toBeGreaterThan(0);
38
+ });
39
+
40
+ it("carries the owl:Ontology header and SHACL shape count", async () => {
41
+ const result = await listOntologies(store);
42
+ const ds = result.find((o) => o.prefix === "ds");
43
+ expect(ds?.title).toBe("Design System Ontology");
44
+ expect(ds?.version).toBe("0.1.0-test");
45
+ expect(ds?.shapeCount).toBeGreaterThan(0);
46
+ });
47
+
48
+ it("omits header fields for namespaces without an owl:Ontology node", async () => {
49
+ const result = await listOntologies(store);
50
+ const cs = result.find((o) => o.prefix === "cs");
51
+ expect(cs?.title).toBeUndefined();
52
+ expect(cs?.version).toBeUndefined();
53
+ });
54
+
31
55
  it("includes cs namespace", async () => {
32
56
  const result = await listOntologies(store);
33
57
  const cs = result.find((o) => o.prefix === "cs");
@@ -36,6 +60,59 @@ describe("listOntologies", () => {
36
60
  expect(cs?.anatomyCount).toBe(0);
37
61
  });
38
62
 
63
+ it("lists namespaces without a registered prefix", async () => {
64
+ const scoped = await createTestStore({
65
+ ttl: `@prefix owl: <http://www.w3.org/2002/07/owl#> .
66
+ <http://unprefixed.example.org/ontology#Widget> a owl:Class .
67
+ <http://unprefixed.example.org/ontology#partOf> a owl:ObjectProperty .`,
68
+ });
69
+ try {
70
+ const result = await listOntologies(scoped.store);
71
+ const anon = result.find(
72
+ (o) => o.namespace === "http://unprefixed.example.org/ontology#",
73
+ );
74
+ expect(anon).toBeDefined();
75
+ expect(anon?.prefix).toBe("");
76
+ expect(anon?.classCount).toBe(1);
77
+ expect(anon?.relationCount).toBe(1);
78
+ } finally {
79
+ scoped.cleanup();
80
+ }
81
+ });
82
+
83
+ it("derives namespaces from short path-only URIs", async () => {
84
+ const scoped = await createTestStore({
85
+ ttl: `@prefix owl: <http://www.w3.org/2002/07/owl#> .
86
+ <http://a/b> a owl:Class .`,
87
+ });
88
+ try {
89
+ const result = await listOntologies(scoped.store);
90
+ expect(result.find((o) => o.namespace === "http://a/")?.classCount).toBe(
91
+ 1,
92
+ );
93
+ } finally {
94
+ scoped.cleanup();
95
+ }
96
+ });
97
+
98
+ it("lists a namespace that only contributes SHACL shapes", async () => {
99
+ const scoped = await createTestStore({
100
+ ttl: `@prefix sh: <http://www.w3.org/ns/shacl#> .
101
+ <http://shapes.example.org/ontology#OnlyShape> a sh:NodeShape .`,
102
+ });
103
+ try {
104
+ const result = await listOntologies(scoped.store);
105
+ const shapeOnly = result.find(
106
+ (o) => o.namespace === "http://shapes.example.org/ontology#",
107
+ );
108
+ expect(shapeOnly).toBeDefined();
109
+ expect(shapeOnly?.shapeCount).toBe(1);
110
+ expect(shapeOnly?.classCount).toBe(0);
111
+ } finally {
112
+ scoped.cleanup();
113
+ }
114
+ });
115
+
39
116
  it("returns sorted by prefix", async () => {
40
117
  const result = await listOntologies(store);
41
118
  const prefixes = result.map((o) => o.prefix);