@canonical/pragma-cli 0.27.1-experimental.0 → 0.30.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 (344) hide show
  1. package/README.md +67 -15
  2. package/dist/pragma +0 -0
  3. package/package.json +16 -17
  4. package/src/config/defaultConfig.test.ts +33 -0
  5. package/src/config/defaultConfig.ts +59 -0
  6. package/src/config/defaults.json +17 -0
  7. package/src/config/findProjectConfigPath.test.ts +53 -0
  8. package/src/config/findProjectConfigPath.ts +36 -0
  9. package/src/config/index.ts +17 -2
  10. package/src/config/mergeConfigFileUpdate.ts +58 -0
  11. package/src/config/parseConfigValues.ts +215 -0
  12. package/src/config/readConfig.test.ts +104 -13
  13. package/src/config/readConfig.ts +12 -117
  14. package/src/config/readConfigLayers.test.ts +107 -0
  15. package/src/config/readConfigLayers.ts +115 -0
  16. package/src/config/resolveGlobalConfigPath.ts +13 -0
  17. package/src/config/resolveWriteConfigPath.test.ts +53 -0
  18. package/src/config/resolveWriteConfigPath.ts +31 -0
  19. package/src/config/types.ts +88 -2
  20. package/src/config/writeConfig.ts +25 -43
  21. package/src/constants.ts +12 -1
  22. package/src/domains/block/commands/index.ts +2 -1
  23. package/src/domains/block/commands/list.ts +5 -90
  24. package/src/domains/block/commands/lookup.ts +8 -167
  25. package/src/domains/block/commands/sample.ts +55 -0
  26. package/src/domains/block/formatters/index.ts +2 -1
  27. package/src/domains/block/formatters/sample.ts +21 -0
  28. package/src/domains/block/index.ts +3 -3
  29. package/src/domains/block/mcp/specs.ts +36 -168
  30. package/src/domains/block/operations/index.ts +2 -1
  31. package/src/domains/block/operations/lookup.ts +9 -0
  32. package/src/domains/block/operations/sample.ts +41 -0
  33. package/src/domains/block/orchestration/blockEmptyError.test.ts +26 -0
  34. package/src/domains/block/orchestration/resolveBlockLookup.ts +11 -3
  35. package/src/domains/block/stories.test.ts +28 -0
  36. package/src/domains/block/stories.ts +254 -0
  37. package/src/domains/config/commands/channel.test.ts +14 -3
  38. package/src/domains/config/commands/channel.ts +11 -7
  39. package/src/domains/config/commands/configScope.ts +46 -0
  40. package/src/domains/config/commands/framework.test.ts +105 -0
  41. package/src/domains/config/commands/framework.ts +91 -0
  42. package/src/domains/config/commands/index.ts +2 -0
  43. package/src/domains/config/commands/show.ts +5 -45
  44. package/src/domains/config/commands/tier.test.ts +13 -2
  45. package/src/domains/config/commands/tier.ts +11 -7
  46. package/src/domains/config/commands/trace.test.ts +165 -0
  47. package/src/domains/config/commands/trace.ts +83 -0
  48. package/src/domains/config/formatters/channel.test.ts +20 -6
  49. package/src/domains/config/formatters/channel.ts +14 -11
  50. package/src/domains/config/formatters/framework.ts +37 -0
  51. package/src/domains/config/formatters/index.ts +2 -0
  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 +28 -0
  57. package/src/domains/config/index.ts +15 -2
  58. package/src/domains/config/mcp/specs.ts +33 -53
  59. package/src/domains/config/operations/index.ts +1 -0
  60. package/src/domains/config/operations/show.test.ts +18 -0
  61. package/src/domains/config/operations/show.ts +7 -1
  62. package/src/domains/config/operations/types.ts +7 -0
  63. package/src/domains/config/operations/validateFramework.ts +24 -0
  64. package/src/domains/config/stories.ts +42 -0
  65. package/src/domains/config/tasks/index.ts +3 -0
  66. package/src/domains/config/tasks/setChannel.ts +13 -22
  67. package/src/domains/config/tasks/setFramework.ts +21 -0
  68. package/src/domains/config/tasks/setTier.ts +10 -23
  69. package/src/domains/config/tasks/setTrace.ts +20 -0
  70. package/src/domains/config/tasks/writeConfigField.ts +41 -0
  71. package/src/domains/create/commands/component.ts +5 -5
  72. package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
  73. package/src/domains/doctor/operations/checks/checkKeStore.ts +5 -5
  74. package/src/domains/doctor/operations/checks/checkMcpCommands.ts +130 -0
  75. package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
  76. package/src/domains/doctor/operations/checks/checkPackageRefs.ts +30 -48
  77. package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +1 -1
  78. package/src/domains/doctor/operations/checks/index.ts +1 -0
  79. package/src/domains/doctor/operations/checks.test.ts +162 -8
  80. package/src/domains/doctor/operations/runChecks.test.ts +85 -4
  81. package/src/domains/doctor/operations/runChecks.ts +50 -12
  82. package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
  83. package/src/domains/graph/helpers/resolveUri.ts +28 -21
  84. package/src/domains/graphql/commands/build.test.ts +196 -0
  85. package/src/domains/graphql/commands/build.ts +117 -0
  86. package/src/domains/graphql/commands/check.test.ts +141 -0
  87. package/src/domains/graphql/commands/check.ts +81 -0
  88. package/src/domains/graphql/commands/index.ts +5 -0
  89. package/src/domains/graphql/commands/serve.test.ts +40 -0
  90. package/src/domains/graphql/commands/serve.ts +131 -0
  91. package/src/domains/graphql/constants.ts +10 -0
  92. package/src/domains/graphql/formatters/index.ts +3 -0
  93. package/src/domains/graphql/formatters/report.ts +78 -0
  94. package/src/domains/graphql/helpers/gatherSources.test.ts +92 -0
  95. package/src/domains/graphql/helpers/gatherSources.ts +58 -0
  96. package/src/domains/graphql/helpers/index.ts +6 -0
  97. package/src/domains/graphql/helpers/parsePrefixes.test.ts +44 -0
  98. package/src/domains/graphql/helpers/parsePrefixes.ts +38 -0
  99. package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +56 -0
  100. package/src/domains/graphql/helpers/resolveSourceFiles.ts +45 -0
  101. package/src/domains/graphql/helpers/routeGraphql.test.ts +43 -0
  102. package/src/domains/graphql/helpers/routeGraphql.ts +28 -0
  103. package/src/domains/graphql/index.ts +24 -0
  104. package/src/domains/graphql/operations/compileSchema.test.ts +95 -0
  105. package/src/domains/graphql/operations/compileSchema.ts +107 -0
  106. package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
  107. package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
  108. package/src/domains/graphql/operations/index.ts +12 -0
  109. package/src/domains/graphql/types.ts +29 -0
  110. package/src/domains/info/operations/collectInfo.test.ts +16 -5
  111. package/src/domains/info/operations/collectInfo.ts +16 -19
  112. package/src/domains/llm/capabilities.test.ts +91 -0
  113. package/src/domains/llm/commands/capabilities.ts +28 -0
  114. package/src/domains/llm/commands/index.ts +1 -0
  115. package/src/domains/llm/data/commandReference.ts +90 -18
  116. package/src/domains/llm/data/decisionTrees.ts +15 -13
  117. package/src/domains/llm/data/index.ts +2 -0
  118. package/src/domains/llm/data/toolCatalog.ts +190 -0
  119. package/src/domains/llm/formatters/capabilities.ts +50 -0
  120. package/src/domains/llm/formatters/index.ts +1 -0
  121. package/src/domains/llm/index.ts +3 -2
  122. package/src/domains/llm/mcp/index.ts +1 -1
  123. package/src/domains/llm/mcp/specs.ts +59 -52
  124. package/src/domains/llm/types.ts +40 -0
  125. package/src/domains/modifier/commands/index.ts +2 -1
  126. package/src/domains/modifier/commands/list.ts +5 -38
  127. package/src/domains/modifier/commands/lookup.ts +8 -79
  128. package/src/domains/modifier/commands/sample.ts +53 -0
  129. package/src/domains/modifier/formatters/index.ts +2 -1
  130. package/src/domains/modifier/formatters/sample.ts +15 -0
  131. package/src/domains/modifier/index.ts +7 -3
  132. package/src/domains/modifier/mcp/specs.ts +38 -70
  133. package/src/domains/modifier/operations/index.ts +2 -1
  134. package/src/domains/modifier/operations/lookup.ts +9 -0
  135. package/src/domains/modifier/operations/sample.ts +32 -0
  136. package/src/domains/modifier/orchestration/modifierEmptyError.test.ts +26 -0
  137. package/src/domains/modifier/orchestration/modifierEmptyError.ts +7 -2
  138. package/src/domains/modifier/orchestration/resolveModifierLookup.ts +15 -2
  139. package/src/domains/modifier/stories.test.ts +20 -0
  140. package/src/domains/modifier/stories.ts +77 -0
  141. package/src/domains/ontology/commands/list.ts +5 -58
  142. package/src/domains/ontology/commands/show.ts +6 -58
  143. package/src/domains/ontology/formatters/show.ts +7 -1
  144. package/src/domains/ontology/mcp/specs.ts +7 -84
  145. package/src/domains/ontology/stories.test.ts +36 -0
  146. package/src/domains/ontology/stories.ts +108 -0
  147. package/src/domains/refs/operations/index.ts +1 -1
  148. package/src/domains/refs/operations/paths.ts +29 -1
  149. package/src/domains/refs/operations/updateRefs.test.ts +6 -3
  150. package/src/domains/refs/operations/updateRefs.ts +2 -36
  151. package/src/domains/setup/commands/skills.test.ts +6 -2
  152. package/src/domains/setup/commands/skills.ts +6 -2
  153. package/src/domains/setup/helpers/runSetupTask.test.ts +148 -150
  154. package/src/domains/setup/helpers/runSetupTask.ts +62 -70
  155. package/src/domains/setup/operations/setupMcp.test.ts +6 -1
  156. package/src/domains/shared/bootStore.ts +92 -50
  157. package/src/domains/shared/compactUri.test.ts +11 -0
  158. package/src/domains/shared/compactUri.ts +10 -5
  159. package/src/domains/shared/context.ts +2 -2
  160. package/src/domains/shared/contracts.ts +12 -0
  161. package/src/domains/shared/createInteractivePromptSession.test.ts +439 -0
  162. package/src/domains/shared/createInteractivePromptSession.ts +236 -0
  163. package/src/domains/shared/emptyErrorRecovery.test.ts +109 -0
  164. package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
  165. package/src/domains/shared/loaders/bundledLoader.ts +206 -0
  166. package/src/domains/shared/loaders/gitLoader.ts +31 -0
  167. package/src/domains/shared/loaders/index.ts +9 -0
  168. package/src/domains/shared/loaders/localLoader.ts +87 -0
  169. package/src/domains/shared/loaders/readPackageDir.ts +147 -0
  170. package/src/domains/shared/loaders/storyAssetsPlugin.test.ts +84 -0
  171. package/src/domains/shared/loaders/storyAssetsPlugin.ts +46 -0
  172. package/src/domains/shared/lookupMany.test.ts +120 -0
  173. package/src/domains/shared/lookupMany.ts +43 -3
  174. package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
  175. package/src/domains/shared/mergeAndParseRefs.ts +44 -0
  176. package/src/domains/shared/packages.ts +14 -120
  177. package/src/domains/shared/pickRandom.ts +22 -0
  178. package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
  179. package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
  180. package/src/domains/shared/runtime.ts +7 -63
  181. package/src/domains/shared/sampleFormatters.ts +47 -0
  182. package/src/domains/shared/semanticPackage.ts +112 -0
  183. package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
  184. package/src/domains/shared/stories/compileLookupCommand.ts +100 -0
  185. package/src/domains/shared/stories/compileLookupTool.test.ts +105 -0
  186. package/src/domains/shared/stories/compileLookupTool.ts +96 -0
  187. package/src/domains/shared/stories/compileReadCommand.test.ts +121 -0
  188. package/src/domains/shared/stories/compileReadCommand.ts +48 -0
  189. package/src/domains/shared/stories/compileReadTool.test.ts +64 -0
  190. package/src/domains/shared/stories/compileReadTool.ts +38 -0
  191. package/src/domains/shared/stories/condense.test.ts +18 -0
  192. package/src/domains/shared/stories/condense.ts +15 -0
  193. package/src/domains/shared/stories/index.ts +20 -0
  194. package/src/domains/shared/stories/normalizeNames.test.ts +20 -0
  195. package/src/domains/shared/stories/normalizeNames.ts +22 -0
  196. package/src/domains/shared/stories/pack/applyPackFilters.test.ts +102 -0
  197. package/src/domains/shared/stories/pack/applyPackFilters.ts +76 -0
  198. package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +51 -0
  199. package/src/domains/shared/stories/pack/buildLookupQuery.ts +80 -0
  200. package/src/domains/shared/stories/pack/collectPackStories.test.ts +108 -0
  201. package/src/domains/shared/stories/pack/collectPackStories.ts +76 -0
  202. package/src/domains/shared/stories/pack/compilePackCommands.ts +40 -0
  203. package/src/domains/shared/stories/pack/compilePackStories.test.ts +146 -0
  204. package/src/domains/shared/stories/pack/compilePackStories.ts +253 -0
  205. package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +43 -0
  206. package/src/domains/shared/stories/pack/index.ts +28 -0
  207. package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
  208. package/src/domains/shared/stories/pack/standardParity.test.ts +308 -0
  209. package/src/domains/shared/stories/pack/types.ts +104 -0
  210. package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +240 -0
  211. package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +408 -0
  212. package/src/domains/shared/stories/projectCliParameters.test.ts +59 -0
  213. package/src/domains/shared/stories/projectCliParameters.ts +57 -0
  214. package/src/domains/shared/stories/projectToolParams.test.ts +50 -0
  215. package/src/domains/shared/stories/projectToolParams.ts +32 -0
  216. package/src/domains/shared/stories/requirePragmaContext.test.ts +23 -0
  217. package/src/domains/shared/stories/requirePragmaContext.ts +23 -0
  218. package/src/domains/shared/stories/resolveLookupDetailed.test.ts +57 -0
  219. package/src/domains/shared/stories/resolveLookupDetailed.ts +27 -0
  220. package/src/domains/shared/stories/types.ts +171 -0
  221. package/src/domains/shared/suggestions/detectCrossDomain.test.ts +43 -0
  222. package/src/domains/shared/suggestions/detectCrossDomain.ts +116 -0
  223. package/src/domains/shared/suggestions/expandGlob.test.ts +92 -0
  224. package/src/domains/shared/suggestions/expandGlob.ts +52 -0
  225. package/src/domains/shared/suggestions/expandLookupQueries.ts +57 -0
  226. package/src/domains/shared/suggestions/index.ts +7 -0
  227. package/src/domains/shared/suggestions/listDomainNames.ts +61 -0
  228. package/src/domains/shared/suggestions/suggestNames.test.ts +70 -0
  229. package/src/domains/shared/suggestions/suggestNames.ts +130 -0
  230. package/src/domains/shared/types/index.ts +1 -0
  231. package/src/domains/shared/types/runtime.ts +4 -1
  232. package/src/domains/shared/types/sample.ts +17 -0
  233. package/src/domains/skill/commands/index.ts +3 -1
  234. package/src/domains/skill/commands/list.test.ts +6 -2
  235. package/src/domains/skill/commands/list.ts +5 -63
  236. package/src/domains/skill/commands/lookup.test.ts +118 -0
  237. package/src/domains/skill/commands/lookup.ts +14 -0
  238. package/src/domains/skill/formatters/index.ts +1 -0
  239. package/src/domains/skill/formatters/lookup.test.ts +46 -0
  240. package/src/domains/skill/formatters/lookup.ts +57 -0
  241. package/src/domains/skill/helpers/resolveSkillSources.ts +48 -16
  242. package/src/domains/skill/index.ts +7 -3
  243. package/src/domains/skill/mcp/specs.ts +10 -29
  244. package/src/domains/skill/operations/discover.test.ts +61 -30
  245. package/src/domains/skill/operations/discover.ts +28 -37
  246. package/src/domains/skill/operations/index.ts +2 -1
  247. package/src/domains/skill/operations/list.test.ts +15 -7
  248. package/src/domains/skill/operations/lookup.test.ts +91 -0
  249. package/src/domains/skill/operations/lookup.ts +70 -0
  250. package/src/domains/skill/stories.test.ts +43 -0
  251. package/src/domains/skill/stories.ts +103 -0
  252. package/src/domains/skill/types.ts +8 -0
  253. package/src/domains/standard/commands/index.ts +2 -1
  254. package/src/domains/standard/commands/list.ts +5 -84
  255. package/src/domains/standard/commands/lookup.ts +8 -93
  256. package/src/domains/standard/commands/sample.ts +57 -0
  257. package/src/domains/standard/formatters/index.ts +2 -1
  258. package/src/domains/standard/formatters/sample.ts +15 -0
  259. package/src/domains/standard/index.ts +8 -1
  260. package/src/domains/standard/mcp/specs.ts +44 -152
  261. package/src/domains/standard/operations/index.ts +2 -1
  262. package/src/domains/standard/operations/lookup.ts +9 -0
  263. package/src/domains/standard/operations/sample.ts +35 -0
  264. package/src/domains/standard/orchestration/resolveStandardLookup.ts +15 -2
  265. package/src/domains/standard/orchestration/standardEmptyError.test.ts +33 -0
  266. package/src/domains/standard/orchestration/standardEmptyError.ts +16 -6
  267. package/src/domains/standard/stories.test.ts +24 -0
  268. package/src/domains/standard/stories.ts +151 -0
  269. package/src/domains/tier/commands/list.ts +5 -55
  270. package/src/domains/tier/mcp/specs.ts +5 -31
  271. package/src/domains/tier/stories.test.ts +22 -0
  272. package/src/domains/tier/stories.ts +52 -0
  273. package/src/domains/token/commands/index.ts +2 -1
  274. package/src/domains/token/commands/sample.ts +53 -0
  275. package/src/domains/token/formatters/index.ts +2 -1
  276. package/src/domains/token/formatters/sample.ts +16 -0
  277. package/src/domains/token/index.ts +8 -1
  278. package/src/domains/token/mcp/specs.ts +52 -2
  279. package/src/domains/token/operations/index.ts +2 -1
  280. package/src/domains/token/operations/lookup.ts +9 -0
  281. package/src/domains/token/operations/sample.ts +32 -0
  282. package/src/domains/token/orchestration/resolveTokenLookup.ts +15 -2
  283. package/src/domains/token/orchestration/tokenEmptyError.test.ts +33 -0
  284. package/src/domains/token/orchestration/tokenEmptyError.ts +5 -2
  285. package/src/domains/trace/commands/clear.ts +71 -0
  286. package/src/domains/trace/commands/index.ts +5 -0
  287. package/src/domains/trace/commands/sessions.ts +32 -0
  288. package/src/domains/trace/commands/show.ts +145 -0
  289. package/src/domains/trace/formatters/index.ts +9 -0
  290. package/src/domains/trace/formatters/sessions.ts +80 -0
  291. package/src/domains/trace/formatters/show.ts +122 -0
  292. package/src/domains/trace/index.ts +17 -0
  293. package/src/domains/trace/operations/index.ts +8 -0
  294. package/src/domains/trace/operations/listSessions.test.ts +55 -0
  295. package/src/domains/trace/operations/listSessions.ts +52 -0
  296. package/src/domains/trace/operations/readTraceLog.test.ts +100 -0
  297. package/src/domains/trace/operations/readTraceLog.ts +104 -0
  298. package/src/domains/trace/tracePlugin.test.ts +171 -0
  299. package/src/domains/trace/tracePlugin.ts +159 -0
  300. package/src/domains/trace/types.ts +65 -0
  301. package/src/error/PragmaError.ts +15 -2
  302. package/src/error/types.ts +15 -1
  303. package/src/mcp/error/serializeErrorPayload.ts +7 -0
  304. package/src/mcp/error/types.ts +8 -0
  305. package/src/mcp/registerResources.test.ts +405 -75
  306. package/src/mcp/registerResources.ts +5 -299
  307. package/src/mcp/resources/buildGraphIndex.ts +167 -0
  308. package/src/mcp/resources/buildResourceList.test.ts +97 -0
  309. package/src/mcp/resources/buildResourceList.ts +176 -0
  310. package/src/mcp/resources/classifyEntity.test.ts +40 -0
  311. package/src/mcp/resources/classifyEntity.ts +27 -0
  312. package/src/mcp/resources/constants.ts +105 -0
  313. package/src/mcp/resources/displayPredicates.ts +62 -0
  314. package/src/mcp/resources/pickFirstValue.test.ts +29 -0
  315. package/src/mcp/resources/pickFirstValue.ts +26 -0
  316. package/src/mcp/resources/pickPrimaryType.test.ts +41 -0
  317. package/src/mcp/resources/pickPrimaryType.ts +26 -0
  318. package/src/mcp/resources/rankUriCompletions.test.ts +52 -0
  319. package/src/mcp/resources/rankUriCompletions.ts +64 -0
  320. package/src/mcp/resources/readEntity.ts +169 -0
  321. package/src/mcp/resources/registerResources.ts +126 -0
  322. package/src/mcp/resources/types.ts +128 -0
  323. package/src/mcp/tools/index.ts +9 -0
  324. package/src/mcp/tools/registerTools.test.ts +84 -12
  325. package/src/mcp/types.ts +4 -0
  326. package/src/mcp/utils/wrapTool.test.ts +1 -0
  327. package/src/pipeline/collectCommands.ts +15 -2
  328. package/src/pipeline/renderError.ts +15 -0
  329. package/src/pipeline/resolveCommandKind.ts +8 -1
  330. package/src/pipeline/runCli.ts +51 -6
  331. package/src/testing/createTestMcpClient.ts +5 -1
  332. package/src/testing/graphqlFixtures.ts +72 -0
  333. package/src/testing/index.ts +17 -0
  334. package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
  335. package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
  336. package/src/testing/integration/executor-execution.test.ts +101 -0
  337. package/src/testing/integration/executor-golden.test.ts +145 -0
  338. package/src/testing/integration/mcp-surface.test.ts +11 -5
  339. package/src/testing/integration/parity.test.ts +17 -12
  340. package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
  341. package/src/testing/setupXdgIsolation.ts +15 -0
  342. package/src/testing/standardParityFixtures.ts +92 -0
  343. package/src/testing/storyFixtures.ts +63 -0
  344. package/src/pipeline/runInteractiveCommand.ts +0 -198
