@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.
- package/README.md +377 -0
- package/package.json +78 -0
- package/src/bin.test.ts +52 -0
- package/src/bin.ts +19 -0
- package/src/compile-validation.runner.ts +137 -0
- package/src/compile-validation.ts +192 -0
- package/src/completions/computeSocketPath.test.ts +26 -0
- package/src/completions/computeSocketPath.ts +16 -0
- package/src/completions/constants.ts +18 -0
- package/src/completions/handleQuery.test.ts +93 -0
- package/src/completions/handleQuery.ts +30 -0
- package/src/completions/index.ts +14 -0
- package/src/completions/queryCompletions.test.ts +100 -0
- package/src/completions/queryCompletions.ts +61 -0
- package/src/completions/querySocket.test.ts +70 -0
- package/src/completions/querySocket.ts +44 -0
- package/src/completions/startCompletionsServer.test.ts +74 -0
- package/src/completions/startCompletionsServer.ts +75 -0
- package/src/completions/startCompletionsServer.unit.test.ts +131 -0
- package/src/completions/waitForSocket.test.ts +27 -0
- package/src/completions/waitForSocket.ts +27 -0
- package/src/config/configExists.ts +14 -0
- package/src/config/index.ts +6 -0
- package/src/config/readConfig.test.ts +152 -0
- package/src/config/readConfig.ts +64 -0
- package/src/config/resolveConfigPath.test.ts +20 -0
- package/src/config/resolveConfigPath.ts +11 -0
- package/src/config/types.ts +26 -0
- package/src/config/writeConfig.ts +49 -0
- package/src/constants.ts +78 -0
- package/src/domains/block/blockConfig.ts +53 -0
- package/src/domains/block/commands/index.ts +4 -0
- package/src/domains/block/commands/list.test.ts +111 -0
- package/src/domains/block/commands/list.ts +69 -0
- package/src/domains/block/commands/lookup.test.ts +187 -0
- package/src/domains/block/commands/lookup.ts +199 -0
- package/src/domains/block/formatters/index.ts +4 -0
- package/src/domains/block/formatters/list.test.ts +107 -0
- package/src/domains/block/formatters/list.ts +64 -0
- package/src/domains/block/formatters/lookup.test.ts +317 -0
- package/src/domains/block/formatters/lookup.ts +354 -0
- package/src/domains/block/formatters/types.ts +16 -0
- package/src/domains/block/helpers/index.ts +4 -0
- package/src/domains/block/helpers/resolveAspects.test.ts +64 -0
- package/src/domains/block/helpers/resolveAspects.ts +35 -0
- package/src/domains/block/index.ts +25 -0
- package/src/domains/block/mcp/index.ts +2 -0
- package/src/domains/block/mcp/specs.ts +199 -0
- package/src/domains/block/operations/index.ts +4 -0
- package/src/domains/block/operations/list.test.ts +80 -0
- package/src/domains/block/operations/list.ts +72 -0
- package/src/domains/block/operations/lookup.test.ts +108 -0
- package/src/domains/block/operations/lookup.ts +359 -0
- package/src/domains/block/orchestration/blockEmptyError.ts +19 -0
- package/src/domains/block/orchestration/buildBlockFilters.ts +12 -0
- package/src/domains/block/orchestration/enrichBlocks.ts +37 -0
- package/src/domains/block/orchestration/index.ts +5 -0
- package/src/domains/block/orchestration/resolveBlockList.ts +39 -0
- package/src/domains/block/orchestration/resolveBlockLookup.ts +21 -0
- package/src/domains/block/types.ts +30 -0
- package/src/domains/config/commands/channel.test.ts +101 -0
- package/src/domains/config/commands/channel.ts +80 -0
- package/src/domains/config/commands/index.ts +4 -0
- package/src/domains/config/commands/show.test.ts +61 -0
- package/src/domains/config/commands/show.ts +51 -0
- package/src/domains/config/commands/tier.test.ts +84 -0
- package/src/domains/config/commands/tier.ts +78 -0
- package/src/domains/config/formatters/channel.test.ts +56 -0
- package/src/domains/config/formatters/channel.ts +34 -0
- package/src/domains/config/formatters/index.ts +4 -0
- package/src/domains/config/formatters/show.test.ts +126 -0
- package/src/domains/config/formatters/show.ts +66 -0
- package/src/domains/config/formatters/tier.test.ts +70 -0
- package/src/domains/config/formatters/tier.ts +40 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/mcp/index.ts +2 -0
- package/src/domains/config/mcp/specs.ts +108 -0
- package/src/domains/config/operations/index.ts +5 -0
- package/src/domains/config/operations/show.test.ts +60 -0
- package/src/domains/config/operations/show.ts +42 -0
- package/src/domains/config/operations/types.ts +13 -0
- package/src/domains/config/operations/validateChannel.test.ts +36 -0
- package/src/domains/config/operations/validateChannel.ts +24 -0
- package/src/domains/config/operations/validateTier.test.ts +56 -0
- package/src/domains/config/operations/validateTier.ts +35 -0
- package/src/domains/create/commands/component.test.ts +166 -0
- package/src/domains/create/commands/component.ts +129 -0
- package/src/domains/create/commands/index.ts +3 -0
- package/src/domains/create/commands/package.test.ts +35 -0
- package/src/domains/create/commands/package.ts +21 -0
- package/src/domains/create/index.ts +15 -0
- package/src/domains/create/mcp/index.ts +2 -0
- package/src/domains/create/mcp/specs.ts +174 -0
- package/src/domains/doctor/commands/doctor.test.ts +75 -0
- package/src/domains/doctor/commands/doctor.ts +43 -0
- package/src/domains/doctor/commands/index.ts +2 -0
- package/src/domains/doctor/formatters/doctor.test.ts +117 -0
- package/src/domains/doctor/formatters/doctor.ts +84 -0
- package/src/domains/doctor/formatters/index.ts +2 -0
- package/src/domains/doctor/index.ts +9 -0
- package/src/domains/doctor/mcp/index.ts +2 -0
- package/src/domains/doctor/mcp/specs.ts +88 -0
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +28 -0
- package/src/domains/doctor/operations/checks/checkKeStore.ts +38 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +65 -0
- package/src/domains/doctor/operations/checks/checkNodeVersion.ts +25 -0
- package/src/domains/doctor/operations/checks/checkPragmaVersion.ts +20 -0
- package/src/domains/doctor/operations/checks/checkShellCompletions.ts +42 -0
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +64 -0
- package/src/domains/doctor/operations/checks/index.ts +8 -0
- package/src/domains/doctor/operations/checks.test.ts +151 -0
- package/src/domains/doctor/operations/index.ts +3 -0
- package/src/domains/doctor/operations/runChecks.test.ts +89 -0
- package/src/domains/doctor/operations/runChecks.ts +38 -0
- package/src/domains/doctor/operations/types.ts +20 -0
- package/src/domains/graph/commands/index.ts +4 -0
- package/src/domains/graph/commands/inspect.test.ts +94 -0
- package/src/domains/graph/commands/inspect.ts +63 -0
- package/src/domains/graph/commands/query.test.ts +92 -0
- package/src/domains/graph/commands/query.ts +60 -0
- package/src/domains/graph/formatters/index.ts +4 -0
- package/src/domains/graph/formatters/inspect.ts +45 -0
- package/src/domains/graph/formatters/query.ts +37 -0
- package/src/domains/graph/helpers/index.ts +3 -0
- package/src/domains/graph/helpers/resolveUri.ts +70 -0
- package/src/domains/graph/index.ts +22 -0
- package/src/domains/graph/mcp/index.ts +2 -0
- package/src/domains/graph/mcp/specs.ts +82 -0
- package/src/domains/graph/operations/executeQuery.test.ts +68 -0
- package/src/domains/graph/operations/executeQuery.ts +32 -0
- package/src/domains/graph/operations/index.ts +4 -0
- package/src/domains/graph/operations/inspectUri.test.ts +101 -0
- package/src/domains/graph/operations/inspectUri.ts +61 -0
- package/src/domains/info/commands/index.ts +4 -0
- package/src/domains/info/commands/info.test.ts +88 -0
- package/src/domains/info/commands/info.ts +47 -0
- package/src/domains/info/commands/upgrade.test.ts +183 -0
- package/src/domains/info/commands/upgrade.ts +150 -0
- package/src/domains/info/constants.test.ts +22 -0
- package/src/domains/info/constants.ts +15 -0
- package/src/domains/info/formatters/index.ts +8 -0
- package/src/domains/info/formatters/info.test.ts +173 -0
- package/src/domains/info/formatters/info.ts +116 -0
- package/src/domains/info/formatters/upgrade.test.ts +133 -0
- package/src/domains/info/formatters/upgrade.ts +68 -0
- package/src/domains/info/index.ts +7 -0
- package/src/domains/info/operations/checkRegistryVersion.test.ts +124 -0
- package/src/domains/info/operations/checkRegistryVersion.ts +45 -0
- package/src/domains/info/operations/collectInfo.test.ts +111 -0
- package/src/domains/info/operations/collectInfo.ts +68 -0
- package/src/domains/info/operations/collectStoreSummary.test.ts +61 -0
- package/src/domains/info/operations/collectStoreSummary.ts +42 -0
- package/src/domains/info/operations/index.ts +5 -0
- package/src/domains/info/types.test-d.ts +35 -0
- package/src/domains/info/types.ts +46 -0
- package/src/domains/llm/commands/index.ts +3 -0
- package/src/domains/llm/commands/llm.ts +37 -0
- package/src/domains/llm/data/commandReference.ts +25 -0
- package/src/domains/llm/data/decisionTrees.ts +46 -0
- package/src/domains/llm/data/index.ts +4 -0
- package/src/domains/llm/formatters/index.ts +3 -0
- package/src/domains/llm/formatters/orientation.ts +53 -0
- package/src/domains/llm/index.ts +8 -0
- package/src/domains/llm/llmCommand.test.ts +93 -0
- package/src/domains/llm/mcp/index.ts +2 -0
- package/src/domains/llm/mcp/specs.ts +87 -0
- package/src/domains/llm/operations/collectContext.ts +47 -0
- package/src/domains/llm/operations/index.ts +3 -0
- package/src/domains/llm/types.ts +32 -0
- package/src/domains/modifier/commands/index.ts +4 -0
- package/src/domains/modifier/commands/list.test.ts +57 -0
- package/src/domains/modifier/commands/list.ts +33 -0
- package/src/domains/modifier/commands/lookup.test.ts +91 -0
- package/src/domains/modifier/commands/lookup.ts +105 -0
- package/src/domains/modifier/formatters/index.ts +4 -0
- package/src/domains/modifier/formatters/list.test.ts +38 -0
- package/src/domains/modifier/formatters/list.ts +35 -0
- package/src/domains/modifier/formatters/lookup.test.ts +33 -0
- package/src/domains/modifier/formatters/lookup.ts +38 -0
- package/src/domains/modifier/index.ts +22 -0
- package/src/domains/modifier/mcp/index.ts +2 -0
- package/src/domains/modifier/mcp/specs.ts +97 -0
- package/src/domains/modifier/operations/index.ts +4 -0
- package/src/domains/modifier/operations/list.test.ts +39 -0
- package/src/domains/modifier/operations/list.ts +41 -0
- package/src/domains/modifier/operations/lookup.test.ts +37 -0
- package/src/domains/modifier/operations/lookup.ts +57 -0
- package/src/domains/modifier/orchestration/index.ts +3 -0
- package/src/domains/modifier/orchestration/modifierEmptyError.ts +10 -0
- package/src/domains/modifier/orchestration/resolveModifierList.ts +16 -0
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +20 -0
- package/src/domains/modifier/types.ts +5 -0
- package/src/domains/ontology/commands/index.ts +4 -0
- package/src/domains/ontology/commands/list.test.ts +82 -0
- package/src/domains/ontology/commands/list.ts +46 -0
- package/src/domains/ontology/commands/show.test.ts +103 -0
- package/src/domains/ontology/commands/show.ts +66 -0
- package/src/domains/ontology/formatters/index.ts +4 -0
- package/src/domains/ontology/formatters/list.ts +37 -0
- package/src/domains/ontology/formatters/show.ts +74 -0
- package/src/domains/ontology/helpers/findNamespace.ts +23 -0
- package/src/domains/ontology/helpers/index.ts +7 -0
- package/src/domains/ontology/helpers/queryClasses.ts +50 -0
- package/src/domains/ontology/helpers/queryProperties.ts +57 -0
- package/src/domains/ontology/helpers/resolvePrefix.ts +45 -0
- package/src/domains/ontology/index.ts +26 -0
- package/src/domains/ontology/mcp/index.ts +2 -0
- package/src/domains/ontology/mcp/specs.ts +93 -0
- package/src/domains/ontology/operations/index.ts +5 -0
- package/src/domains/ontology/operations/listOntologies.test.ts +45 -0
- package/src/domains/ontology/operations/listOntologies.ts +101 -0
- package/src/domains/ontology/operations/showOntology.test.ts +65 -0
- package/src/domains/ontology/operations/showOntology.ts +41 -0
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +39 -0
- package/src/domains/ontology/operations/showOntologyRaw.ts +50 -0
- package/src/domains/setup/commands/all.ts +58 -0
- package/src/domains/setup/commands/completions.ts +85 -0
- package/src/domains/setup/commands/entrypoints.test.ts +170 -0
- package/src/domains/setup/commands/index.ts +6 -0
- package/src/domains/setup/commands/lsp.ts +49 -0
- package/src/domains/setup/commands/mcp.ts +119 -0
- package/src/domains/setup/commands/skills.test.ts +64 -0
- package/src/domains/setup/commands/skills.ts +106 -0
- package/src/domains/setup/formatters/index.ts +2 -0
- package/src/domains/setup/formatters/skills.test.ts +103 -0
- package/src/domains/setup/formatters/skills.ts +112 -0
- package/src/domains/setup/formatters/types.ts +7 -0
- package/src/domains/setup/helpers/completionScripts.test.ts +58 -0
- package/src/domains/setup/helpers/completionScripts.ts +92 -0
- package/src/domains/setup/helpers/constants.ts +2 -0
- package/src/domains/setup/helpers/detectShell.test.ts +48 -0
- package/src/domains/setup/helpers/detectShell.ts +20 -0
- package/src/domains/setup/helpers/index.ts +12 -0
- package/src/domains/setup/helpers/runSetupTask.test.ts +279 -0
- package/src/domains/setup/helpers/runSetupTask.ts +229 -0
- package/src/domains/setup/index.ts +33 -0
- package/src/domains/setup/operations/index.ts +6 -0
- package/src/domains/setup/operations/setupAll.test.ts +48 -0
- package/src/domains/setup/operations/setupAll.ts +41 -0
- package/src/domains/setup/operations/setupCompletions.test.ts +94 -0
- package/src/domains/setup/operations/setupCompletions.ts +54 -0
- package/src/domains/setup/operations/setupLsp.test.ts +29 -0
- package/src/domains/setup/operations/setupLsp.ts +17 -0
- package/src/domains/setup/operations/setupMcp.test.ts +115 -0
- package/src/domains/setup/operations/setupMcp.ts +108 -0
- package/src/domains/setup/operations/setupSkills.test.ts +191 -0
- package/src/domains/setup/operations/setupSkills.ts +160 -0
- package/src/domains/setup/types.ts +18 -0
- package/src/domains/shared/ToolSpec.ts +49 -0
- package/src/domains/shared/bootStore.ts +77 -0
- package/src/domains/shared/buildQuery.ts +18 -0
- package/src/domains/shared/compactUri.test.ts +21 -0
- package/src/domains/shared/compactUri.ts +16 -0
- package/src/domains/shared/context.ts +15 -0
- package/src/domains/shared/contracts.ts +113 -0
- package/src/domains/shared/extractLocalName.test.ts +21 -0
- package/src/domains/shared/extractLocalName.ts +14 -0
- package/src/domains/shared/filters/buildChannelFilter.test.ts +52 -0
- package/src/domains/shared/filters/buildChannelFilter.ts +41 -0
- package/src/domains/shared/filters/buildFilterConfig.ts +16 -0
- package/src/domains/shared/filters/buildFilters.test.ts +33 -0
- package/src/domains/shared/filters/buildFilters.ts +30 -0
- package/src/domains/shared/filters/buildTierFilter.test.ts +78 -0
- package/src/domains/shared/filters/buildTierFilter.ts +69 -0
- package/src/domains/shared/filters/describeFilters.ts +14 -0
- package/src/domains/shared/filters/index.ts +10 -0
- package/src/domains/shared/formatters.ts +35 -0
- package/src/domains/shared/lookupMany.ts +45 -0
- package/src/domains/shared/namespaces.ts +18 -0
- package/src/domains/shared/packages.ts +76 -0
- package/src/domains/shared/prefixes.ts +37 -0
- package/src/domains/shared/runtime.ts +62 -0
- package/src/domains/shared/types.test-d.ts +127 -0
- package/src/domains/shared/types.ts +348 -0
- package/src/domains/skill/commands/index.ts +2 -0
- package/src/domains/skill/commands/list.test.ts +111 -0
- package/src/domains/skill/commands/list.ts +69 -0
- package/src/domains/skill/formatters/index.ts +2 -0
- package/src/domains/skill/formatters/list.test.ts +140 -0
- package/src/domains/skill/formatters/list.ts +119 -0
- package/src/domains/skill/formatters/types.ts +8 -0
- package/src/domains/skill/helpers/index.ts +6 -0
- package/src/domains/skill/helpers/parseFrontmatter.test.ts +122 -0
- package/src/domains/skill/helpers/parseFrontmatter.ts +112 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +34 -0
- package/src/domains/skill/index.ts +19 -0
- package/src/domains/skill/mcp/index.ts +2 -0
- package/src/domains/skill/mcp/specs.ts +38 -0
- package/src/domains/skill/operations/discover.test.ts +145 -0
- package/src/domains/skill/operations/discover.ts +68 -0
- package/src/domains/skill/operations/index.ts +4 -0
- package/src/domains/skill/operations/list.test.ts +68 -0
- package/src/domains/skill/operations/list.ts +47 -0
- package/src/domains/skill/types.ts +25 -0
- package/src/domains/standard/commands/categories.test.ts +70 -0
- package/src/domains/standard/commands/categories.ts +48 -0
- package/src/domains/standard/commands/index.ts +5 -0
- package/src/domains/standard/commands/list.test.ts +105 -0
- package/src/domains/standard/commands/list.ts +81 -0
- package/src/domains/standard/commands/lookup.test.ts +135 -0
- package/src/domains/standard/commands/lookup.ts +127 -0
- package/src/domains/standard/formatters/categories.test.ts +44 -0
- package/src/domains/standard/formatters/categories.ts +38 -0
- package/src/domains/standard/formatters/index.ts +6 -0
- package/src/domains/standard/formatters/list.test.ts +166 -0
- package/src/domains/standard/formatters/list.ts +156 -0
- package/src/domains/standard/formatters/lookup.test.ts +95 -0
- package/src/domains/standard/formatters/lookup.ts +86 -0
- package/src/domains/standard/formatters/types.ts +31 -0
- package/src/domains/standard/index.ts +32 -0
- package/src/domains/standard/mcp/index.ts +2 -0
- package/src/domains/standard/mcp/specs.ts +197 -0
- package/src/domains/standard/operations/categories.test.ts +61 -0
- package/src/domains/standard/operations/categories.ts +38 -0
- package/src/domains/standard/operations/index.ts +5 -0
- package/src/domains/standard/operations/list.test.ts +75 -0
- package/src/domains/standard/operations/list.ts +64 -0
- package/src/domains/standard/operations/lookup.test.ts +58 -0
- package/src/domains/standard/operations/lookup.ts +142 -0
- package/src/domains/standard/orchestration/buildStandardFilters.ts +11 -0
- package/src/domains/standard/orchestration/index.ts +4 -0
- package/src/domains/standard/orchestration/resolveStandardList.ts +42 -0
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +20 -0
- package/src/domains/standard/orchestration/standardEmptyError.ts +19 -0
- package/src/domains/standard/types.ts +15 -0
- package/src/domains/tier/commands/index.ts +3 -0
- package/src/domains/tier/commands/list.test.ts +67 -0
- package/src/domains/tier/commands/list.ts +43 -0
- package/src/domains/tier/formatters/index.ts +3 -0
- package/src/domains/tier/formatters/list.test.ts +33 -0
- package/src/domains/tier/formatters/list.ts +40 -0
- package/src/domains/tier/index.ts +17 -0
- package/src/domains/tier/mcp/index.ts +2 -0
- package/src/domains/tier/mcp/specs.ts +38 -0
- package/src/domains/tier/operations/index.ts +3 -0
- package/src/domains/tier/operations/list.test.ts +32 -0
- package/src/domains/tier/operations/list.ts +33 -0
- package/src/domains/token/commands/add-config.test.ts +68 -0
- package/src/domains/token/commands/add-config.ts +62 -0
- package/src/domains/token/commands/index.ts +5 -0
- package/src/domains/token/commands/list.test.ts +82 -0
- package/src/domains/token/commands/list.ts +45 -0
- package/src/domains/token/commands/lookup.test.ts +125 -0
- package/src/domains/token/commands/lookup.ts +121 -0
- package/src/domains/token/formatters/index.ts +4 -0
- package/src/domains/token/formatters/list.test.ts +37 -0
- package/src/domains/token/formatters/list.ts +37 -0
- package/src/domains/token/formatters/lookup.test.ts +61 -0
- package/src/domains/token/formatters/lookup.ts +72 -0
- package/src/domains/token/index.ts +32 -0
- package/src/domains/token/mcp/index.ts +2 -0
- package/src/domains/token/mcp/specs.ts +145 -0
- package/src/domains/token/operations/add-config.test.ts +68 -0
- package/src/domains/token/operations/add-config.ts +61 -0
- package/src/domains/token/operations/index.ts +7 -0
- package/src/domains/token/operations/list.test.ts +50 -0
- package/src/domains/token/operations/list.ts +52 -0
- package/src/domains/token/operations/lookup.test.ts +42 -0
- package/src/domains/token/operations/lookup.ts +66 -0
- package/src/domains/token/orchestration/index.ts +3 -0
- package/src/domains/token/orchestration/resolveTokenList.ts +17 -0
- package/src/domains/token/orchestration/resolveTokenLookup.ts +20 -0
- package/src/domains/token/orchestration/tokenEmptyError.ts +17 -0
- package/src/domains/token/types.ts +6 -0
- package/src/error/PragmaError.test.ts +121 -0
- package/src/error/PragmaError.ts +164 -0
- package/src/error/constants.ts +12 -0
- package/src/error/index.ts +4 -0
- package/src/error/types.ts +41 -0
- package/src/index.ts +141 -0
- package/src/mcp/createMcpServer.test.ts +41 -0
- package/src/mcp/createMcpServer.ts +53 -0
- package/src/mcp/error/buildRecovery.test.ts +37 -0
- package/src/mcp/error/buildRecovery.ts +17 -0
- package/src/mcp/error/index.ts +12 -0
- package/src/mcp/error/serializeError.test.ts +121 -0
- package/src/mcp/error/serializeError.ts +31 -0
- package/src/mcp/error/serializeErrorPayload.test.ts +38 -0
- package/src/mcp/error/serializeErrorPayload.ts +27 -0
- package/src/mcp/error/types.ts +51 -0
- package/src/mcp/index.ts +15 -0
- package/src/mcp/registerResources.test.ts +236 -0
- package/src/mcp/registerResources.ts +303 -0
- package/src/mcp/runMcpServer.test.ts +66 -0
- package/src/mcp/runMcpServer.ts +24 -0
- package/src/mcp/tools/index.ts +55 -0
- package/src/mcp/tools/registerFromSpec.ts +97 -0
- package/src/mcp/tools/registerTools.test.ts +1124 -0
- package/src/mcp/types.ts +62 -0
- package/src/mcp/utils/estimateTokens.test.ts +14 -0
- package/src/mcp/utils/estimateTokens.ts +9 -0
- package/src/mcp/utils/index.ts +11 -0
- package/src/mcp/utils/wrapTool.test.ts +108 -0
- package/src/mcp/utils/wrapTool.ts +81 -0
- package/src/package-manager/constants.ts +29 -0
- package/src/package-manager/detectInstallSource.test.ts +23 -0
- package/src/package-manager/detectInstallSource.ts +111 -0
- package/src/package-manager/detectLocalInstall.test.ts +16 -0
- package/src/package-manager/detectLocalInstall.ts +43 -0
- package/src/package-manager/detectPackageManager.test.ts +81 -0
- package/src/package-manager/detectPackageManager.ts +30 -0
- package/src/package-manager/index.ts +6 -0
- package/src/package-manager/types.ts +12 -0
- package/src/pipeline/collectCommands.test.ts +37 -0
- package/src/pipeline/collectCommands.ts +47 -0
- package/src/pipeline/constants.ts +14 -0
- package/src/pipeline/createProgram.test.ts +112 -0
- package/src/pipeline/createProgram.ts +70 -0
- package/src/pipeline/formatTerminal.test.ts +43 -0
- package/src/pipeline/formatTerminal.ts +53 -0
- package/src/pipeline/index.ts +19 -0
- package/src/pipeline/mapExitCode.test.ts +41 -0
- package/src/pipeline/mapExitCode.ts +12 -0
- package/src/pipeline/parseGlobalFlags.ts +21 -0
- package/src/pipeline/renderError.test.ts +151 -0
- package/src/pipeline/renderError.ts +114 -0
- package/src/pipeline/resolveCommandKind.test.ts +68 -0
- package/src/pipeline/resolveCommandKind.ts +71 -0
- package/src/pipeline/runCli.orchestration.test.ts +418 -0
- package/src/pipeline/runCli.test.ts +70 -0
- package/src/pipeline/runCli.ts +215 -0
- package/src/pipeline/types.ts +17 -0
- package/src/testing/cli.ts +43 -0
- package/src/testing/createTestMcpClient.ts +64 -0
- package/src/testing/dsFixtures.ts +506 -0
- package/src/testing/fixtures/canonical-config.json +4 -0
- package/src/testing/fixtures/canonical.ttl +437 -0
- package/src/testing/fixtures/filtered-config.json +4 -0
- package/src/testing/fixtures.ts +34 -0
- package/src/testing/helpers/assertParity.ts +28 -0
- package/src/testing/helpers/createTestMcpClient.ts +40 -0
- package/src/testing/helpers/createTestRuntime.ts +67 -0
- package/src/testing/index.ts +8 -0
- package/src/testing/integration/agent-session.test.ts +148 -0
- package/src/testing/integration/boot.test.ts +67 -0
- package/src/testing/integration/mcp-surface.test.ts +574 -0
- package/src/testing/integration/parity.test.ts +192 -0
- package/src/testing/store.ts +39 -0
- 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,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,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,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,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
|
+
}
|