@canonical/pragma-cli 0.18.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 (439) hide show
  1. package/README.md +377 -0
  2. package/package.json +78 -0
  3. package/src/bin.test.ts +52 -0
  4. package/src/bin.ts +19 -0
  5. package/src/compile-validation.runner.ts +137 -0
  6. package/src/compile-validation.ts +192 -0
  7. package/src/completions/computeSocketPath.test.ts +26 -0
  8. package/src/completions/computeSocketPath.ts +16 -0
  9. package/src/completions/constants.ts +18 -0
  10. package/src/completions/handleQuery.test.ts +93 -0
  11. package/src/completions/handleQuery.ts +30 -0
  12. package/src/completions/index.ts +14 -0
  13. package/src/completions/queryCompletions.test.ts +100 -0
  14. package/src/completions/queryCompletions.ts +61 -0
  15. package/src/completions/querySocket.test.ts +70 -0
  16. package/src/completions/querySocket.ts +44 -0
  17. package/src/completions/startCompletionsServer.test.ts +74 -0
  18. package/src/completions/startCompletionsServer.ts +75 -0
  19. package/src/completions/startCompletionsServer.unit.test.ts +131 -0
  20. package/src/completions/waitForSocket.test.ts +27 -0
  21. package/src/completions/waitForSocket.ts +27 -0
  22. package/src/config/configExists.ts +14 -0
  23. package/src/config/index.ts +6 -0
  24. package/src/config/readConfig.test.ts +152 -0
  25. package/src/config/readConfig.ts +64 -0
  26. package/src/config/resolveConfigPath.test.ts +20 -0
  27. package/src/config/resolveConfigPath.ts +11 -0
  28. package/src/config/types.ts +26 -0
  29. package/src/config/writeConfig.ts +49 -0
  30. package/src/constants.ts +78 -0
  31. package/src/domains/block/blockConfig.ts +53 -0
  32. package/src/domains/block/commands/index.ts +4 -0
  33. package/src/domains/block/commands/list.test.ts +111 -0
  34. package/src/domains/block/commands/list.ts +69 -0
  35. package/src/domains/block/commands/lookup.test.ts +187 -0
  36. package/src/domains/block/commands/lookup.ts +199 -0
  37. package/src/domains/block/formatters/index.ts +4 -0
  38. package/src/domains/block/formatters/list.test.ts +107 -0
  39. package/src/domains/block/formatters/list.ts +64 -0
  40. package/src/domains/block/formatters/lookup.test.ts +317 -0
  41. package/src/domains/block/formatters/lookup.ts +354 -0
  42. package/src/domains/block/formatters/types.ts +16 -0
  43. package/src/domains/block/helpers/index.ts +4 -0
  44. package/src/domains/block/helpers/resolveAspects.test.ts +64 -0
  45. package/src/domains/block/helpers/resolveAspects.ts +35 -0
  46. package/src/domains/block/index.ts +25 -0
  47. package/src/domains/block/mcp/index.ts +2 -0
  48. package/src/domains/block/mcp/specs.ts +199 -0
  49. package/src/domains/block/operations/index.ts +4 -0
  50. package/src/domains/block/operations/list.test.ts +80 -0
  51. package/src/domains/block/operations/list.ts +72 -0
  52. package/src/domains/block/operations/lookup.test.ts +108 -0
  53. package/src/domains/block/operations/lookup.ts +359 -0
  54. package/src/domains/block/orchestration/blockEmptyError.ts +19 -0
  55. package/src/domains/block/orchestration/buildBlockFilters.ts +12 -0
  56. package/src/domains/block/orchestration/enrichBlocks.ts +37 -0
  57. package/src/domains/block/orchestration/index.ts +5 -0
  58. package/src/domains/block/orchestration/resolveBlockList.ts +39 -0
  59. package/src/domains/block/orchestration/resolveBlockLookup.ts +21 -0
  60. package/src/domains/block/types.ts +30 -0
  61. package/src/domains/config/commands/channel.test.ts +101 -0
  62. package/src/domains/config/commands/channel.ts +80 -0
  63. package/src/domains/config/commands/index.ts +4 -0
  64. package/src/domains/config/commands/show.test.ts +61 -0
  65. package/src/domains/config/commands/show.ts +51 -0
  66. package/src/domains/config/commands/tier.test.ts +84 -0
  67. package/src/domains/config/commands/tier.ts +78 -0
  68. package/src/domains/config/formatters/channel.test.ts +56 -0
  69. package/src/domains/config/formatters/channel.ts +34 -0
  70. package/src/domains/config/formatters/index.ts +4 -0
  71. package/src/domains/config/formatters/show.test.ts +126 -0
  72. package/src/domains/config/formatters/show.ts +66 -0
  73. package/src/domains/config/formatters/tier.test.ts +70 -0
  74. package/src/domains/config/formatters/tier.ts +40 -0
  75. package/src/domains/config/index.ts +23 -0
  76. package/src/domains/config/mcp/index.ts +2 -0
  77. package/src/domains/config/mcp/specs.ts +108 -0
  78. package/src/domains/config/operations/index.ts +5 -0
  79. package/src/domains/config/operations/show.test.ts +60 -0
  80. package/src/domains/config/operations/show.ts +42 -0
  81. package/src/domains/config/operations/types.ts +13 -0
  82. package/src/domains/config/operations/validateChannel.test.ts +36 -0
  83. package/src/domains/config/operations/validateChannel.ts +24 -0
  84. package/src/domains/config/operations/validateTier.test.ts +56 -0
  85. package/src/domains/config/operations/validateTier.ts +35 -0
  86. package/src/domains/create/commands/component.test.ts +166 -0
  87. package/src/domains/create/commands/component.ts +129 -0
  88. package/src/domains/create/commands/index.ts +3 -0
  89. package/src/domains/create/commands/package.test.ts +35 -0
  90. package/src/domains/create/commands/package.ts +21 -0
  91. package/src/domains/create/index.ts +15 -0
  92. package/src/domains/create/mcp/index.ts +2 -0
  93. package/src/domains/create/mcp/specs.ts +174 -0
  94. package/src/domains/doctor/commands/doctor.test.ts +75 -0
  95. package/src/domains/doctor/commands/doctor.ts +43 -0
  96. package/src/domains/doctor/commands/index.ts +2 -0
  97. package/src/domains/doctor/formatters/doctor.test.ts +117 -0
  98. package/src/domains/doctor/formatters/doctor.ts +84 -0
  99. package/src/domains/doctor/formatters/index.ts +2 -0
  100. package/src/domains/doctor/index.ts +9 -0
  101. package/src/domains/doctor/mcp/index.ts +2 -0
  102. package/src/domains/doctor/mcp/specs.ts +88 -0
  103. package/src/domains/doctor/operations/checks/checkConfigFile.ts +28 -0
  104. package/src/domains/doctor/operations/checks/checkKeStore.ts +38 -0
  105. package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +65 -0
  106. package/src/domains/doctor/operations/checks/checkNodeVersion.ts +25 -0
  107. package/src/domains/doctor/operations/checks/checkPragmaVersion.ts +20 -0
  108. package/src/domains/doctor/operations/checks/checkShellCompletions.ts +42 -0
  109. package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +64 -0
  110. package/src/domains/doctor/operations/checks/index.ts +8 -0
  111. package/src/domains/doctor/operations/checks.test.ts +151 -0
  112. package/src/domains/doctor/operations/index.ts +3 -0
  113. package/src/domains/doctor/operations/runChecks.test.ts +89 -0
  114. package/src/domains/doctor/operations/runChecks.ts +38 -0
  115. package/src/domains/doctor/operations/types.ts +20 -0
  116. package/src/domains/graph/commands/index.ts +4 -0
  117. package/src/domains/graph/commands/inspect.test.ts +94 -0
  118. package/src/domains/graph/commands/inspect.ts +63 -0
  119. package/src/domains/graph/commands/query.test.ts +92 -0
  120. package/src/domains/graph/commands/query.ts +60 -0
  121. package/src/domains/graph/formatters/index.ts +4 -0
  122. package/src/domains/graph/formatters/inspect.ts +45 -0
  123. package/src/domains/graph/formatters/query.ts +37 -0
  124. package/src/domains/graph/helpers/index.ts +3 -0
  125. package/src/domains/graph/helpers/resolveUri.ts +70 -0
  126. package/src/domains/graph/index.ts +22 -0
  127. package/src/domains/graph/mcp/index.ts +2 -0
  128. package/src/domains/graph/mcp/specs.ts +82 -0
  129. package/src/domains/graph/operations/executeQuery.test.ts +68 -0
  130. package/src/domains/graph/operations/executeQuery.ts +32 -0
  131. package/src/domains/graph/operations/index.ts +4 -0
  132. package/src/domains/graph/operations/inspectUri.test.ts +101 -0
  133. package/src/domains/graph/operations/inspectUri.ts +61 -0
  134. package/src/domains/info/commands/index.ts +4 -0
  135. package/src/domains/info/commands/info.test.ts +88 -0
  136. package/src/domains/info/commands/info.ts +47 -0
  137. package/src/domains/info/commands/upgrade.test.ts +183 -0
  138. package/src/domains/info/commands/upgrade.ts +150 -0
  139. package/src/domains/info/constants.test.ts +22 -0
  140. package/src/domains/info/constants.ts +15 -0
  141. package/src/domains/info/formatters/index.ts +8 -0
  142. package/src/domains/info/formatters/info.test.ts +173 -0
  143. package/src/domains/info/formatters/info.ts +116 -0
  144. package/src/domains/info/formatters/upgrade.test.ts +133 -0
  145. package/src/domains/info/formatters/upgrade.ts +68 -0
  146. package/src/domains/info/index.ts +7 -0
  147. package/src/domains/info/operations/checkRegistryVersion.test.ts +124 -0
  148. package/src/domains/info/operations/checkRegistryVersion.ts +45 -0
  149. package/src/domains/info/operations/collectInfo.test.ts +111 -0
  150. package/src/domains/info/operations/collectInfo.ts +68 -0
  151. package/src/domains/info/operations/collectStoreSummary.test.ts +61 -0
  152. package/src/domains/info/operations/collectStoreSummary.ts +42 -0
  153. package/src/domains/info/operations/index.ts +5 -0
  154. package/src/domains/info/types.test-d.ts +35 -0
  155. package/src/domains/info/types.ts +46 -0
  156. package/src/domains/llm/commands/index.ts +3 -0
  157. package/src/domains/llm/commands/llm.ts +37 -0
  158. package/src/domains/llm/data/commandReference.ts +25 -0
  159. package/src/domains/llm/data/decisionTrees.ts +46 -0
  160. package/src/domains/llm/data/index.ts +4 -0
  161. package/src/domains/llm/formatters/index.ts +3 -0
  162. package/src/domains/llm/formatters/orientation.ts +53 -0
  163. package/src/domains/llm/index.ts +8 -0
  164. package/src/domains/llm/llmCommand.test.ts +93 -0
  165. package/src/domains/llm/mcp/index.ts +2 -0
  166. package/src/domains/llm/mcp/specs.ts +87 -0
  167. package/src/domains/llm/operations/collectContext.ts +47 -0
  168. package/src/domains/llm/operations/index.ts +3 -0
  169. package/src/domains/llm/types.ts +32 -0
  170. package/src/domains/modifier/commands/index.ts +4 -0
  171. package/src/domains/modifier/commands/list.test.ts +57 -0
  172. package/src/domains/modifier/commands/list.ts +33 -0
  173. package/src/domains/modifier/commands/lookup.test.ts +91 -0
  174. package/src/domains/modifier/commands/lookup.ts +105 -0
  175. package/src/domains/modifier/formatters/index.ts +4 -0
  176. package/src/domains/modifier/formatters/list.test.ts +38 -0
  177. package/src/domains/modifier/formatters/list.ts +35 -0
  178. package/src/domains/modifier/formatters/lookup.test.ts +33 -0
  179. package/src/domains/modifier/formatters/lookup.ts +38 -0
  180. package/src/domains/modifier/index.ts +22 -0
  181. package/src/domains/modifier/mcp/index.ts +2 -0
  182. package/src/domains/modifier/mcp/specs.ts +97 -0
  183. package/src/domains/modifier/operations/index.ts +4 -0
  184. package/src/domains/modifier/operations/list.test.ts +39 -0
  185. package/src/domains/modifier/operations/list.ts +41 -0
  186. package/src/domains/modifier/operations/lookup.test.ts +37 -0
  187. package/src/domains/modifier/operations/lookup.ts +57 -0
  188. package/src/domains/modifier/orchestration/index.ts +3 -0
  189. package/src/domains/modifier/orchestration/modifierEmptyError.ts +10 -0
  190. package/src/domains/modifier/orchestration/resolveModifierList.ts +16 -0
  191. package/src/domains/modifier/orchestration/resolveModifierLookup.ts +20 -0
  192. package/src/domains/modifier/types.ts +5 -0
  193. package/src/domains/ontology/commands/index.ts +4 -0
  194. package/src/domains/ontology/commands/list.test.ts +82 -0
  195. package/src/domains/ontology/commands/list.ts +46 -0
  196. package/src/domains/ontology/commands/show.test.ts +103 -0
  197. package/src/domains/ontology/commands/show.ts +66 -0
  198. package/src/domains/ontology/formatters/index.ts +4 -0
  199. package/src/domains/ontology/formatters/list.ts +37 -0
  200. package/src/domains/ontology/formatters/show.ts +74 -0
  201. package/src/domains/ontology/helpers/findNamespace.ts +23 -0
  202. package/src/domains/ontology/helpers/index.ts +7 -0
  203. package/src/domains/ontology/helpers/queryClasses.ts +50 -0
  204. package/src/domains/ontology/helpers/queryProperties.ts +57 -0
  205. package/src/domains/ontology/helpers/resolvePrefix.ts +45 -0
  206. package/src/domains/ontology/index.ts +26 -0
  207. package/src/domains/ontology/mcp/index.ts +2 -0
  208. package/src/domains/ontology/mcp/specs.ts +93 -0
  209. package/src/domains/ontology/operations/index.ts +5 -0
  210. package/src/domains/ontology/operations/listOntologies.test.ts +45 -0
  211. package/src/domains/ontology/operations/listOntologies.ts +101 -0
  212. package/src/domains/ontology/operations/showOntology.test.ts +65 -0
  213. package/src/domains/ontology/operations/showOntology.ts +41 -0
  214. package/src/domains/ontology/operations/showOntologyRaw.test.ts +39 -0
  215. package/src/domains/ontology/operations/showOntologyRaw.ts +50 -0
  216. package/src/domains/setup/commands/all.ts +58 -0
  217. package/src/domains/setup/commands/completions.ts +85 -0
  218. package/src/domains/setup/commands/entrypoints.test.ts +170 -0
  219. package/src/domains/setup/commands/index.ts +6 -0
  220. package/src/domains/setup/commands/lsp.ts +49 -0
  221. package/src/domains/setup/commands/mcp.ts +119 -0
  222. package/src/domains/setup/commands/skills.test.ts +64 -0
  223. package/src/domains/setup/commands/skills.ts +106 -0
  224. package/src/domains/setup/formatters/index.ts +2 -0
  225. package/src/domains/setup/formatters/skills.test.ts +103 -0
  226. package/src/domains/setup/formatters/skills.ts +112 -0
  227. package/src/domains/setup/formatters/types.ts +7 -0
  228. package/src/domains/setup/helpers/completionScripts.test.ts +58 -0
  229. package/src/domains/setup/helpers/completionScripts.ts +92 -0
  230. package/src/domains/setup/helpers/constants.ts +2 -0
  231. package/src/domains/setup/helpers/detectShell.test.ts +48 -0
  232. package/src/domains/setup/helpers/detectShell.ts +20 -0
  233. package/src/domains/setup/helpers/index.ts +12 -0
  234. package/src/domains/setup/helpers/runSetupTask.test.ts +279 -0
  235. package/src/domains/setup/helpers/runSetupTask.ts +229 -0
  236. package/src/domains/setup/index.ts +33 -0
  237. package/src/domains/setup/operations/index.ts +6 -0
  238. package/src/domains/setup/operations/setupAll.test.ts +48 -0
  239. package/src/domains/setup/operations/setupAll.ts +41 -0
  240. package/src/domains/setup/operations/setupCompletions.test.ts +94 -0
  241. package/src/domains/setup/operations/setupCompletions.ts +54 -0
  242. package/src/domains/setup/operations/setupLsp.test.ts +29 -0
  243. package/src/domains/setup/operations/setupLsp.ts +17 -0
  244. package/src/domains/setup/operations/setupMcp.test.ts +115 -0
  245. package/src/domains/setup/operations/setupMcp.ts +108 -0
  246. package/src/domains/setup/operations/setupSkills.test.ts +191 -0
  247. package/src/domains/setup/operations/setupSkills.ts +160 -0
  248. package/src/domains/setup/types.ts +18 -0
  249. package/src/domains/shared/ToolSpec.ts +49 -0
  250. package/src/domains/shared/bootStore.ts +77 -0
  251. package/src/domains/shared/buildQuery.ts +18 -0
  252. package/src/domains/shared/compactUri.test.ts +21 -0
  253. package/src/domains/shared/compactUri.ts +16 -0
  254. package/src/domains/shared/context.ts +15 -0
  255. package/src/domains/shared/contracts.ts +113 -0
  256. package/src/domains/shared/extractLocalName.test.ts +21 -0
  257. package/src/domains/shared/extractLocalName.ts +14 -0
  258. package/src/domains/shared/filters/buildChannelFilter.test.ts +52 -0
  259. package/src/domains/shared/filters/buildChannelFilter.ts +41 -0
  260. package/src/domains/shared/filters/buildFilterConfig.ts +16 -0
  261. package/src/domains/shared/filters/buildFilters.test.ts +33 -0
  262. package/src/domains/shared/filters/buildFilters.ts +30 -0
  263. package/src/domains/shared/filters/buildTierFilter.test.ts +78 -0
  264. package/src/domains/shared/filters/buildTierFilter.ts +69 -0
  265. package/src/domains/shared/filters/describeFilters.ts +14 -0
  266. package/src/domains/shared/filters/index.ts +10 -0
  267. package/src/domains/shared/formatters.ts +35 -0
  268. package/src/domains/shared/lookupMany.ts +45 -0
  269. package/src/domains/shared/namespaces.ts +18 -0
  270. package/src/domains/shared/packages.ts +76 -0
  271. package/src/domains/shared/prefixes.ts +37 -0
  272. package/src/domains/shared/runtime.ts +62 -0
  273. package/src/domains/shared/types.test-d.ts +127 -0
  274. package/src/domains/shared/types.ts +348 -0
  275. package/src/domains/skill/commands/index.ts +2 -0
  276. package/src/domains/skill/commands/list.test.ts +111 -0
  277. package/src/domains/skill/commands/list.ts +69 -0
  278. package/src/domains/skill/formatters/index.ts +2 -0
  279. package/src/domains/skill/formatters/list.test.ts +140 -0
  280. package/src/domains/skill/formatters/list.ts +119 -0
  281. package/src/domains/skill/formatters/types.ts +8 -0
  282. package/src/domains/skill/helpers/index.ts +6 -0
  283. package/src/domains/skill/helpers/parseFrontmatter.test.ts +122 -0
  284. package/src/domains/skill/helpers/parseFrontmatter.ts +112 -0
  285. package/src/domains/skill/helpers/resolveSkillSources.ts +34 -0
  286. package/src/domains/skill/index.ts +19 -0
  287. package/src/domains/skill/mcp/index.ts +2 -0
  288. package/src/domains/skill/mcp/specs.ts +38 -0
  289. package/src/domains/skill/operations/discover.test.ts +145 -0
  290. package/src/domains/skill/operations/discover.ts +68 -0
  291. package/src/domains/skill/operations/index.ts +4 -0
  292. package/src/domains/skill/operations/list.test.ts +68 -0
  293. package/src/domains/skill/operations/list.ts +47 -0
  294. package/src/domains/skill/types.ts +25 -0
  295. package/src/domains/standard/commands/categories.test.ts +70 -0
  296. package/src/domains/standard/commands/categories.ts +48 -0
  297. package/src/domains/standard/commands/index.ts +5 -0
  298. package/src/domains/standard/commands/list.test.ts +105 -0
  299. package/src/domains/standard/commands/list.ts +81 -0
  300. package/src/domains/standard/commands/lookup.test.ts +135 -0
  301. package/src/domains/standard/commands/lookup.ts +127 -0
  302. package/src/domains/standard/formatters/categories.test.ts +44 -0
  303. package/src/domains/standard/formatters/categories.ts +38 -0
  304. package/src/domains/standard/formatters/index.ts +6 -0
  305. package/src/domains/standard/formatters/list.test.ts +166 -0
  306. package/src/domains/standard/formatters/list.ts +156 -0
  307. package/src/domains/standard/formatters/lookup.test.ts +95 -0
  308. package/src/domains/standard/formatters/lookup.ts +86 -0
  309. package/src/domains/standard/formatters/types.ts +31 -0
  310. package/src/domains/standard/index.ts +32 -0
  311. package/src/domains/standard/mcp/index.ts +2 -0
  312. package/src/domains/standard/mcp/specs.ts +197 -0
  313. package/src/domains/standard/operations/categories.test.ts +61 -0
  314. package/src/domains/standard/operations/categories.ts +38 -0
  315. package/src/domains/standard/operations/index.ts +5 -0
  316. package/src/domains/standard/operations/list.test.ts +75 -0
  317. package/src/domains/standard/operations/list.ts +64 -0
  318. package/src/domains/standard/operations/lookup.test.ts +58 -0
  319. package/src/domains/standard/operations/lookup.ts +142 -0
  320. package/src/domains/standard/orchestration/buildStandardFilters.ts +11 -0
  321. package/src/domains/standard/orchestration/index.ts +4 -0
  322. package/src/domains/standard/orchestration/resolveStandardList.ts +42 -0
  323. package/src/domains/standard/orchestration/resolveStandardLookup.ts +20 -0
  324. package/src/domains/standard/orchestration/standardEmptyError.ts +19 -0
  325. package/src/domains/standard/types.ts +15 -0
  326. package/src/domains/tier/commands/index.ts +3 -0
  327. package/src/domains/tier/commands/list.test.ts +67 -0
  328. package/src/domains/tier/commands/list.ts +43 -0
  329. package/src/domains/tier/formatters/index.ts +3 -0
  330. package/src/domains/tier/formatters/list.test.ts +33 -0
  331. package/src/domains/tier/formatters/list.ts +40 -0
  332. package/src/domains/tier/index.ts +17 -0
  333. package/src/domains/tier/mcp/index.ts +2 -0
  334. package/src/domains/tier/mcp/specs.ts +38 -0
  335. package/src/domains/tier/operations/index.ts +3 -0
  336. package/src/domains/tier/operations/list.test.ts +32 -0
  337. package/src/domains/tier/operations/list.ts +33 -0
  338. package/src/domains/token/commands/add-config.test.ts +68 -0
  339. package/src/domains/token/commands/add-config.ts +62 -0
  340. package/src/domains/token/commands/index.ts +5 -0
  341. package/src/domains/token/commands/list.test.ts +82 -0
  342. package/src/domains/token/commands/list.ts +45 -0
  343. package/src/domains/token/commands/lookup.test.ts +125 -0
  344. package/src/domains/token/commands/lookup.ts +121 -0
  345. package/src/domains/token/formatters/index.ts +4 -0
  346. package/src/domains/token/formatters/list.test.ts +37 -0
  347. package/src/domains/token/formatters/list.ts +37 -0
  348. package/src/domains/token/formatters/lookup.test.ts +61 -0
  349. package/src/domains/token/formatters/lookup.ts +72 -0
  350. package/src/domains/token/index.ts +32 -0
  351. package/src/domains/token/mcp/index.ts +2 -0
  352. package/src/domains/token/mcp/specs.ts +145 -0
  353. package/src/domains/token/operations/add-config.test.ts +68 -0
  354. package/src/domains/token/operations/add-config.ts +61 -0
  355. package/src/domains/token/operations/index.ts +7 -0
  356. package/src/domains/token/operations/list.test.ts +50 -0
  357. package/src/domains/token/operations/list.ts +52 -0
  358. package/src/domains/token/operations/lookup.test.ts +42 -0
  359. package/src/domains/token/operations/lookup.ts +66 -0
  360. package/src/domains/token/orchestration/index.ts +3 -0
  361. package/src/domains/token/orchestration/resolveTokenList.ts +17 -0
  362. package/src/domains/token/orchestration/resolveTokenLookup.ts +20 -0
  363. package/src/domains/token/orchestration/tokenEmptyError.ts +17 -0
  364. package/src/domains/token/types.ts +6 -0
  365. package/src/error/PragmaError.test.ts +121 -0
  366. package/src/error/PragmaError.ts +164 -0
  367. package/src/error/constants.ts +12 -0
  368. package/src/error/index.ts +4 -0
  369. package/src/error/types.ts +41 -0
  370. package/src/index.ts +141 -0
  371. package/src/mcp/createMcpServer.test.ts +41 -0
  372. package/src/mcp/createMcpServer.ts +53 -0
  373. package/src/mcp/error/buildRecovery.test.ts +37 -0
  374. package/src/mcp/error/buildRecovery.ts +17 -0
  375. package/src/mcp/error/index.ts +12 -0
  376. package/src/mcp/error/serializeError.test.ts +121 -0
  377. package/src/mcp/error/serializeError.ts +31 -0
  378. package/src/mcp/error/serializeErrorPayload.test.ts +38 -0
  379. package/src/mcp/error/serializeErrorPayload.ts +27 -0
  380. package/src/mcp/error/types.ts +51 -0
  381. package/src/mcp/index.ts +15 -0
  382. package/src/mcp/registerResources.test.ts +236 -0
  383. package/src/mcp/registerResources.ts +303 -0
  384. package/src/mcp/runMcpServer.test.ts +66 -0
  385. package/src/mcp/runMcpServer.ts +24 -0
  386. package/src/mcp/tools/index.ts +55 -0
  387. package/src/mcp/tools/registerFromSpec.ts +97 -0
  388. package/src/mcp/tools/registerTools.test.ts +1124 -0
  389. package/src/mcp/types.ts +62 -0
  390. package/src/mcp/utils/estimateTokens.test.ts +14 -0
  391. package/src/mcp/utils/estimateTokens.ts +9 -0
  392. package/src/mcp/utils/index.ts +11 -0
  393. package/src/mcp/utils/wrapTool.test.ts +108 -0
  394. package/src/mcp/utils/wrapTool.ts +81 -0
  395. package/src/package-manager/constants.ts +29 -0
  396. package/src/package-manager/detectInstallSource.test.ts +23 -0
  397. package/src/package-manager/detectInstallSource.ts +111 -0
  398. package/src/package-manager/detectLocalInstall.test.ts +16 -0
  399. package/src/package-manager/detectLocalInstall.ts +43 -0
  400. package/src/package-manager/detectPackageManager.test.ts +81 -0
  401. package/src/package-manager/detectPackageManager.ts +30 -0
  402. package/src/package-manager/index.ts +6 -0
  403. package/src/package-manager/types.ts +12 -0
  404. package/src/pipeline/collectCommands.test.ts +37 -0
  405. package/src/pipeline/collectCommands.ts +47 -0
  406. package/src/pipeline/constants.ts +14 -0
  407. package/src/pipeline/createProgram.test.ts +112 -0
  408. package/src/pipeline/createProgram.ts +70 -0
  409. package/src/pipeline/formatTerminal.test.ts +43 -0
  410. package/src/pipeline/formatTerminal.ts +53 -0
  411. package/src/pipeline/index.ts +19 -0
  412. package/src/pipeline/mapExitCode.test.ts +41 -0
  413. package/src/pipeline/mapExitCode.ts +12 -0
  414. package/src/pipeline/parseGlobalFlags.ts +21 -0
  415. package/src/pipeline/renderError.test.ts +151 -0
  416. package/src/pipeline/renderError.ts +114 -0
  417. package/src/pipeline/resolveCommandKind.test.ts +68 -0
  418. package/src/pipeline/resolveCommandKind.ts +71 -0
  419. package/src/pipeline/runCli.orchestration.test.ts +418 -0
  420. package/src/pipeline/runCli.test.ts +70 -0
  421. package/src/pipeline/runCli.ts +215 -0
  422. package/src/pipeline/types.ts +17 -0
  423. package/src/testing/cli.ts +43 -0
  424. package/src/testing/createTestMcpClient.ts +64 -0
  425. package/src/testing/dsFixtures.ts +506 -0
  426. package/src/testing/fixtures/canonical-config.json +4 -0
  427. package/src/testing/fixtures/canonical.ttl +437 -0
  428. package/src/testing/fixtures/filtered-config.json +4 -0
  429. package/src/testing/fixtures.ts +34 -0
  430. package/src/testing/helpers/assertParity.ts +28 -0
  431. package/src/testing/helpers/createTestMcpClient.ts +40 -0
  432. package/src/testing/helpers/createTestRuntime.ts +67 -0
  433. package/src/testing/index.ts +8 -0
  434. package/src/testing/integration/agent-session.test.ts +148 -0
  435. package/src/testing/integration/boot.test.ts +67 -0
  436. package/src/testing/integration/mcp-surface.test.ts +574 -0
  437. package/src/testing/integration/parity.test.ts +192 -0
  438. package/src/testing/store.ts +39 -0
  439. package/src/testing/types.ts +20 -0
