@canonical/pragma-cli 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -47
- package/dist/pragma +0 -0
- package/package.json +15 -13
- package/src/completions/constants.ts +7 -0
- package/src/completions/handleQuery.test.ts +32 -0
- package/src/completions/handleQuery.ts +20 -1
- package/src/completions/queryCompletions.test.ts +5 -0
- package/src/completions/queryCompletions.ts +17 -3
- package/src/completions/querySocket.test.ts +31 -0
- package/src/completions/querySocket.ts +36 -9
- package/src/config/defaultConfig.test.ts +33 -0
- package/src/config/defaultConfig.ts +59 -0
- package/src/config/defaults.json +17 -0
- package/src/config/findProjectConfigPath.test.ts +53 -0
- package/src/config/findProjectConfigPath.ts +36 -0
- package/src/config/index.ts +17 -2
- package/src/config/mergeConfigFileUpdate.ts +58 -0
- package/src/config/parseConfigValues.ts +217 -0
- package/src/config/readConfig.test.ts +104 -13
- package/src/config/readConfig.ts +12 -153
- package/src/config/readConfigLayers.test.ts +109 -0
- package/src/config/readConfigLayers.ts +118 -0
- package/src/config/resolveGlobalConfigPath.ts +13 -0
- package/src/config/resolveWriteConfigPath.test.ts +53 -0
- package/src/config/resolveWriteConfigPath.ts +31 -0
- package/src/config/types.ts +83 -1
- package/src/config/writeConfig.ts +25 -55
- package/src/constants.ts +3 -1
- package/src/domains/block/commands/list.ts +5 -90
- package/src/domains/block/commands/lookup.ts +8 -167
- package/src/domains/block/commands/sample.ts +2 -1
- package/src/domains/block/formatters/list.test.ts +3 -3
- package/src/domains/block/formatters/lookup.test.ts +5 -5
- package/src/domains/block/mcp/specs.ts +16 -196
- package/src/domains/block/orchestration/enrichBlocks.ts +6 -3
- package/src/domains/block/orchestration/resolveBlockLookup.ts +2 -1
- package/src/domains/block/stories.test.ts +28 -0
- package/src/domains/block/stories.ts +260 -0
- package/src/domains/config/commands/channel.test.ts +30 -3
- package/src/domains/config/commands/channel.ts +25 -8
- package/src/domains/config/commands/configScope.ts +46 -0
- package/src/domains/config/commands/framework.test.ts +32 -1
- package/src/domains/config/commands/framework.ts +26 -8
- package/src/domains/config/commands/show.ts +5 -45
- package/src/domains/config/commands/tier.test.ts +20 -2
- package/src/domains/config/commands/tier.ts +25 -8
- package/src/domains/config/commands/trace.test.ts +19 -2
- package/src/domains/config/commands/trace.ts +6 -3
- package/src/domains/config/formatters/channel.test.ts +20 -6
- package/src/domains/config/formatters/channel.ts +14 -11
- package/src/domains/config/formatters/framework.ts +14 -11
- package/src/domains/config/formatters/show.test.ts +27 -0
- package/src/domains/config/formatters/show.ts +27 -4
- package/src/domains/config/formatters/tier.test.ts +26 -10
- package/src/domains/config/formatters/tier.ts +19 -11
- package/src/domains/config/formatters/trace.ts +7 -7
- package/src/domains/config/mcp/specs.ts +33 -53
- package/src/domains/config/operations/show.test.ts +18 -0
- package/src/domains/config/operations/show.ts +7 -1
- package/src/domains/config/operations/types.ts +7 -0
- package/src/domains/config/operations/validateTier.test.ts +9 -0
- package/src/domains/config/operations/validateTier.ts +10 -2
- package/src/domains/config/stories.ts +42 -0
- package/src/domains/config/tasks/index.ts +1 -0
- package/src/domains/config/tasks/setChannel.ts +13 -28
- package/src/domains/config/tasks/setFramework.ts +11 -30
- package/src/domains/config/tasks/setTier.ts +10 -29
- package/src/domains/config/tasks/setTrace.ts +10 -28
- package/src/domains/config/tasks/writeConfigField.ts +41 -0
- package/src/domains/create/generatorPack/bundled.ts +49 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.test.ts +159 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.ts +312 -0
- package/src/domains/create/index.ts +13 -7
- package/src/domains/create/mcp/specs.ts +6 -161
- package/src/domains/create/renderGeneratorUi.test.ts +103 -0
- package/src/domains/create/renderGeneratorUi.ts +65 -0
- package/src/domains/doctor/formatters/doctor.test.ts +50 -2
- package/src/domains/doctor/formatters/doctor.ts +90 -38
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
- package/src/domains/doctor/operations/checks/checkMcpCommands.ts +133 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
- package/src/domains/doctor/operations/checks/checkPackageRefs.ts +32 -26
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +1 -1
- package/src/domains/doctor/operations/checks/index.ts +1 -0
- package/src/domains/doctor/operations/checks.test.ts +160 -7
- package/src/domains/doctor/operations/runChecks.test.ts +15 -6
- package/src/domains/doctor/operations/runChecks.ts +2 -0
- package/src/domains/doctor/operations/types.ts +23 -1
- package/src/domains/graph/commands/inspect.test.ts +2 -2
- package/src/domains/graph/commands/query.test.ts +5 -3
- package/src/domains/graph/formatters/inspect.ts +7 -7
- package/src/domains/graph/formatters/query.test.ts +87 -0
- package/src/domains/graph/formatters/query.ts +42 -5
- package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
- package/src/domains/graph/helpers/resolveUri.ts +28 -21
- package/src/domains/graph/operations/inspectUri.test.ts +5 -5
- package/src/domains/graphql/commands/build.test.ts +5 -3
- package/src/domains/graphql/commands/build.ts +8 -16
- package/src/domains/graphql/commands/check.test.ts +5 -3
- package/src/domains/graphql/commands/check.ts +7 -13
- package/src/domains/graphql/commands/index.ts +1 -0
- package/src/domains/graphql/commands/serve.test.ts +46 -0
- package/src/domains/graphql/commands/serve.ts +141 -0
- package/src/domains/graphql/constants.ts +10 -0
- package/src/domains/graphql/helpers/gatherSources.test.ts +92 -0
- package/src/domains/graphql/helpers/gatherSources.ts +58 -0
- package/src/domains/graphql/helpers/index.ts +2 -0
- package/src/domains/graphql/helpers/parsePrefixes.test.ts +3 -3
- package/src/domains/graphql/helpers/parsePrefixes.ts +3 -3
- package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +9 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.ts +24 -3
- package/src/domains/graphql/helpers/routeGraphql.test.ts +43 -0
- package/src/domains/graphql/helpers/routeGraphql.ts +28 -0
- package/src/domains/graphql/index.ts +9 -6
- package/src/domains/graphql/operations/compileSchema.test.ts +23 -47
- package/src/domains/graphql/operations/compileSchema.ts +23 -25
- package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
- package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.test.ts +167 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.ts +178 -0
- package/src/domains/graphql/operations/index.ts +10 -0
- package/src/domains/info/formatters/upgrade.test.ts +7 -4
- package/src/domains/info/formatters/upgrade.ts +3 -1
- package/src/domains/info/operations/collectEntityCounts.test.ts +156 -0
- package/src/domains/info/operations/collectEntityCounts.ts +123 -0
- package/src/domains/info/operations/collectInfo.test.ts +14 -3
- package/src/domains/info/operations/collectInfo.ts +12 -15
- package/src/domains/info/operations/index.ts +1 -0
- package/src/domains/info/types.ts +13 -0
- package/src/domains/llm/capabilities.test.ts +24 -4
- package/src/domains/llm/commands/capabilities.ts +12 -3
- package/src/domains/llm/commands/llm.ts +5 -1
- package/src/domains/llm/data/commandReference.ts +20 -11
- package/src/domains/llm/data/decisionTrees.ts +10 -5
- package/src/domains/llm/data/toolCatalog.ts +55 -18
- package/src/domains/llm/formatters/orientation.ts +5 -1
- package/src/domains/llm/llmCommand.test.ts +11 -3
- package/src/domains/llm/mcp/specs.ts +3 -4
- package/src/domains/llm/operations/collectContext.test.ts +64 -0
- package/src/domains/llm/operations/collectContext.ts +7 -17
- package/src/domains/modifier/commands/list.ts +5 -38
- package/src/domains/modifier/commands/lookup.ts +8 -79
- package/src/domains/modifier/commands/sample.ts +2 -1
- package/src/domains/modifier/mcp/specs.ts +15 -94
- package/src/domains/modifier/operations/lookup.ts +5 -3
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +2 -1
- package/src/domains/modifier/stories.test.ts +20 -0
- package/src/domains/modifier/stories.ts +86 -0
- package/src/domains/ontology/commands/list.test.ts +5 -3
- package/src/domains/ontology/commands/list.ts +5 -58
- package/src/domains/ontology/commands/show.test.ts +85 -9
- package/src/domains/ontology/commands/show.ts +6 -58
- package/src/domains/ontology/formatters/index.ts +1 -0
- package/src/domains/ontology/formatters/list.ts +37 -12
- package/src/domains/ontology/formatters/show.ts +361 -64
- package/src/domains/ontology/helpers/buildClassTree.ts +89 -0
- package/src/domains/ontology/helpers/completeClassNames.ts +43 -0
- package/src/domains/ontology/helpers/expandOntologyIris.ts +79 -0
- package/src/domains/ontology/helpers/index.ts +14 -0
- package/src/domains/ontology/helpers/queryClasses.ts +32 -16
- package/src/domains/ontology/helpers/queryProperties.ts +39 -6
- package/src/domains/ontology/helpers/queryTboxFacts.ts +160 -0
- package/src/domains/ontology/mcp/specs.ts +7 -84
- package/src/domains/ontology/operations/listOntologies.test.ts +80 -3
- package/src/domains/ontology/operations/listOntologies.ts +126 -30
- package/src/domains/ontology/operations/showOntology.test.ts +131 -12
- package/src/domains/ontology/operations/showOntology.ts +289 -7
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +4 -2
- package/src/domains/ontology/stories.test.ts +36 -0
- package/src/domains/ontology/stories.ts +153 -0
- package/src/domains/refs/operations/updateRefs.ts +2 -38
- package/src/domains/setup/commands/index.ts +1 -0
- package/src/domains/setup/commands/setup.ts +70 -0
- package/src/domains/setup/commands/skills.test.ts +6 -2
- package/src/domains/setup/commands/skills.ts +6 -2
- package/src/domains/setup/helpers/runSetupTask.test.ts +148 -150
- package/src/domains/setup/helpers/runSetupTask.ts +62 -70
- package/src/domains/setup/index.ts +7 -3
- package/src/domains/setup/operations/setupLsp.test.ts +3 -2
- package/src/domains/setup/operations/setupLsp.ts +7 -2
- package/src/domains/setup/operations/setupMcp.test.ts +6 -1
- package/src/domains/shared/bootStore.bareCore.test.ts +63 -0
- package/src/domains/shared/bootStore.test.ts +82 -0
- package/src/domains/shared/bootStore.ts +57 -18
- package/src/domains/shared/compactUri.test.ts +11 -0
- package/src/domains/shared/compactUri.ts +10 -5
- package/src/domains/shared/context.ts +2 -2
- package/src/domains/shared/contracts.ts +11 -0
- package/src/domains/shared/createInteractivePromptSession.test.ts +439 -0
- package/src/domains/shared/createInteractivePromptSession.ts +236 -0
- package/src/domains/shared/emptyErrorRecovery.test.ts +23 -26
- package/src/domains/shared/extractLocalName.test.ts +3 -3
- package/src/domains/shared/formatters.ts +23 -2
- package/src/domains/shared/listTiers.ts +40 -0
- package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
- package/src/domains/shared/loaders/bundledLoader.ts +158 -12
- package/src/domains/shared/loaders/gitLoader.ts +1 -2
- package/src/domains/shared/loaders/index.ts +4 -1
- package/src/domains/shared/loaders/localLoader.ts +2 -4
- package/src/domains/shared/loaders/readPackageDir.test.ts +58 -0
- package/src/domains/shared/loaders/readPackageDir.ts +82 -9
- package/src/domains/shared/loaders/storyAssetsPlugin.test.ts +84 -0
- package/src/domains/shared/loaders/storyAssetsPlugin.ts +46 -0
- package/src/domains/shared/lookupMany.test.ts +135 -0
- package/src/domains/shared/lookupMany.ts +50 -2
- package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
- package/src/domains/shared/mergeAndParseRefs.ts +44 -0
- package/src/domains/shared/namespaces.ts +13 -5
- package/src/domains/shared/packages.ts +10 -17
- package/src/domains/shared/parseSampleCount.test.ts +47 -0
- package/src/domains/shared/parseSampleCount.ts +45 -0
- package/src/domains/shared/prefixes.test.ts +211 -0
- package/src/domains/shared/prefixes.ts +182 -15
- package/src/domains/shared/renderers.ts +5 -5
- package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
- package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
- package/src/domains/shared/resolveLookupExitCode.test.ts +48 -0
- package/src/domains/shared/resolveLookupExitCode.ts +42 -0
- package/src/domains/shared/runtime.ts +4 -63
- package/src/domains/shared/semanticPackage.test.ts +89 -0
- package/src/domains/shared/semanticPackage.ts +34 -3
- package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
- package/src/domains/shared/stories/compileLookupCommand.ts +102 -0
- package/src/domains/shared/stories/compileLookupTool.test.ts +105 -0
- package/src/domains/shared/stories/compileLookupTool.ts +96 -0
- package/src/domains/shared/stories/compileReadCommand.test.ts +121 -0
- package/src/domains/shared/stories/compileReadCommand.ts +48 -0
- package/src/domains/shared/stories/compileReadTool.test.ts +64 -0
- package/src/domains/shared/stories/compileReadTool.ts +38 -0
- package/src/domains/shared/stories/condense.test.ts +18 -0
- package/src/domains/shared/stories/condense.ts +15 -0
- package/src/domains/shared/stories/index.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.test.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.ts +22 -0
- package/src/domains/shared/stories/pack/applyPackFilters.test.ts +151 -0
- package/src/domains/shared/stories/pack/applyPackFilters.ts +111 -0
- package/src/domains/shared/stories/pack/applyPackSearch.test.ts +57 -0
- package/src/domains/shared/stories/pack/applyPackSearch.ts +41 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +81 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.ts +154 -0
- package/src/domains/shared/stories/pack/bundled/index.ts +23 -0
- package/src/domains/shared/stories/pack/bundled/standardPack.ts +164 -0
- package/src/domains/shared/stories/pack/bundled/tierPack.ts +50 -0
- package/src/domains/shared/stories/pack/collectPackStories.test.ts +406 -0
- package/src/domains/shared/stories/pack/collectPackStories.ts +158 -0
- package/src/domains/shared/stories/pack/compilePackCommands.ts +50 -0
- package/src/domains/shared/stories/pack/compilePackStories.test.ts +751 -0
- package/src/domains/shared/stories/pack/compilePackStories.ts +724 -0
- package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +55 -0
- package/src/domains/shared/stories/pack/index.ts +42 -0
- package/src/domains/shared/stories/pack/reservedVerbs.test.ts +213 -0
- package/src/domains/shared/stories/pack/reservedVerbs.ts +170 -0
- package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
- package/src/domains/shared/stories/pack/standardParity.test.ts +381 -0
- package/src/domains/shared/stories/pack/types.ts +224 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +742 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +859 -0
- package/src/domains/shared/stories/projectCliParameters.test.ts +59 -0
- package/src/domains/shared/stories/projectCliParameters.ts +57 -0
- package/src/domains/shared/stories/projectToolParams.test.ts +50 -0
- package/src/domains/shared/stories/projectToolParams.ts +32 -0
- package/src/domains/shared/stories/requirePragmaContext.test.ts +23 -0
- package/src/domains/shared/stories/requirePragmaContext.ts +23 -0
- package/src/domains/shared/stories/resolveLookupDetailed.test.ts +57 -0
- package/src/domains/shared/stories/resolveLookupDetailed.ts +27 -0
- package/src/domains/shared/stories/types.ts +179 -0
- package/src/domains/shared/suggestions/expandGlob.ts +1 -0
- package/src/domains/shared/suggestions/suggestNames.ts +43 -10
- package/src/domains/shared/types/index.ts +5 -9
- package/src/domains/shared/types/ontology.ts +119 -24
- package/src/domains/shared/types/standard.ts +9 -52
- package/src/domains/skill/commands/index.ts +3 -1
- package/src/domains/skill/commands/list.test.ts +6 -2
- package/src/domains/skill/commands/list.ts +5 -63
- package/src/domains/skill/commands/lookup.test.ts +118 -0
- package/src/domains/skill/commands/lookup.ts +14 -0
- package/src/domains/skill/formatters/index.ts +1 -0
- package/src/domains/skill/formatters/lookup.test.ts +46 -0
- package/src/domains/skill/formatters/lookup.ts +57 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +0 -1
- package/src/domains/skill/index.ts +7 -3
- package/src/domains/skill/mcp/specs.ts +10 -29
- package/src/domains/skill/operations/discover.test.ts +61 -30
- package/src/domains/skill/operations/discover.ts +28 -37
- package/src/domains/skill/operations/index.ts +2 -1
- package/src/domains/skill/operations/list.test.ts +15 -7
- package/src/domains/skill/operations/lookup.test.ts +91 -0
- package/src/domains/skill/operations/lookup.ts +70 -0
- package/src/domains/skill/stories.test.ts +43 -0
- package/src/domains/skill/stories.ts +103 -0
- package/src/domains/skill/types.ts +8 -0
- package/src/domains/token/commands/lookup.test.ts +8 -0
- package/src/domains/token/commands/lookup.ts +12 -0
- package/src/domains/token/commands/sample.ts +2 -1
- package/src/domains/token/featureFlag.ts +17 -0
- package/src/domains/token/index.ts +5 -0
- package/src/domains/token/mcp/specs.ts +18 -2
- package/src/domains/token/orchestration/resolveTokenLookup.ts +2 -1
- package/src/domains/trace/commands/resolveTraceLimit.test.ts +31 -0
- package/src/domains/trace/commands/show.ts +30 -4
- package/src/domains/trace/tracePlugin.test.ts +1 -1
- package/src/index.ts +1 -13
- package/src/mcp/registerResources.test.ts +382 -74
- package/src/mcp/registerResources.ts +5 -348
- package/src/mcp/resources/buildGraphIndex.ts +167 -0
- package/src/mcp/resources/buildResourceList.test.ts +97 -0
- package/src/mcp/resources/buildResourceList.ts +176 -0
- package/src/mcp/resources/classifyEntity.test.ts +40 -0
- package/src/mcp/resources/classifyEntity.ts +27 -0
- package/src/mcp/resources/constants.ts +105 -0
- package/src/mcp/resources/displayPredicates.ts +62 -0
- package/src/mcp/resources/pickFirstValue.test.ts +29 -0
- package/src/mcp/resources/pickFirstValue.ts +26 -0
- package/src/mcp/resources/pickPrimaryType.test.ts +41 -0
- package/src/mcp/resources/pickPrimaryType.ts +26 -0
- package/src/mcp/resources/rankUriCompletions.test.ts +52 -0
- package/src/mcp/resources/rankUriCompletions.ts +64 -0
- package/src/mcp/resources/readEntity.ts +169 -0
- package/src/mcp/resources/registerResources.ts +126 -0
- package/src/mcp/resources/types.ts +128 -0
- package/src/mcp/tools/index.ts +22 -5
- package/src/mcp/tools/registerTools.test.ts +167 -34
- package/src/mcp/types.ts +4 -0
- package/src/pipeline/collectCommands.test.ts +151 -1
- package/src/pipeline/collectCommands.ts +35 -13
- package/src/pipeline/createProgram.test.ts +5 -1
- package/src/pipeline/createProgram.ts +2 -2
- package/src/pipeline/firstRun.test.ts +80 -0
- package/src/pipeline/firstRun.ts +99 -0
- package/src/pipeline/parseGlobalFlags.test.ts +102 -1
- package/src/pipeline/parseGlobalFlags.ts +98 -9
- package/src/pipeline/resolveCommandKind.test.ts +12 -0
- package/src/pipeline/resolveCommandKind.ts +4 -0
- package/src/pipeline/rootHelp.test.ts +87 -0
- package/src/pipeline/rootHelp.ts +265 -0
- package/src/pipeline/runCli.orchestration.test.ts +28 -12
- package/src/pipeline/runCli.test.ts +17 -4
- package/src/pipeline/runCli.ts +202 -25
- package/src/testing/cli.ts +30 -2
- package/src/testing/createTestMcpClient.ts +4 -1
- package/src/testing/dsFixtures.ts +21 -4
- package/src/testing/index.ts +7 -0
- package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
- package/src/testing/integration/cli-user-stories.test.ts +63 -0
- package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
- package/src/testing/integration/edge-cases.test.ts +62 -50
- package/src/testing/integration/executor-execution.test.ts +103 -0
- package/src/testing/integration/executor-golden.test.ts +145 -0
- package/src/testing/integration/mcp-surface.test.ts +40 -15
- package/src/testing/integration/parity.test.ts +136 -82
- package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
- package/src/testing/setupXdgIsolation.ts +26 -0
- package/src/testing/standardParityFixtures.ts +35 -0
- package/src/testing/store.ts +4 -4
- package/src/testing/storyFixtures.ts +63 -0
- package/src/domains/create/commands/component.test.ts +0 -166
- package/src/domains/create/commands/component.ts +0 -123
- package/src/domains/create/commands/index.ts +0 -3
- package/src/domains/create/commands/package.test.ts +0 -35
- package/src/domains/create/commands/package.ts +0 -21
- package/src/domains/create/generators.ts +0 -8
- package/src/domains/standard/commands/categories.test.ts +0 -70
- package/src/domains/standard/commands/categories.ts +0 -48
- package/src/domains/standard/commands/index.ts +0 -6
- package/src/domains/standard/commands/list.test.ts +0 -105
- package/src/domains/standard/commands/list.ts +0 -90
- package/src/domains/standard/commands/lookup.test.ts +0 -135
- package/src/domains/standard/commands/lookup.ts +0 -99
- package/src/domains/standard/commands/sample.ts +0 -57
- package/src/domains/standard/formatters/categories.test.ts +0 -44
- package/src/domains/standard/formatters/categories.ts +0 -38
- package/src/domains/standard/formatters/index.ts +0 -10
- package/src/domains/standard/formatters/list.test.ts +0 -169
- package/src/domains/standard/formatters/list.ts +0 -184
- package/src/domains/standard/formatters/lookup.test.ts +0 -95
- package/src/domains/standard/formatters/lookup.ts +0 -101
- package/src/domains/standard/formatters/sample.ts +0 -15
- package/src/domains/standard/formatters/types.ts +0 -31
- package/src/domains/standard/index.ts +0 -40
- package/src/domains/standard/mcp/index.ts +0 -2
- package/src/domains/standard/mcp/specs.ts +0 -244
- package/src/domains/standard/operations/categories.test.ts +0 -61
- package/src/domains/standard/operations/categories.ts +0 -38
- package/src/domains/standard/operations/index.ts +0 -6
- package/src/domains/standard/operations/list.test.ts +0 -75
- package/src/domains/standard/operations/list.ts +0 -64
- package/src/domains/standard/operations/lookup.test.ts +0 -58
- package/src/domains/standard/operations/lookup.ts +0 -151
- package/src/domains/standard/operations/sample.ts +0 -35
- package/src/domains/standard/orchestration/buildStandardFilters.ts +0 -11
- package/src/domains/standard/orchestration/index.ts +0 -4
- package/src/domains/standard/orchestration/resolveStandardList.ts +0 -45
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +0 -32
- package/src/domains/standard/orchestration/standardEmptyError.test.ts +0 -33
- package/src/domains/standard/orchestration/standardEmptyError.ts +0 -29
- package/src/domains/standard/standardConfig.ts +0 -42
- package/src/domains/standard/types.ts +0 -15
- package/src/domains/tier/commands/index.ts +0 -3
- package/src/domains/tier/commands/list.test.ts +0 -67
- package/src/domains/tier/commands/list.ts +0 -59
- package/src/domains/tier/formatters/index.ts +0 -3
- package/src/domains/tier/formatters/list.test.ts +0 -33
- package/src/domains/tier/formatters/list.ts +0 -45
- package/src/domains/tier/index.ts +0 -17
- package/src/domains/tier/mcp/index.ts +0 -2
- package/src/domains/tier/mcp/specs.ts +0 -38
- package/src/domains/tier/operations/index.ts +0 -3
- package/src/domains/tier/operations/list.test.ts +0 -32
- package/src/domains/tier/operations/list.ts +0 -33
- package/src/pipeline/runInteractiveCommand.ts +0 -198
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ See [docs/getting-started.md](docs/getting-started.md) for a full walkthrough.
|
|
|
22
22
|
|
|
23
23
|
## CLI Commands
|
|
24
24
|
|
|
25
|
-
pragma organizes commands into
|
|
25
|
+
pragma organizes commands into 17 domains — counting every directory under `src/domains/` except `shared/`, which holds cross-domain infrastructure rather than commands. The day-to-day domains are documented below; two are specialised and not covered here: `graphql` (compile TTL ontologies into GraphQL schema artifacts) and `trace` (query access tracing). Every command supports three output modes: plain text (default), `--llm` (condensed Markdown), and `--format json` (structured JSON).
|
|
26
26
|
|
|
27
27
|
### Block
|
|
28
28
|
|
|
@@ -36,7 +36,7 @@ pragma organizes commands into 14 domains. Every command supports three output m
|
|
|
36
36
|
| Command | Description |
|
|
37
37
|
|---------|-------------|
|
|
38
38
|
| `pragma standard list` | List all code standards |
|
|
39
|
-
| `pragma standard lookup <name>` | Show standard
|
|
39
|
+
| `pragma standard lookup <name>` | Show standard details (`--detailed` adds do/don't examples) |
|
|
40
40
|
| `pragma standard categories` | List standard categories with counts |
|
|
41
41
|
|
|
42
42
|
### Modifier
|
|
@@ -46,13 +46,17 @@ pragma organizes commands into 14 domains. Every command supports three output m
|
|
|
46
46
|
| `pragma modifier list` | List all modifier families |
|
|
47
47
|
| `pragma modifier lookup <name>` | Show modifier family with values |
|
|
48
48
|
|
|
49
|
-
###
|
|
49
|
+
### Tokens
|
|
50
50
|
|
|
51
51
|
| Command | Description |
|
|
52
52
|
|---------|-------------|
|
|
53
|
-
| `pragma
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
| `pragma tokens add-config` | Add Terrazzo config for token build |
|
|
54
|
+
|
|
55
|
+
> **Note:** The token *read* commands (`token list`, `token lookup`, `token sample`)
|
|
56
|
+
> are currently disabled behind a feature flag
|
|
57
|
+
> (`src/domains/token/featureFlag.ts`) because the published design-system
|
|
58
|
+
> data does not yet contain token instances. They will return once token
|
|
59
|
+
> data ships.
|
|
56
60
|
|
|
57
61
|
### Tier
|
|
58
62
|
|
|
@@ -65,7 +69,10 @@ pragma organizes commands into 14 domains. Every command supports three output m
|
|
|
65
69
|
| Command | Description |
|
|
66
70
|
|---------|-------------|
|
|
67
71
|
| `pragma ontology list` | List loaded ontology namespaces |
|
|
68
|
-
| `pragma ontology show <prefix>` | Show
|
|
72
|
+
| `pragma ontology show <prefix>` | Show the TBox: name, metadata, class hierarchy tree with instance counts and relations |
|
|
73
|
+
| `pragma ontology show <prefix> --properties` | Also show datatype properties (attributes) |
|
|
74
|
+
| `pragma ontology show <prefix> --full-uris` | Show full URIs instead of compact prefixed IRIs |
|
|
75
|
+
| `pragma ontology show <prefix> --class <Class>` | Deep-dive into one class: super chain, direct/inherited properties, reverse references, sample instances, and ready-to-run follow-up queries |
|
|
69
76
|
|
|
70
77
|
### Graph
|
|
71
78
|
|
|
@@ -87,6 +94,7 @@ pragma organizes commands into 14 domains. Every command supports three output m
|
|
|
87
94
|
| Command | Description |
|
|
88
95
|
|---------|-------------|
|
|
89
96
|
| `pragma skill list` | List discovered agent skills from installed packages |
|
|
97
|
+
| `pragma skill lookup <name...>` | Show full SKILL.md instructions for skills by name |
|
|
90
98
|
|
|
91
99
|
### LLM
|
|
92
100
|
|
|
@@ -96,15 +104,16 @@ pragma organizes commands into 14 domains. Every command supports three output m
|
|
|
96
104
|
|
|
97
105
|
### Setup
|
|
98
106
|
|
|
99
|
-
All setup commands support `--dry-run
|
|
107
|
+
All setup commands support `--dry-run`; `--yes` and `--undo` are supported
|
|
108
|
+
where shown below.
|
|
100
109
|
|
|
101
110
|
| Command | Description |
|
|
102
111
|
|---------|-------------|
|
|
103
|
-
| `pragma setup
|
|
104
|
-
| `pragma setup mcp` | Configure pragma MCP server for AI harnesses |
|
|
105
|
-
| `pragma setup completions` | Install shell completions (bash/zsh/fish) |
|
|
106
|
-
| `pragma setup skills` | Symlink agent skills into harness config |
|
|
107
|
-
| `pragma setup lsp` |
|
|
112
|
+
| `pragma setup` | Run all setup steps (completions + LSP + MCP); supports `--yes`, `--undo` |
|
|
113
|
+
| `pragma setup mcp` | Configure pragma MCP server for AI harnesses; supports `--yes`, `--undo` |
|
|
114
|
+
| `pragma setup completions` | Install shell completions (bash/zsh/fish); supports `--undo` |
|
|
115
|
+
| `pragma setup skills` | Symlink agent skills into harness config; supports `--yes` |
|
|
116
|
+
| `pragma setup lsp` | Install the Terrazzo LSP VS Code extension; supports `--undo` |
|
|
108
117
|
|
|
109
118
|
### Create
|
|
110
119
|
|
|
@@ -112,8 +121,9 @@ Create commands scaffold new code using summon generators. They support `--undo`
|
|
|
112
121
|
|
|
113
122
|
| Command | Description |
|
|
114
123
|
|---------|-------------|
|
|
115
|
-
| `pragma create component <
|
|
116
|
-
| `pragma create package
|
|
124
|
+
| `pragma create component <framework> [path]` | Scaffold a new design system component |
|
|
125
|
+
| `pragma create package` | Scaffold a new monorepo package (`--name`, `--type`, …) |
|
|
126
|
+
| `pragma create application [path]` | Scaffold a complete React application with SSR and routing |
|
|
117
127
|
|
|
118
128
|
### Doctor
|
|
119
129
|
|
|
@@ -125,8 +135,19 @@ Create commands scaffold new code using summon generators. They support `--undo`
|
|
|
125
135
|
|
|
126
136
|
| Command | Description |
|
|
127
137
|
|---------|-------------|
|
|
128
|
-
| `pragma info` | Show pragma version,
|
|
129
|
-
|
|
138
|
+
| `pragma info` | Show pragma version, config, update status, and store summary |
|
|
139
|
+
|
|
140
|
+
### Upgrade
|
|
141
|
+
|
|
142
|
+
| Command | Description |
|
|
143
|
+
|---------|-------------|
|
|
144
|
+
| `pragma upgrade` | Upgrade the pragma CLI to the latest version (`--dry-run` to check only) |
|
|
145
|
+
|
|
146
|
+
### Refs
|
|
147
|
+
|
|
148
|
+
| Command | Description |
|
|
149
|
+
|---------|-------------|
|
|
150
|
+
| `pragma update-refs` | Fetch or clone git-referenced semantic packages into the local cache (needed before `skill list` can discover skills) |
|
|
130
151
|
|
|
131
152
|
## Global Flags
|
|
132
153
|
|
|
@@ -143,7 +164,7 @@ Setup and create commands support `--undo` to reverse previous operations. The u
|
|
|
143
164
|
```bash
|
|
144
165
|
pragma setup mcp --undo # Remove MCP configuration
|
|
145
166
|
pragma setup completions --undo # Remove shell completions
|
|
146
|
-
pragma create component Foo --undo # Remove scaffolded component files
|
|
167
|
+
pragma create component react src/lib/Foo --undo # Remove scaffolded component files
|
|
147
168
|
```
|
|
148
169
|
|
|
149
170
|
## MCP Integration
|
|
@@ -173,27 +194,27 @@ Or add manually to your `.mcp.json`:
|
|
|
173
194
|
}
|
|
174
195
|
```
|
|
175
196
|
|
|
176
|
-
### MCP Tools (
|
|
197
|
+
### MCP Tools (28)
|
|
177
198
|
|
|
178
199
|
All tools return a consistent envelope: `{ ok: true, data, meta }` for success, `{ ok: true, condensed: true, text, tokens }` for condensed mode, or `{ ok: false, error }` with structured recovery on failure.
|
|
179
200
|
|
|
180
|
-
#### Read Tools (
|
|
201
|
+
#### Read Tools (18)
|
|
202
|
+
|
|
203
|
+
Lookup tools accept a `names` array, so several entities can be fetched in
|
|
204
|
+
one call (partial results are returned alongside per-name errors).
|
|
181
205
|
|
|
182
206
|
| Tool | Description |
|
|
183
207
|
|------|-------------|
|
|
184
208
|
| `block_list` | List blocks with optional tier filtering and disclosure levels |
|
|
185
209
|
| `block_lookup` | Look up detailed block info (anatomy, modifiers, tokens, standards) |
|
|
186
|
-
| `
|
|
210
|
+
| `block_sample` | Return random complete block instances for shape discovery |
|
|
187
211
|
| `standard_list` | List code standards with optional category/search filtering |
|
|
188
212
|
| `standard_lookup` | Look up standard with do/don't code examples |
|
|
189
|
-
| `standard_batch_lookup` | Look up multiple standards by name in a single call |
|
|
190
213
|
| `standard_categories` | List standard categories with counts |
|
|
214
|
+
| `standard_sample` | Return random complete standard instances for shape discovery |
|
|
191
215
|
| `modifier_list` | List modifier families |
|
|
192
216
|
| `modifier_lookup` | Look up modifier family with values |
|
|
193
|
-
| `
|
|
194
|
-
| `token_list` | List design tokens with optional category filtering |
|
|
195
|
-
| `token_lookup` | Look up token with theme-resolved values |
|
|
196
|
-
| `token_batch_lookup` | Look up multiple tokens by name in a single call |
|
|
217
|
+
| `modifier_sample` | Return random complete modifier instances for shape discovery |
|
|
197
218
|
| `tier_list` | List all tiers in the hierarchy |
|
|
198
219
|
| `config_show` | Show current tier and channel configuration |
|
|
199
220
|
| `ontology_list` | List loaded ontology namespaces with class/property counts |
|
|
@@ -201,8 +222,12 @@ All tools return a consistent envelope: `{ ok: true, data, meta }` for success,
|
|
|
201
222
|
| `graph_query` | Execute raw SPARQL against the ke store |
|
|
202
223
|
| `graph_inspect` | Inspect all triples for a URI |
|
|
203
224
|
| `skill_list` | List discovered agent skills |
|
|
225
|
+
| `skill_lookup` | Get full SKILL.md content for skills by name |
|
|
204
226
|
|
|
205
|
-
|
|
227
|
+
`token_list`, `token_lookup`, and `token_sample` are feature-flagged off
|
|
228
|
+
until token data ships (see the Tokens note above).
|
|
229
|
+
|
|
230
|
+
#### Write Tools (6)
|
|
206
231
|
|
|
207
232
|
| Tool | Description |
|
|
208
233
|
|------|-------------|
|
|
@@ -211,6 +236,7 @@ All tools return a consistent envelope: `{ ok: true, data, meta }` for success,
|
|
|
211
236
|
| `tokens_add_config` | Add Terrazzo token build configuration |
|
|
212
237
|
| `create_component` | Scaffold a new design system component |
|
|
213
238
|
| `create_package` | Scaffold a new monorepo package |
|
|
239
|
+
| `create_application` | Scaffold a complete React application |
|
|
214
240
|
|
|
215
241
|
#### Orientation Tools (2)
|
|
216
242
|
|
|
@@ -280,12 +306,12 @@ Error responses include a `recovery` object that tells agents what tool to call
|
|
|
280
306
|
|
|
281
307
|
### Batch Results
|
|
282
308
|
|
|
283
|
-
|
|
309
|
+
Lookup tools accept a `names` array and return partial results — valid items in `results`, failures in `errors`:
|
|
284
310
|
|
|
285
311
|
```json
|
|
286
312
|
{
|
|
287
313
|
"results": [{ "name": "Button", ... }],
|
|
288
|
-
"errors": [{ "
|
|
314
|
+
"errors": [{ "query": "Buton", "code": "ENTITY_NOT_FOUND", "message": "...", "suggestions": ["Button"] }]
|
|
289
315
|
}
|
|
290
316
|
```
|
|
291
317
|
|
|
@@ -295,27 +321,82 @@ Every subject URI in the ke graph is exposed as a discoverable MCP resource via
|
|
|
295
321
|
|
|
296
322
|
## Configuration
|
|
297
323
|
|
|
298
|
-
|
|
324
|
+
Configuration is layered: built-in defaults, then the global file at
|
|
325
|
+
`$XDG_CONFIG_HOME/pragma/config.json` (default `~/.config/pragma/config.json`),
|
|
326
|
+
then the nearest `pragma.config.json` at or above the current directory —
|
|
327
|
+
each field won by the most specific layer that sets it. Install pragma
|
|
328
|
+
globally, configure once, and override per project:
|
|
299
329
|
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"tier": "apps/lxd",
|
|
333
|
+
"channel": "normal"
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
`pragma config tier|channel|framework|trace` writes to the nearest existing
|
|
338
|
+
project file, or to the global file when no project is configured; pass
|
|
339
|
+
`--local` or `--global` to pick the layer explicitly. Every write echoes the
|
|
340
|
+
file it wrote, and `pragma config show` reports which layer supplied each
|
|
341
|
+
value.
|
|
342
|
+
|
|
343
|
+
### Custom read stories (experimental)
|
|
344
|
+
|
|
345
|
+
A config (or a semantic package, via `stories/*.json`) can declare
|
|
346
|
+
declarative read stories — any ontology loaded through `packages` gets
|
|
347
|
+
`pragma <noun> list` / `<noun> lookup` on both the CLI and MCP:
|
|
348
|
+
|
|
349
|
+
```json
|
|
350
|
+
{
|
|
351
|
+
"prefixes": { "ex": "http://example.org/recipes/" },
|
|
352
|
+
"packages": [{ "name": "my-recipes", "source": "file:///data/recipes" }],
|
|
353
|
+
"stories": [
|
|
354
|
+
{
|
|
355
|
+
"noun": "recipe",
|
|
356
|
+
"description": "List recipes",
|
|
357
|
+
"list": {
|
|
358
|
+
"query": "SELECT ?uri ?name ?category WHERE { ?uri a ex:Recipe ; ex:name ?name ; ex:category ?category } ORDER BY ?name",
|
|
359
|
+
"columns": [{ "field": "name" }, { "field": "category" }],
|
|
360
|
+
"filters": [
|
|
361
|
+
{ "param": "category", "variable": "category", "values": ["breakfast", "soup"] }
|
|
362
|
+
]
|
|
363
|
+
},
|
|
364
|
+
"lookup": {
|
|
365
|
+
"type": "ex:Recipe",
|
|
366
|
+
"by": "ex:name",
|
|
367
|
+
"fields": [{ "name": "category", "property": "ex:category" }],
|
|
368
|
+
"sections": [{ "name": "instructions", "property": "ex:instructions" }]
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
]
|
|
372
|
+
}
|
|
303
373
|
```
|
|
304
374
|
|
|
305
|
-
|
|
375
|
+
The lookup query is generated (user input is escaped, never interpolated by
|
|
376
|
+
the pack), the store stays read-only, and config-declared stories override
|
|
377
|
+
package-shipped ones on noun collisions. Declared `filters` become
|
|
378
|
+
`pragma recipe list --category soup` on the CLI and an enum parameter on the
|
|
379
|
+
MCP tool; they are row predicates applied after the query runs, so filter
|
|
380
|
+
input can never inject SPARQL and the query's ordering is preserved. The
|
|
381
|
+
format is experimental and may change.
|
|
306
382
|
|
|
307
383
|
## Error Handling
|
|
308
384
|
|
|
309
|
-
|
|
385
|
+
Lookup errors report each failed name with typo suggestions:
|
|
310
386
|
|
|
311
387
|
```
|
|
312
|
-
|
|
388
|
+
**Errors:**
|
|
389
|
+
- Buton: block "Buton" not found.
|
|
390
|
+
Did you mean: Button?
|
|
391
|
+
```
|
|
313
392
|
|
|
314
|
-
|
|
315
|
-
- Button
|
|
316
|
-
- ButtonGroup
|
|
393
|
+
Other errors carry a code and, where available, a recovery hint:
|
|
317
394
|
|
|
318
|
-
|
|
395
|
+
```
|
|
396
|
+
## Error: EMPTY_RESULTS
|
|
397
|
+
No standards found.
|
|
398
|
+
Filters: category=nope
|
|
399
|
+
Recovery: `pragma standard list`
|
|
319
400
|
```
|
|
320
401
|
|
|
321
402
|
With `--format json`, errors are returned as structured JSON with error code, suggestions, and recovery. With `--llm`, errors are rendered as Markdown.
|
|
@@ -336,7 +417,7 @@ With `--format json`, errors are returned as structured JSON with error code, su
|
|
|
336
417
|
|
|
337
418
|
pragma is structured as a domain-driven application using the federation pattern from `@canonical/cli-core`:
|
|
338
419
|
|
|
339
|
-
1. **Domains** —
|
|
420
|
+
1. **Domains** — 17 domain modules (block, config, create, doctor, graph, graphql, info, llm, modifier, ontology, refs, setup, skill, standard, tier, token, trace — every directory under `src/domains/` except the `shared/` infrastructure folder), each contributing `CommandDefinition`s
|
|
340
421
|
2. **Operations** — data retrieval functions that query the ke triple store via SPARQL
|
|
341
422
|
3. **Formatters** — three-mode output adapters (plain/llm/json) for each operation
|
|
342
423
|
4. **Commands** — thin wiring layer connecting Commander.js parameters to operations + formatters
|
|
@@ -364,13 +445,13 @@ bun build --compile --minify src/bin.ts --outfile dist/pragma
|
|
|
364
445
|
|
|
365
446
|
## Dependencies
|
|
366
447
|
|
|
367
|
-
- [`@canonical/ke`](
|
|
448
|
+
- [`@canonical/ke`](../../runtime/ke/) — triple store runtime (Oxigraph WASM)
|
|
368
449
|
- [`@canonical/cli-core`](../core/) — shared CLI machinery (Commander.js registration, help formatting)
|
|
369
|
-
- [`@canonical/task`](../../
|
|
370
|
-
- [`@canonical/harnesses`](../../
|
|
371
|
-
- [`@canonical/summon-core`](../../
|
|
372
|
-
- [`@canonical/summon-component`](../../
|
|
373
|
-
- [`@canonical/summon-package`](../../
|
|
450
|
+
- [`@canonical/task`](../../runtime/task/) — reversible task trees for setup/create with undo support
|
|
451
|
+
- [`@canonical/harnesses`](../../runtime/harnesses/) — AI harness detection (Claude Code, Cursor, Windsurf)
|
|
452
|
+
- [`@canonical/summon-core`](../../summon/core/) — code generation runtime
|
|
453
|
+
- [`@canonical/summon-component`](../../summon/component/) — component generator
|
|
454
|
+
- [`@canonical/summon-package`](../../summon/package/) — package generator
|
|
374
455
|
|
|
375
456
|
## License
|
|
376
457
|
|
package/dist/pragma
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonical/pragma-cli",
|
|
3
3
|
"description": "CLI and MCP server for Canonical's design system.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.31.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|
|
7
7
|
"types": "src/index.ts",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@biomejs/biome": "2.4.9",
|
|
63
|
-
"@canonical/biome-config": "^0.
|
|
64
|
-
"@canonical/typescript-config": "^0.
|
|
65
|
-
"@canonical/webarchitect": "^0.
|
|
63
|
+
"@canonical/biome-config": "^0.31.0",
|
|
64
|
+
"@canonical/typescript-config": "^0.31.0",
|
|
65
|
+
"@canonical/webarchitect": "^0.31.0",
|
|
66
66
|
"@types/bun": "^1.3.10",
|
|
67
67
|
"@types/node": "^24.12.0",
|
|
68
68
|
"@types/react": "^19.2.14",
|
|
@@ -72,16 +72,18 @@
|
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"@canonical/anatomy-dsl": "^0.2.2",
|
|
75
|
-
"@canonical/cli-core": "^0.
|
|
75
|
+
"@canonical/cli-core": "^0.31.0",
|
|
76
76
|
"@canonical/code-standards": "^0.1.2",
|
|
77
77
|
"@canonical/design-system": "^0.1.2",
|
|
78
|
-
"@canonical/harnesses": "^0.
|
|
79
|
-
"@canonical/ke": "^0.
|
|
80
|
-
"@canonical/ke-graphql": "^0.
|
|
81
|
-
"@canonical/summon
|
|
82
|
-
"@canonical/summon-
|
|
83
|
-
"@canonical/summon-
|
|
84
|
-
"@canonical/
|
|
78
|
+
"@canonical/harnesses": "^0.31.0",
|
|
79
|
+
"@canonical/ke": "^0.31.0",
|
|
80
|
+
"@canonical/ke-graphql": "^0.31.0",
|
|
81
|
+
"@canonical/summon": "^0.31.0",
|
|
82
|
+
"@canonical/summon-application": "^0.31.0",
|
|
83
|
+
"@canonical/summon-component": "^0.31.0",
|
|
84
|
+
"@canonical/summon-core": "^0.31.0",
|
|
85
|
+
"@canonical/summon-package": "^0.31.0",
|
|
86
|
+
"@canonical/task": "^0.31.0",
|
|
85
87
|
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
86
88
|
"chalk": "^5.6.2",
|
|
87
89
|
"commander": "^14.0.3",
|
|
@@ -90,5 +92,5 @@
|
|
|
90
92
|
"react": "^19.2.4",
|
|
91
93
|
"zod": "^3.25.0"
|
|
92
94
|
},
|
|
93
|
-
"gitHead": "
|
|
95
|
+
"gitHead": "d4a67ebe42e62b8cf3de77f42f537309ca88d672"
|
|
94
96
|
}
|
|
@@ -16,3 +16,10 @@ export const POLL_INTERVAL_MS = 50;
|
|
|
16
16
|
|
|
17
17
|
/** Maximum time to wait for a spawned server to become ready. */
|
|
18
18
|
export const SPAWN_TIMEOUT_MS = 5_000;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Maximum time to wait for a query response before giving up. Bounds the
|
|
22
|
+
* whole client call so a wedged or slow server can never hang the shell's
|
|
23
|
+
* tab-completion — the query resolves to no candidates instead.
|
|
24
|
+
*/
|
|
25
|
+
export const QUERY_TIMEOUT_MS = 3_000;
|
|
@@ -37,6 +37,16 @@ function makeTree(): CompletionTree {
|
|
|
37
37
|
);
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
name: "detailed",
|
|
42
|
+
description: "Show full detail",
|
|
43
|
+
type: "boolean",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "anatomyOnly",
|
|
47
|
+
description: "Show anatomy only",
|
|
48
|
+
type: "boolean",
|
|
49
|
+
},
|
|
40
50
|
],
|
|
41
51
|
execute: async () => createExitResult(0),
|
|
42
52
|
},
|
|
@@ -90,4 +100,26 @@ describe("handleQuery", () => {
|
|
|
90
100
|
const result = await handleQuery("block list something", makeTree(), ctx);
|
|
91
101
|
expect(result).toBe("");
|
|
92
102
|
});
|
|
103
|
+
|
|
104
|
+
it("strips the leading program name shells forward", async () => {
|
|
105
|
+
// Every generated shell script forwards the full command line, so the
|
|
106
|
+
// program name arrives as the first word.
|
|
107
|
+
const result = await handleQuery("pragma blo", makeTree(), ctx);
|
|
108
|
+
expect(result).toBe("block");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("lists nouns when only the program name is present", async () => {
|
|
112
|
+
const result = await handleQuery("pragma", makeTree(), ctx);
|
|
113
|
+
expect(result).toBe("block\nstandard");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("completes verb flags when the word starts with a dash", async () => {
|
|
117
|
+
const result = await handleQuery("block get --", makeTree(), ctx);
|
|
118
|
+
expect(result).toBe("--anatomy-only\n--detailed");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("filters verb flags by the dash-prefixed partial", async () => {
|
|
122
|
+
const result = await handleQuery("block get --d", makeTree(), ctx);
|
|
123
|
+
expect(result).toBe("--detailed");
|
|
124
|
+
});
|
|
93
125
|
});
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import type { CommandContext, CompletionTree } from "@canonical/cli-core";
|
|
2
2
|
import { resolveCompletion } from "@canonical/cli-core";
|
|
3
|
+
import { PROGRAM_NAME } from "../constants.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Split a raw shell partial into completion words, dropping the leading
|
|
7
|
+
* program name.
|
|
8
|
+
*
|
|
9
|
+
* Every generated shell script forwards the full command line — including the
|
|
10
|
+
* `pragma` program name as the first word — so without this strip the resolver
|
|
11
|
+
* mistakes `pragma` for the noun and returns no candidates. An empty partial
|
|
12
|
+
* (first-Tab, no word yet) resolves to a single empty word so noun completion
|
|
13
|
+
* still fires.
|
|
14
|
+
*
|
|
15
|
+
* @param partial - The raw partial input string from the shell.
|
|
16
|
+
* @returns The completion words with any leading program name removed.
|
|
17
|
+
*/
|
|
18
|
+
function splitCompletionWords(partial: string): string[] {
|
|
19
|
+
const words = partial.length === 0 ? [""] : partial.split(" ");
|
|
20
|
+
return words.at(0) === PROGRAM_NAME ? words.slice(1) : words;
|
|
21
|
+
}
|
|
3
22
|
|
|
4
23
|
/**
|
|
5
24
|
* Resolve a partial CLI input against a completion tree and return
|
|
@@ -22,7 +41,7 @@ export default async function handleQuery(
|
|
|
22
41
|
tree: CompletionTree,
|
|
23
42
|
ctx: CommandContext,
|
|
24
43
|
): Promise<string> {
|
|
25
|
-
const words = partial
|
|
44
|
+
const words = splitCompletionWords(partial);
|
|
26
45
|
const result = resolveCompletion(tree, words);
|
|
27
46
|
if (!result.completer) return "";
|
|
28
47
|
const candidates = await result.completer(result.partial, ctx);
|
|
@@ -26,12 +26,15 @@ vi.mock("./waitForSocket.js", () => ({
|
|
|
26
26
|
|
|
27
27
|
describe("queryCompletions", () => {
|
|
28
28
|
let stdoutSpy: ReturnType<typeof vi.spyOn>;
|
|
29
|
+
const unrefMock = vi.fn();
|
|
29
30
|
|
|
30
31
|
beforeEach(() => {
|
|
31
32
|
vi.clearAllMocks();
|
|
32
33
|
stdoutSpy = vi
|
|
33
34
|
.spyOn(process.stdout, "write")
|
|
34
35
|
.mockImplementation(() => true);
|
|
36
|
+
// The spawned server handle is unref'd so the client can exit immediately.
|
|
37
|
+
spawnMock.mockReturnValue({ unref: unrefMock });
|
|
35
38
|
vi.stubGlobal("Bun", { spawn: spawnMock });
|
|
36
39
|
});
|
|
37
40
|
|
|
@@ -67,6 +70,8 @@ describe("queryCompletions", () => {
|
|
|
67
70
|
|
|
68
71
|
expect(unlinkSyncMock).toHaveBeenCalledWith("/tmp/pragma-completions.sock");
|
|
69
72
|
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
73
|
+
// The server handle is detached so the client is not held alive by it.
|
|
74
|
+
expect(unrefMock).toHaveBeenCalledTimes(1);
|
|
70
75
|
expect(waitForSocketMock).toHaveBeenCalled();
|
|
71
76
|
expect(querySocketMock).toHaveBeenCalledTimes(2);
|
|
72
77
|
expect(stdoutSpy).toHaveBeenCalledWith("block\n");
|
|
@@ -38,12 +38,26 @@ export default async function queryCompletions(partial: string): Promise<void> {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
// No running server — spawn one.
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// No running server — spawn one. Re-invoke THIS executable so completion
|
|
42
|
+
// works from the shipped binary as well as from source: when the entry file
|
|
43
|
+
// exists on disk (source run) spawn `bun run bin.ts`; otherwise (a compiled
|
|
44
|
+
// standalone binary, where bin.ts is embedded, not a file) spawn the binary
|
|
45
|
+
// itself. The old code always spawned `bun run <dir>/../bin.ts`, which does
|
|
46
|
+
// not exist inside a compiled binary, so its server never started and every
|
|
47
|
+
// completion silently returned nothing.
|
|
48
|
+
const entryPath = resolve(import.meta.dirname, "../bin.ts");
|
|
49
|
+
const spawnArgs = existsSync(entryPath)
|
|
50
|
+
? [process.execPath, "run", entryPath, "_completions-server"]
|
|
51
|
+
: [process.execPath, "_completions-server"];
|
|
52
|
+
const server = Bun.spawn(spawnArgs, {
|
|
44
53
|
stdio: ["ignore", "ignore", "ignore"],
|
|
45
54
|
cwd: process.cwd(),
|
|
46
55
|
});
|
|
56
|
+
// Detach the server from the client's lifecycle. Without this the child keeps
|
|
57
|
+
// the client's event loop alive until the server's idle timeout (~10s) fires,
|
|
58
|
+
// so every tab-completion appears to hang for ~10s and the client tears the
|
|
59
|
+
// server down on exit — defeating the persistent-server fast path entirely.
|
|
60
|
+
server.unref();
|
|
47
61
|
|
|
48
62
|
const ready = await waitForSocket(socketPath, SPAWN_TIMEOUT_MS);
|
|
49
63
|
if (!ready) {
|
|
@@ -67,4 +67,35 @@ describe("querySocket", () => {
|
|
|
67
67
|
"connect failed",
|
|
68
68
|
);
|
|
69
69
|
});
|
|
70
|
+
|
|
71
|
+
it("times out and closes the socket when the server never replies", async () => {
|
|
72
|
+
vi.useFakeTimers();
|
|
73
|
+
const end = vi.fn();
|
|
74
|
+
|
|
75
|
+
connectMock.mockImplementation(
|
|
76
|
+
(options: {
|
|
77
|
+
socket: {
|
|
78
|
+
open: (socket: {
|
|
79
|
+
write: () => void;
|
|
80
|
+
flush: () => void;
|
|
81
|
+
end: () => void;
|
|
82
|
+
}) => void;
|
|
83
|
+
};
|
|
84
|
+
}) => {
|
|
85
|
+
// Open but never send data or close — simulate a wedged server.
|
|
86
|
+
options.socket.open({ write: () => {}, flush: () => {}, end });
|
|
87
|
+
return Promise.resolve({});
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
const promise = querySocket("/tmp/pragma.sock", "blo");
|
|
93
|
+
const assertion = expect(promise).rejects.toThrow(/timed out/);
|
|
94
|
+
await vi.advanceTimersByTimeAsync(5000);
|
|
95
|
+
await assertion;
|
|
96
|
+
expect(end).toHaveBeenCalledTimes(1);
|
|
97
|
+
} finally {
|
|
98
|
+
vi.useRealTimers();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
70
101
|
});
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
+
import { QUERY_TIMEOUT_MS } from "./constants.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Connect to a Unix domain socket, send a partial string, and
|
|
3
5
|
* collect the response.
|
|
4
6
|
*
|
|
5
|
-
* Opens a Bun
|
|
6
|
-
*
|
|
7
|
-
*
|
|
7
|
+
* Opens a Bun connection to the socket, writes the partial terminated by a
|
|
8
|
+
* newline, and accumulates response chunks until the server closes the
|
|
9
|
+
* connection. The whole exchange is bounded by {@link QUERY_TIMEOUT_MS}: if a
|
|
10
|
+
* wedged or slow server never replies, the promise rejects rather than hanging
|
|
11
|
+
* the shell's tab-completion indefinitely.
|
|
8
12
|
*
|
|
9
13
|
* @param socketPath - Absolute path to the Unix domain socket.
|
|
10
14
|
* @param partial - The partial CLI input to send for completion.
|
|
@@ -18,10 +22,31 @@ export default function querySocket(
|
|
|
18
22
|
): Promise<string> {
|
|
19
23
|
return new Promise<string>((resolve, reject) => {
|
|
20
24
|
const chunks: Buffer[] = [];
|
|
25
|
+
let settled = false;
|
|
26
|
+
let openSocket: { end: () => void } | undefined;
|
|
27
|
+
|
|
28
|
+
const timer = setTimeout(() => {
|
|
29
|
+
if (settled) return;
|
|
30
|
+
settled = true;
|
|
31
|
+
// Close the connection so a hung server does not leak an open socket.
|
|
32
|
+
openSocket?.end();
|
|
33
|
+
reject(
|
|
34
|
+
new Error(`Completion query timed out after ${QUERY_TIMEOUT_MS}ms`),
|
|
35
|
+
);
|
|
36
|
+
}, QUERY_TIMEOUT_MS);
|
|
37
|
+
|
|
38
|
+
const settle = (run: () => void): void => {
|
|
39
|
+
if (settled) return;
|
|
40
|
+
settled = true;
|
|
41
|
+
clearTimeout(timer);
|
|
42
|
+
run();
|
|
43
|
+
};
|
|
44
|
+
|
|
21
45
|
Bun.connect({
|
|
22
46
|
unix: socketPath,
|
|
23
47
|
socket: {
|
|
24
48
|
open(socket) {
|
|
49
|
+
openSocket = socket;
|
|
25
50
|
socket.write(`${partial}\n`);
|
|
26
51
|
socket.flush();
|
|
27
52
|
},
|
|
@@ -29,16 +54,18 @@ export default function querySocket(
|
|
|
29
54
|
chunks.push(Buffer.from(data));
|
|
30
55
|
},
|
|
31
56
|
close() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
.
|
|
35
|
-
|
|
57
|
+
settle(() =>
|
|
58
|
+
resolve(
|
|
59
|
+
Buffer.concat(chunks)
|
|
60
|
+
.toString("utf-8")
|
|
61
|
+
.replace(/\r?\n$/, ""),
|
|
62
|
+
),
|
|
36
63
|
);
|
|
37
64
|
},
|
|
38
65
|
error(_socket, err) {
|
|
39
|
-
reject(err);
|
|
66
|
+
settle(() => reject(err));
|
|
40
67
|
},
|
|
41
68
|
},
|
|
42
|
-
}).catch(reject);
|
|
69
|
+
}).catch((err) => settle(() => reject(err)));
|
|
43
70
|
});
|
|
44
71
|
}
|