@@ -0,0 +1,159 @@
1
+ /**
2
+ * KE plugin for query access tracing.
3
+ *
4
+ * Intercepts `onQuery` and `onResult` hooks to record every
5
+ * `store.query()` call as an NDJSON line in a session-scoped log file.
6
+ *
7
+ * Activation: conditional — only instantiated when `PRAGMA_TRACE=1` or
8
+ * `trace: true` in pragma.config.json.
9
+ * Correlation: closure variable `pending` — safe because KE calls
10
+ * `onQuery` → Oxigraph WASM (sync) → `onResult` with no interleaving.
11
+ */
12
+
13
+ import { appendFileSync, mkdirSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { definePlugin } from "@canonical/ke";
16
+ import type { TraceApi, TracePluginOptions, TraceRecord } from "./types.js";
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // FNV-1a 32-bit hash
20
+ // ---------------------------------------------------------------------------
21
+
22
+ const FNV_OFFSET = 0x811c9dc5;
23
+ const FNV_PRIME = 0x01000193;
24
+
25
+ function fnv1a(input: string): string {
26
+ let hash = FNV_OFFSET;
27
+ for (let i = 0; i < input.length; i++) {
28
+ hash ^= input.charCodeAt(i);
29
+ hash = Math.imul(hash, FNV_PRIME);
30
+ }
31
+ return (hash >>> 0).toString(16).padStart(8, "0");
32
+ }
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Session ID generation
36
+ // ---------------------------------------------------------------------------
37
+
38
+ function generateSessionId(): string {
39
+ const now = new Date();
40
+ const date = [
41
+ now.getFullYear(),
42
+ String(now.getMonth() + 1).padStart(2, "0"),
43
+ String(now.getDate()).padStart(2, "0"),
44
+ ].join("");
45
+ const time = [
46
+ String(now.getHours()).padStart(2, "0"),
47
+ String(now.getMinutes()).padStart(2, "0"),
48
+ String(now.getSeconds()).padStart(2, "0"),
49
+ ].join("");
50
+ const rand = Math.random().toString(16).slice(2, 6);
51
+ return `${date}-${time}-${rand}`;
52
+ }
53
+
54
+ // ---------------------------------------------------------------------------
55
+ // Record builder
56
+ // ---------------------------------------------------------------------------
57
+
58
+ function buildRecord(
59
+ sessionId: string,
60
+ seq: number,
61
+ sparql: string,
62
+ startMs: number,
63
+ result: import("@canonical/ke").QueryResult,
64
+ maxBindings: number,
65
+ ): TraceRecord {
66
+ const ms = Math.round((performance.now() - startMs) * 100) / 100;
67
+ const qh = fnv1a(sparql);
68
+
69
+ const base = {
70
+ ts: new Date().toISOString(),
71
+ sid: sessionId,
72
+ seq,
73
+ qh,
74
+ q: sparql,
75
+ ms,
76
+ };
77
+
78
+ switch (result.type) {
79
+ case "select":
80
+ return {
81
+ ...base,
82
+ type: "select",
83
+ count: result.bindings.length,
84
+ vars: result.variables,
85
+ bindings: result.bindings.slice(0, maxBindings),
86
+ };
87
+ case "construct":
88
+ return {
89
+ ...base,
90
+ type: "construct",
91
+ count: result.triples.length,
92
+ triples: result.triples.slice(0, maxBindings).map((t) => ({
93
+ s: t.subject,
94
+ p: t.predicate,
95
+ o: t.object,
96
+ })),
97
+ };
98
+ case "ask":
99
+ return {
100
+ ...base,
101
+ type: "ask",
102
+ count: 1,
103
+ ask: result.result,
104
+ };
105
+ }
106
+ }
107
+
108
+ // ---------------------------------------------------------------------------
109
+ // Plugin factory
110
+ // ---------------------------------------------------------------------------
111
+
112
+ export function createTracePlugin(options: TracePluginOptions) {
113
+ const maxBindings = options.maxBindings ?? 200;
114
+ const sessionId = options.sessionId ?? generateSessionId();
115
+ const logPath = join(options.traceDir, `${sessionId}.ndjson`);
116
+
117
+ let seq = 0;
118
+ let pendingQuery: string | undefined;
119
+ let pendingStart: number | undefined;
120
+
121
+ return definePlugin<TraceApi>({
122
+ name: "trace",
123
+
124
+ onReady() {
125
+ mkdirSync(options.traceDir, { recursive: true });
126
+ return {
127
+ sessionId,
128
+ logPath,
129
+ get queryCount() {
130
+ return seq;
131
+ },
132
+ };
133
+ },
134
+
135
+ onQuery(sparql) {
136
+ pendingQuery = sparql;
137
+ pendingStart = performance.now();
138
+ return undefined;
139
+ },
140
+
141
+ onResult(result) {
142
+ if (pendingQuery !== undefined && pendingStart !== undefined) {
143
+ const record = buildRecord(
144
+ sessionId,
145
+ seq,
146
+ pendingQuery,
147
+ pendingStart,
148
+ result,
149
+ maxBindings,
150
+ );
151
+ appendFileSync(logPath, `${JSON.stringify(record)}\n`);
152
+ seq++;
153
+ pendingQuery = undefined;
154
+ pendingStart = undefined;
155
+ }
156
+ return undefined;
157
+ },
158
+ });
159
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Types for query access tracing.
3
+ *
4
+ * One NDJSON record per `store.query()` call. The trace plugin writes
5
+ * these to session-scoped log files; the CLI reads them back.
6
+ */
7
+
8
+ /** A single trace record — one per store.query() call. */
9
+ export interface TraceRecord {
10
+ /** ISO-8601 timestamp. */
11
+ ts: string;
12
+ /** Session identifier. */
13
+ sid: string;
14
+ /** Monotonic query index within the session. */
15
+ seq: number;
16
+ /** FNV-1a hash of the query string (8 hex chars). */
17
+ qh: string;
18
+ /** SPARQL query string (after prefix expansion). */
19
+ q: string;
20
+ /** Execution duration in milliseconds. */
21
+ ms: number;
22
+ /** Result type discriminant. */
23
+ type: "select" | "construct" | "ask";
24
+ /** True result count (bindings / triples / 1). */
25
+ count: number;
26
+ /** SELECT variable names. */
27
+ vars?: string[];
28
+ /** SELECT result rows (capped at maxBindings). */
29
+ bindings?: Record<string, string>[];
30
+ /** CONSTRUCT triples (capped at maxBindings). */
31
+ triples?: { s: string; p: string; o: string }[];
32
+ /** ASK result. */
33
+ ask?: boolean;
34
+ }
35
+
36
+ /** API exposed via `store.api<TraceApi>("trace")`. */
37
+ export interface TraceApi {
38
+ readonly sessionId: string;
39
+ readonly logPath: string;
40
+ readonly queryCount: number;
41
+ }
42
+
43
+ /** Options for creating the trace plugin. */
44
+ export interface TracePluginOptions {
45
+ /** Directory for trace log files. */
46
+ traceDir: string;
47
+ /** Session identifier (generated if omitted). */
48
+ sessionId?: string;
49
+ /** Max bindings/triples to record per query. Default: 200. */
50
+ maxBindings?: number;
51
+ }
52
+
53
+ /** A trace session on disk. */
54
+ export interface TraceSession {
55
+ /** Session identifier (derived from filename). */
56
+ sessionId: string;
57
+ /** Absolute path to the NDJSON file. */
58
+ path: string;
59
+ /** Number of query records in the file. */
60
+ queryCount: number;
61
+ /** File size in bytes. */
62
+ sizeBytes: number;
63
+ /** File creation time. */
64
+ createdAt: Date;
65
+ }
@@ -1,4 +1,9 @@
1
- import type { ErrorCode, PragmaErrorData, Recovery } from "./types.js";
1
+ import type {
2
+ CrossDomainRecovery,
3
+ ErrorCode,
4
+ PragmaErrorData,
5
+ Recovery,
6
+ } from "./types.js";
2
7
 
3
8
  /**
4
9
  * Structured error for all pragma domain operations.
@@ -16,6 +21,8 @@ class PragmaError extends Error {
16
21
  readonly suggestions: string[];
17
22
  /** Structured recovery hint with optional CLI command or MCP tool call. */
18
23
  readonly recovery: Recovery | undefined;
24
+ /** Cross-domain redirect when name exists in another domain. */
25
+ readonly crossDomain: CrossDomainRecovery | undefined;
19
26
  /** Active filters at the time of the error, for diagnostic context. */
20
27
  readonly filters: Record<string, string> | undefined;
21
28
  /** Enumerated valid options when input was rejected. */
@@ -31,6 +38,7 @@ class PragmaError extends Error {
31
38
  this.entity = data.entity;
32
39
  this.suggestions = data.suggestions ?? [];
33
40
  this.recovery = data.recovery;
41
+ this.crossDomain = data.crossDomain;
34
42
  this.filters = data.filters;
35
43
  this.validOptions = data.validOptions;
36
44
  }
@@ -49,6 +57,7 @@ class PragmaError extends Error {
49
57
  opts: {
50
58
  suggestions?: string[];
51
59
  recovery?: Recovery;
60
+ crossDomain?: CrossDomainRecovery;
52
61
  } = {},
53
62
  ): PragmaError {
54
63
  return new PragmaError({
@@ -57,6 +66,7 @@ class PragmaError extends Error {
57
66
  entity: { type: entityType, name: entityName },
58
67
  suggestions: opts.suggestions,
59
68
  recovery: opts.recovery,
69
+ crossDomain: opts.crossDomain,
60
70
  });
61
71
  }
62
72
 
@@ -70,15 +80,18 @@ class PragmaError extends Error {
70
80
  static emptyResults(
71
81
  entityType: string,
72
82
  opts: {
83
+ message?: string;
73
84
  filters?: Record<string, string>;
74
85
  recovery?: Recovery;
86
+ validOptions?: string[];
75
87
  } = {},
76
88
  ): PragmaError {
77
89
  return new PragmaError({
78
90
  code: "EMPTY_RESULTS",
79
- message: `No ${entityType}s found.`,
91
+ message: opts.message ?? `No ${entityType}s found.`,
80
92
  filters: opts.filters,
81
93
  recovery: opts.recovery,
94
+ validOptions: opts.validOptions,
82
95
  });
83
96
  }
84
97
 
@@ -20,6 +20,18 @@ interface Recovery {
20
20
  mcp?: { tool: string; params?: Record<string, unknown> };
21
21
  }
22
22
 
23
+ /** Hint pointing the user/agent to a different domain when a name exists there. */
24
+ interface CrossDomainRecovery {
25
+ /** Domain where the name was found (e.g., "modifier"). */
26
+ domain: string;
27
+ /** Entity type label for messages. */
28
+ entityType: string;
29
+ /** CLI command to run. */
30
+ cli: string;
31
+ /** MCP tool invocation. */
32
+ mcp: { tool: string; params: Record<string, unknown> };
33
+ }
34
+
23
35
  /** Raw data payload used to construct a PragmaError. */
24
36
  interface PragmaErrorData {
25
37
  /** Machine-readable error classification. */
@@ -32,10 +44,12 @@ interface PragmaErrorData {
32
44
  suggestions?: string[];
33
45
  /** Recovery hint for CLI and MCP adapters. */
34
46
  recovery?: Recovery;
47
+ /** Cross-domain redirect when name exists in another domain. */
48
+ crossDomain?: CrossDomainRecovery;
35
49
  /** Active filters at the time of the error. */
36
50
  filters?: Record<string, string>;
37
51
  /** Enumerated valid options when input was rejected. */
38
52
  validOptions?: string[];
39
53
  }
40
54
 
41
- export type { ErrorCode, PragmaErrorData, Recovery };
55
+ export type { CrossDomainRecovery, ErrorCode, PragmaErrorData, Recovery };
@@ -21,6 +21,13 @@ export default function serializeErrorPayload(
21
21
  message: error.message,
22
22
  ...(error.suggestions.length > 0 && { suggestions: error.suggestions }),
23
23
  ...(recovery && { recovery }),
24
+ ...(error.crossDomain && {
25
+ crossDomain: {
26
+ domain: error.crossDomain.domain,
27
+ tool: error.crossDomain.mcp.tool,
28
+ params: error.crossDomain.mcp.params,
29
+ },
30
+ }),
24
31
  ...(error.filters && { filters: error.filters }),
25
32
  ...(error.validOptions && { validOptions: error.validOptions }),
26
33
  };
@@ -28,11 +28,19 @@ export interface McpRecovery {
28
28
  * Structured MCP error payload embedded in tool response content.
29
29
  * Returned as JSON text content with `isError: true`.
30
30
  */
31
+ /** Cross-domain redirect hint for agents. */
32
+ export interface McpCrossDomainHint {
33
+ readonly domain: string;
34
+ readonly tool: string;
35
+ readonly params: Record<string, unknown>;
36
+ }
37
+
31
38
  export interface McpErrorPayload {
32
39
  readonly code: ErrorCode;
33
40
  readonly message: string;
34
41
  readonly suggestions?: readonly string[];
35
42
  readonly recovery?: McpRecovery;
43
+ readonly crossDomain?: McpCrossDomainHint;
36
44
  readonly filters?: Record<string, string>;
37
45
  readonly validOptions?: readonly string[];
38
46
  }