@@ -0,0 +1,58 @@
1
+ import type { Store } from "@canonical/ke";
2
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+ import { PragmaError } from "#error";
4
+ import { createTestStore, DS_ALL_TTL } from "#testing";
5
+ import lookupStandard from "./lookup.js";
6
+
7
+ let store: Store;
8
+ let cleanup: () => void;
9
+
10
+ beforeAll(async () => {
11
+ const result = await createTestStore({ ttl: DS_ALL_TTL });
12
+ store = result.store;
13
+ cleanup = result.cleanup;
14
+ });
15
+
16
+ afterAll(() => cleanup());
17
+
18
+ describe("lookupStandard", () => {
19
+ it("returns detailed data with dos and donts", async () => {
20
+ const result = await lookupStandard(
21
+ store,
22
+ "react/component/folder-structure",
23
+ );
24
+ expect(result.name).toBe("react/component/folder-structure");
25
+ expect(result.category).toBe("react");
26
+ expect(result.dos.length).toBeGreaterThan(0);
27
+ expect(result.donts.length).toBeGreaterThan(0);
28
+ });
29
+
30
+ it("throws PragmaError.notFound for unknown standard", async () => {
31
+ await expect(lookupStandard(store, "nonexistent")).rejects.toThrow(
32
+ PragmaError,
33
+ );
34
+
35
+ try {
36
+ await lookupStandard(store, "nonexistent");
37
+ } catch (e) {
38
+ expect((e as PragmaError).code).toBe("ENTITY_NOT_FOUND");
39
+ }
40
+ });
41
+
42
+ it("resolves prefixed IRIs and compacts extends", async () => {
43
+ const result = await lookupStandard(store, "cs:react_props");
44
+ expect(result.name).toBe("react/component/props");
45
+ expect(result.extends).toBe("cs:react_folder");
46
+ });
47
+
48
+ it("resolves full IRIs", async () => {
49
+ const result = await lookupStandard(
50
+ store,
51
+ "http://pragma.canonical.com/codestandards#react_props",
52
+ );
53
+ expect(result.name).toBe("react/component/props");
54
+ expect(result.uri).toBe(
55
+ "http://pragma.canonical.com/codestandards#react_props",
56
+ );
57
+ });
58
+ });
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Look up detailed information for a single code standard by name.
3
+ *
4
+ * Queries the base standard data plus its dos and donts code blocks,
5
+ * then assembles a {@link StandardDetailed} object.
6
+ *
7
+ * @param store - ke store to query
8
+ * @param name - standard name (e.g. "react/component/folder-structure")
9
+ * @returns full standard detail including dos/donts code blocks
10
+ * @throws PragmaError.notFound if the standard does not exist
11
+ * @note Queries ke store
12
+ */
13
+
14
+ import type { Store, URI } from "@canonical/ke";
15
+ import { escapeSparqlValue } from "@canonical/ke";
16
+ import { PragmaError } from "#error";
17
+ import resolveUri from "../../graph/helpers/resolveUri.js";
18
+ import { buildQuery } from "../../shared/buildQuery.js";
19
+ import compactUri from "../../shared/compactUri.js";
20
+ import { P } from "../../shared/prefixes.js";
21
+ import type { CodeBlock, StandardDetailed } from "../../shared/types.js";
22
+
23
+ export default async function lookupStandard(
24
+ store: Store,
25
+ nameOrUri: string,
26
+ ): Promise<StandardDetailed> {
27
+ const subjectClause = buildLookupSubjectClause(nameOrUri, store.prefixes);
28
+ const bindClause =
29
+ subjectClause === null ? "" : `BIND(${subjectClause} AS ?standard)`;
30
+ const matchClause =
31
+ subjectClause === null
32
+ ? `?standard ${P.cs}name ${escapeSparqlValue(nameOrUri)} .`
33
+ : "";
34
+
35
+ const baseResult = await store.query(
36
+ buildQuery(`
37
+ SELECT ?standard ?name ?categoryName ?description ?extends
38
+ WHERE {
39
+ ${bindClause}
40
+ ?standard a ${P.cs}CodeStandard ;
41
+ ${P.cs}name ?name ;
42
+ ${P.cs}description ?description .
43
+ ${matchClause}
44
+ OPTIONAL {
45
+ ?standard ${P.cs}hasCategory ?cat .
46
+ ?cat ${P.cs}slug ?categoryName .
47
+ }
48
+ OPTIONAL { ?standard ${P.cs}extends ?extends }
49
+ }
50
+ LIMIT 1
51
+ `),
52
+ );
53
+
54
+ if (baseResult.type !== "select" || baseResult.bindings.length === 0) {
55
+ throw PragmaError.notFound("standard", nameOrUri, {
56
+ recovery: {
57
+ message: "List available standards.",
58
+ cli: "pragma standard list",
59
+ mcp: { tool: "standard_list" },
60
+ },
61
+ });
62
+ }
63
+
64
+ // Safe: length check above guarantees bindings[0] exists
65
+ const base = baseResult.bindings[0] as (typeof baseResult.bindings)[number];
66
+ const standardUri = base.standard;
67
+
68
+ // Fetch dos (cs:do → cs:Example with cs:description, cs:language, cs:code)
69
+ const dosResult = await store.query(
70
+ buildQuery(`
71
+ SELECT ?description ?language ?code
72
+ WHERE {
73
+ <${standardUri}> ${P.cs}do ?example .
74
+ OPTIONAL { ?example ${P.cs}description ?description }
75
+ OPTIONAL { ?example ${P.cs}language ?language }
76
+ OPTIONAL { ?example ${P.cs}code ?code }
77
+ }
78
+ `),
79
+ );
80
+
81
+ const dos: CodeBlock[] =
82
+ dosResult.type === "select"
83
+ ? dosResult.bindings.map((b) => ({
84
+ language: b.language ?? "typescript",
85
+ code: b.code ?? "",
86
+ caption: b.description,
87
+ }))
88
+ : [];
89
+
90
+ // Fetch donts (cs:dont → cs:Example with cs:description, cs:language, cs:code)
91
+ const dontsResult = await store.query(
92
+ buildQuery(`
93
+ SELECT ?description ?language ?code
94
+ WHERE {
95
+ <${standardUri}> ${P.cs}dont ?example .
96
+ OPTIONAL { ?example ${P.cs}description ?description }
97
+ OPTIONAL { ?example ${P.cs}language ?language }
98
+ OPTIONAL { ?example ${P.cs}code ?code }
99
+ }
100
+ `),
101
+ );
102
+
103
+ const donts: CodeBlock[] =
104
+ dontsResult.type === "select"
105
+ ? dontsResult.bindings.map((b) => ({
106
+ language: b.language ?? "typescript",
107
+ code: b.code ?? "",
108
+ caption: b.description,
109
+ }))
110
+ : [];
111
+
112
+ return {
113
+ uri: (standardUri ?? "") as URI,
114
+ name: base.name ?? nameOrUri,
115
+ category: base.categoryName ?? "",
116
+ description: base.description ?? "",
117
+ extends: base.extends
118
+ ? compactUri(base.extends, store.prefixes)
119
+ : undefined,
120
+ dos,
121
+ donts,
122
+ };
123
+ }
124
+
125
+ function buildLookupSubjectClause(
126
+ query: string,
127
+ prefixes: Readonly<Record<string, string>>,
128
+ ): string | null {
129
+ if (!looksLikeUri(query)) {
130
+ return null;
131
+ }
132
+
133
+ return `<${resolveUri(query, prefixes)}>`;
134
+ }
135
+
136
+ function looksLikeUri(query: string): boolean {
137
+ return (
138
+ query.startsWith("http://") ||
139
+ query.startsWith("https://") ||
140
+ query.includes(":")
141
+ );
142
+ }
@@ -0,0 +1,11 @@
1
+ import type { StandardListFilters } from "../../shared/types.js";
2
+
3
+ export default function buildStandardFilters(params: {
4
+ category?: string;
5
+ search?: string;
6
+ }): StandardListFilters {
7
+ return {
8
+ category: params.category,
9
+ search: params.search,
10
+ };
11
+ }
@@ -0,0 +1,4 @@
1
+ export { default as buildStandardFilters } from "./buildStandardFilters.js";
2
+ export { default as resolveStandardList } from "./resolveStandardList.js";
3
+ export { default as resolveStandardLookup } from "./resolveStandardLookup.js";
4
+ export { default as standardEmptyError } from "./standardEmptyError.js";
@@ -0,0 +1,42 @@
1
+ import type { ListParams } from "../../shared/contracts.js";
2
+ import type { PragmaRuntime } from "../../shared/runtime.js";
3
+ import type { Disclosure, StandardListFilters } from "../../shared/types.js";
4
+ import { listStandards, lookupStandard } from "../operations/index.js";
5
+ import type { StandardListResolution } from "../types.js";
6
+ import buildStandardFilters from "./buildStandardFilters.js";
7
+ import standardEmptyError from "./standardEmptyError.js";
8
+
9
+ export default async function resolveStandardList(
10
+ rt: Pick<PragmaRuntime, "store">,
11
+ params: ListParams & StandardListFilters,
12
+ ): Promise<StandardListResolution> {
13
+ const filters = buildStandardFilters(params);
14
+ const items = await listStandards(rt.store, filters);
15
+
16
+ if (items.length === 0) {
17
+ throw standardEmptyError(filters);
18
+ }
19
+
20
+ const disclosure: Disclosure = params.detailed
21
+ ? { level: "detailed" }
22
+ : params.digest
23
+ ? { level: "digest" }
24
+ : { level: "summary" };
25
+
26
+ const details =
27
+ disclosure.level === "summary"
28
+ ? undefined
29
+ : await Promise.all(
30
+ items.map((item) =>
31
+ lookupStandard(rt.store, item.name).catch(() => null),
32
+ ),
33
+ );
34
+
35
+ return {
36
+ params,
37
+ items,
38
+ filters,
39
+ disclosure,
40
+ details,
41
+ };
42
+ }
@@ -0,0 +1,20 @@
1
+ import type { LookupContract, LookupResult } from "../../shared/contracts.js";
2
+ import lookupMany from "../../shared/lookupMany.js";
3
+ import type { PragmaRuntime } from "../../shared/runtime.js";
4
+ import type { StandardDetailed } from "../../shared/types.js";
5
+ import { lookupStandard } from "../operations/index.js";
6
+
7
+ export default async function resolveStandardLookup(
8
+ store: Pick<PragmaRuntime, "store">["store"],
9
+ queries: readonly string[],
10
+ ): Promise<LookupContract<StandardDetailed>> {
11
+ const result: LookupResult<StandardDetailed> = await lookupMany(
12
+ queries,
13
+ (query) => lookupStandard(store, query),
14
+ );
15
+
16
+ return {
17
+ params: { names: queries },
18
+ result,
19
+ };
20
+ }
@@ -0,0 +1,19 @@
1
+ import { PragmaError } from "#error";
2
+ import type { StandardListFilters } from "../../shared/types.js";
3
+
4
+ export default function standardEmptyError(
5
+ filters: StandardListFilters,
6
+ ): PragmaError {
7
+ const active: Record<string, string> = {};
8
+ if (filters.category) active.category = filters.category;
9
+ if (filters.search) active.search = filters.search;
10
+
11
+ return PragmaError.emptyResults("standard", {
12
+ filters: Object.keys(active).length > 0 ? active : undefined,
13
+ recovery: {
14
+ message: "List all standards without filters.",
15
+ cli: "pragma standard list",
16
+ mcp: { tool: "standard_list" },
17
+ },
18
+ });
19
+ }
@@ -0,0 +1,15 @@
1
+ import type { ListParams } from "../shared/contracts.js";
2
+ import type {
3
+ Disclosure,
4
+ StandardDetailed,
5
+ StandardListFilters,
6
+ StandardSummary,
7
+ } from "../shared/types.js";
8
+
9
+ export interface StandardListResolution {
10
+ readonly params: ListParams & StandardListFilters;
11
+ readonly items: readonly StandardSummary[];
12
+ readonly filters: StandardListFilters;
13
+ readonly disclosure: Disclosure;
14
+ readonly details?: readonly (StandardDetailed | null)[];
15
+ }
@@ -0,0 +1,3 @@
1
+ /** @module Re-exports tier command builders (`list`). */
2
+
3
+ export { default as listCommand } from "./list.js";
@@ -0,0 +1,67 @@
1
+ import type { CommandOutputResult } from "@canonical/cli-core";
2
+ import type { Store } from "@canonical/ke";
3
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
4
+ import { createTestStore, DS_ALL_TTL } from "#testing";
5
+ import type { PragmaContext } from "../../shared/context.js";
6
+ import listCommand from "./list.js";
7
+
8
+ let store: Store;
9
+ let cleanup: () => void;
10
+
11
+ beforeAll(async () => {
12
+ const result = await createTestStore({ ttl: DS_ALL_TTL });
13
+ store = result.store;
14
+ cleanup = result.cleanup;
15
+ });
16
+
17
+ afterAll(() => cleanup());
18
+
19
+ function makeCtx(
20
+ overrides?: Partial<PragmaContext["globalFlags"]>,
21
+ ): PragmaContext {
22
+ return {
23
+ cwd: "/tmp",
24
+ store,
25
+ config: { tier: undefined, channel: "normal" },
26
+ globalFlags: {
27
+ llm: false,
28
+ format: "text",
29
+ verbose: false,
30
+ ...overrides,
31
+ },
32
+ };
33
+ }
34
+
35
+ describe("tier list command", () => {
36
+ it("returns tiers with hierarchy", async () => {
37
+ const ctx = makeCtx();
38
+ const cmd = listCommand(ctx);
39
+ const result = await cmd.execute({}, ctx);
40
+ expect(result.tag).toBe("output");
41
+
42
+ const output = result as CommandOutputResult;
43
+ const text = output.render.plain(output.value);
44
+ expect(text).toContain("global");
45
+ expect(text).toContain("apps");
46
+ expect(text).toContain("apps/lxd");
47
+ });
48
+
49
+ it("renders flat tier list without parent references", async () => {
50
+ const ctx = makeCtx();
51
+ const cmd = listCommand(ctx);
52
+ const result = await cmd.execute({}, ctx);
53
+ const output = result as CommandOutputResult;
54
+ const text = output.render.plain(output.value);
55
+ expect(text).not.toContain("(parent:");
56
+ });
57
+
58
+ it("renders LLM format with --llm", async () => {
59
+ const ctx = makeCtx({ llm: true });
60
+ const cmd = listCommand(ctx);
61
+ const result = await cmd.execute({}, ctx);
62
+ const output = result as CommandOutputResult;
63
+ const text = output.render.plain(output.value);
64
+ expect(text).toContain("## Tiers");
65
+ expect(text).toContain("**global**");
66
+ });
67
+ });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Wires the `pragma tier list` CLI command.
3
+ *
4
+ * Lists all tiers defined in the design system ontology. Throws a
5
+ * structured recovery error when no tiers are found.
6
+ */
7
+
8
+ import {
9
+ type CommandDefinition,
10
+ createOutputResult,
11
+ } from "@canonical/cli-core";
12
+ import { PragmaError } from "#error";
13
+ import type { PragmaContext } from "../../shared/context.js";
14
+ import { selectFormatter } from "../../shared/formatters.js";
15
+ import { listFormatters } from "../formatters/index.js";
16
+ import { listTiers } from "../operations/index.js";
17
+
18
+ export default function listCommand(ctx: PragmaContext): CommandDefinition {
19
+ return {
20
+ path: ["tier", "list"],
21
+ description: "List all tiers in the design system ontology",
22
+ parameters: [],
23
+ meta: {
24
+ examples: ["pragma tier list", "pragma tier list --llm"],
25
+ },
26
+ async execute() {
27
+ const tiers = await listTiers(ctx.store);
28
+
29
+ if (tiers.length === 0) {
30
+ throw PragmaError.emptyResults("tier", {
31
+ recovery: {
32
+ message:
33
+ "Ensure design system packages are installed: bun add -D @canonical/ds-global",
34
+ },
35
+ });
36
+ }
37
+
38
+ return createOutputResult(tiers, {
39
+ plain: selectFormatter(ctx, listFormatters),
40
+ });
41
+ },
42
+ };
43
+ }
@@ -0,0 +1,3 @@
1
+ /** @module Re-exports tier formatters (`listFormatters`). */
2
+
3
+ export { default as listFormatters } from "./list.js";
@@ -0,0 +1,33 @@
1
+ import type { URI } from "@canonical/ke";
2
+ import { describe, expect, it } from "vitest";
3
+ import type { TierEntry } from "../../shared/types.js";
4
+ import formatters from "./list.js";
5
+
6
+ const TIERS: TierEntry[] = [
7
+ { uri: "http://example.com/t1" as URI, path: "apps", depth: 0 },
8
+ { uri: "http://example.com/t2" as URI, path: "apps/lxd", depth: 0 },
9
+ { uri: "http://example.com/t3" as URI, path: "global", depth: 0 },
10
+ ];
11
+
12
+ describe("tier list formatters", () => {
13
+ it("plain renders flat tier names", () => {
14
+ const text = formatters.plain(TIERS);
15
+ expect(text).toContain("global");
16
+ expect(text).toContain("apps");
17
+ expect(text).toContain("apps/lxd");
18
+ });
19
+
20
+ it("plain renders one tier per line", () => {
21
+ const text = formatters.plain(TIERS);
22
+ const lines = text.split("\n").filter(Boolean);
23
+ expect(lines).toHaveLength(3);
24
+ });
25
+
26
+ it("llm renders markdown heading and bold paths", () => {
27
+ const text = formatters.llm(TIERS);
28
+ expect(text).toContain("## Tiers");
29
+ expect(text).toContain("- **global**");
30
+ expect(text).toContain("- **apps**");
31
+ expect(text).toContain("- **apps/lxd**");
32
+ });
33
+ });
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Three-mode formatter for `pragma tier list` output.
3
+ *
4
+ * - **plain** — indented terminal text showing tier hierarchy with
5
+ * optional parent annotations.
6
+ * - **llm** — condensed Markdown consumed by LLM agents and reused
7
+ * by the MCP adapter when `condensed: true`.
8
+ * - **json** — structured JSON array for programmatic consumption.
9
+ */
10
+
11
+ import type { Formatters } from "../../shared/formatters.js";
12
+ import type { TierEntry } from "../../shared/types.js";
13
+
14
+ const formatters: Formatters<TierEntry[]> = {
15
+ plain: (tiers) => {
16
+ const lines: string[] = [];
17
+ for (const t of tiers) {
18
+ const indent = " ".repeat(t.depth);
19
+ const parent = t.parent ? ` (parent: ${t.parent})` : "";
20
+ lines.push(`${indent}${t.path}${parent}`);
21
+ }
22
+ return lines.join("\n");
23
+ },
24
+
25
+ llm: (tiers) => {
26
+ const lines: string[] = [];
27
+ lines.push("## Tiers");
28
+ lines.push("");
29
+ for (const t of tiers) {
30
+ const indent = " ".repeat(t.depth);
31
+ const parent = t.parent ? ` (parent: ${t.parent})` : "";
32
+ lines.push(`${indent}- **${t.path}**${parent}`);
33
+ }
34
+ return lines.join("\n");
35
+ },
36
+
37
+ json: (tiers) => JSON.stringify(tiers, null, 2),
38
+ };
39
+
40
+ export default formatters;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @module Tier domain — CLI commands and operations.
3
+ *
4
+ * Commands: `pragma tier list`.
5
+ * Operations: {@link listTiers}.
6
+ */
7
+
8
+ import type { CommandDefinition } from "@canonical/cli-core";
9
+ import type { PragmaContext } from "../shared/context.js";
10
+ import { listCommand } from "./commands/index.js";
11
+
12
+ export function commands(ctx: PragmaContext): CommandDefinition[] {
13
+ return [listCommand(ctx)];
14
+ }
15
+
16
+ export { specs as mcpSpecs } from "./mcp/index.js";
17
+ export { listTiers } from "./operations/index.js";
@@ -0,0 +1,2 @@
1
+ /** @module Tier domain MCP barrel — tier_list. */
2
+ export { default as specs } from "./specs.js";
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MCP tool specs for the tier domain.
3
+ */
4
+
5
+ import type { ToolSpec } from "../../shared/ToolSpec.js";
6
+ import { listFormatters as tierListFmt } from "../formatters/index.js";
7
+ import { listTiers } from "../operations/index.js";
8
+
9
+ const specs: readonly ToolSpec[] = [
10
+ {
11
+ name: "tier_list",
12
+ description: "List all tiers in the design system ontology with hierarchy.",
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 listTiers(rt.store);
23
+
24
+ if (condensed) {
25
+ const text = tierListFmt.llm(result);
26
+ return {
27
+ condensed: true,
28
+ text,
29
+ tokens: `~${Math.ceil(text.length / 4)}`,
30
+ };
31
+ }
32
+
33
+ return { data: result, meta: { count: result.length } };
34
+ },
35
+ },
36
+ ];
37
+
38
+ export default specs;
@@ -0,0 +1,3 @@
1
+ /** @module Re-exports tier operations (`listTiers`). */
2
+
3
+ export { default as listTiers } from "./list.js";
@@ -0,0 +1,32 @@
1
+ import type { Store } from "@canonical/ke";
2
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
3
+ import { createTestStore, DS_ALL_TTL } from "#testing";
4
+ import listTiers from "./list.js";
5
+
6
+ let store: Store;
7
+ let cleanup: () => void;
8
+
9
+ beforeAll(async () => {
10
+ const result = await createTestStore({ ttl: DS_ALL_TTL });
11
+ store = result.store;
12
+ cleanup = result.cleanup;
13
+ });
14
+
15
+ afterAll(() => cleanup());
16
+
17
+ describe("listTiers", () => {
18
+ it("returns all tiers from the ontology", async () => {
19
+ const result = await listTiers(store);
20
+ const paths = result.map((t) => t.path);
21
+ expect(paths).toContain("global");
22
+ expect(paths).toContain("apps");
23
+ expect(paths).toContain("apps/lxd");
24
+ });
25
+
26
+ it("returns sorted by name", async () => {
27
+ const result = await listTiers(store);
28
+ const paths = result.map((t) => t.path);
29
+ const sorted = [...paths].sort();
30
+ expect(paths).toEqual(sorted);
31
+ });
32
+ });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Lists all tiers defined in the design system ontology, ordered by name.
3
+ *
4
+ * @param store - ke store to query
5
+ * @returns array of tier entries, empty when none exist
6
+ * @note Queries ke store
7
+ */
8
+
9
+ import type { Store, URI } from "@canonical/ke";
10
+ import { buildQuery } from "../../shared/buildQuery.js";
11
+ import { P } from "../../shared/prefixes.js";
12
+ import type { TierEntry } from "../../shared/types.js";
13
+
14
+ export default async function listTiers(store: Store): Promise<TierEntry[]> {
15
+ const result = await store.query(
16
+ buildQuery(`
17
+ SELECT ?tier ?name
18
+ WHERE {
19
+ ?tier a ${P.ds}Tier ;
20
+ ${P.ds}name ?name .
21
+ }
22
+ ORDER BY ?name
23
+ `),
24
+ );
25
+
26
+ if (result.type !== "select") return [];
27
+
28
+ return result.bindings.map((b) => ({
29
+ uri: (b.tier ?? "") as URI,
30
+ path: b.name ?? "",
31
+ depth: 0,
32
+ }));
33
+ }