@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
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
10
10
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
11
11
|
import type { PragmaRuntime } from "../../domains/shared/runtime.js";
|
|
12
|
+
import { TOKEN_READ_SURFACE_ENABLED } from "../../domains/token/featureFlag.js";
|
|
12
13
|
import createTestMcpClient from "../helpers/createTestMcpClient.js";
|
|
13
14
|
import createTestRuntime from "../helpers/createTestRuntime.js";
|
|
14
15
|
|
|
@@ -55,7 +56,7 @@ describe("capabilities", () => {
|
|
|
55
56
|
expect(toolNames).toContain("block_list");
|
|
56
57
|
expect(toolNames).toContain("capabilities");
|
|
57
58
|
expect(data.tools.every((t) => t.use_when.length > 0)).toBe(true);
|
|
58
|
-
expect(data.counts.total).toBe(
|
|
59
|
+
expect(data.counts.total).toBe(TOKEN_READ_SURFACE_ENABLED ? 34 : 31);
|
|
59
60
|
expect(data.conventions).toBeDefined();
|
|
60
61
|
expect(data.version).toBeDefined();
|
|
61
62
|
});
|
|
@@ -190,7 +191,11 @@ describe("standard_lookup", () => {
|
|
|
190
191
|
results: { name: string; extends?: string }[];
|
|
191
192
|
};
|
|
192
193
|
expect(data.results[0]?.name).toBe("react/component/props");
|
|
193
|
-
|
|
194
|
+
// Pack entities keep cs:extends as the raw IRI in data (compaction is
|
|
195
|
+
// display-time only) — a pinned PARITY_GAP of the standard cutover.
|
|
196
|
+
expect(data.results[0]?.extends).toBe(
|
|
197
|
+
"http://pragma.canonical.com/codestandards#react_folder",
|
|
198
|
+
);
|
|
194
199
|
});
|
|
195
200
|
});
|
|
196
201
|
|
|
@@ -240,7 +245,7 @@ describe("modifier_lookup", () => {
|
|
|
240
245
|
// Token
|
|
241
246
|
// ---------------------------------------------------------------------------
|
|
242
247
|
|
|
243
|
-
describe("token_list", () => {
|
|
248
|
+
describe.skipIf(!TOKEN_READ_SURFACE_ENABLED)("token_list", () => {
|
|
244
249
|
it("returns tokens", async () => {
|
|
245
250
|
const res = await client.callTool({
|
|
246
251
|
name: "token_list",
|
|
@@ -252,7 +257,7 @@ describe("token_list", () => {
|
|
|
252
257
|
});
|
|
253
258
|
});
|
|
254
259
|
|
|
255
|
-
describe("token_lookup", () => {
|
|
260
|
+
describe.skipIf(!TOKEN_READ_SURFACE_ENABLED)("token_lookup", () => {
|
|
256
261
|
it("returns token with values", async () => {
|
|
257
262
|
const res = await client.callTool({
|
|
258
263
|
name: "token_lookup",
|
|
@@ -273,15 +278,16 @@ describe("token_lookup", () => {
|
|
|
273
278
|
// ---------------------------------------------------------------------------
|
|
274
279
|
|
|
275
280
|
describe("tier_list", () => {
|
|
276
|
-
it("returns tiers
|
|
281
|
+
it("returns the tiers (bundled pack)", async () => {
|
|
277
282
|
const res = await client.callTool({
|
|
278
283
|
name: "tier_list",
|
|
279
284
|
arguments: {},
|
|
280
285
|
});
|
|
281
286
|
const body = parseEnvelope(res);
|
|
282
287
|
expect(body.ok).toBe(true);
|
|
283
|
-
|
|
284
|
-
|
|
288
|
+
// Bundled tier pack: uniform `{uri, name}` rows (no bespoke hierarchy).
|
|
289
|
+
const data = body.data as { name: string }[];
|
|
290
|
+
expect(data.some((t) => t.name === "global")).toBe(true);
|
|
285
291
|
});
|
|
286
292
|
});
|
|
287
293
|
|
|
@@ -480,15 +486,34 @@ describe("disclosure", () => {
|
|
|
480
486
|
expect(meta.disclosure).toBe("digest");
|
|
481
487
|
});
|
|
482
488
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
489
|
+
// `standard list --detailed` was retired with the standard cutover (a
|
|
490
|
+
// pinned PARITY_GAP: pack lists are single-level); per-entity disclosure
|
|
491
|
+
// now lives on the lookup's `detail` parameter and its legacy aliases.
|
|
492
|
+
it("standard_lookup honors the detail parameter", async () => {
|
|
493
|
+
const summary = await client.callTool({
|
|
494
|
+
name: "standard_lookup",
|
|
495
|
+
arguments: {
|
|
496
|
+
names: ["react/component/folder-structure"],
|
|
497
|
+
detail: "summary",
|
|
498
|
+
},
|
|
487
499
|
});
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
expect(
|
|
500
|
+
const summaryData = parseEnvelope(summary).data as {
|
|
501
|
+
results: Record<string, unknown>[];
|
|
502
|
+
};
|
|
503
|
+
expect(summaryData.results[0]).not.toHaveProperty("dos");
|
|
504
|
+
|
|
505
|
+
const detailed = await client.callTool({
|
|
506
|
+
name: "standard_lookup",
|
|
507
|
+
arguments: {
|
|
508
|
+
names: ["react/component/folder-structure"],
|
|
509
|
+
detail: "detailed",
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
const detailedData = parseEnvelope(detailed).data as {
|
|
513
|
+
results: Record<string, unknown>[];
|
|
514
|
+
};
|
|
515
|
+
expect(detailedData.results[0]).toHaveProperty("dos");
|
|
516
|
+
expect(detailedData.results[0]).toHaveProperty("donts");
|
|
492
517
|
});
|
|
493
518
|
});
|
|
494
519
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
11
11
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
12
12
|
// ---- Shared utilities ----
|
|
13
|
+
import { readConfigLayers } from "#config";
|
|
13
14
|
import { VERSION } from "#constants";
|
|
14
15
|
import { detectInstallSource } from "#package-manager";
|
|
15
16
|
// ---- Formatters ----
|
|
@@ -41,20 +42,10 @@ import {
|
|
|
41
42
|
} from "../../domains/ontology/operations/index.js";
|
|
42
43
|
import { CHANNEL_RELEASES } from "../../domains/shared/filters/buildChannelFilter.js";
|
|
43
44
|
import { resolveTierChain } from "../../domains/shared/filters/buildTierFilter.js";
|
|
45
|
+
import { listTiers } from "../../domains/shared/listTiers.js";
|
|
44
46
|
import type { PragmaRuntime } from "../../domains/shared/runtime.js";
|
|
45
|
-
import {
|
|
46
|
-
|
|
47
|
-
categoriesFormatters as standardCatFmt,
|
|
48
|
-
listFormatters as standardListFmt,
|
|
49
|
-
lookupFormatters as standardLookupFmt,
|
|
50
|
-
} from "../../domains/standard/formatters/index.js";
|
|
51
|
-
import {
|
|
52
|
-
listCategories,
|
|
53
|
-
listStandards,
|
|
54
|
-
lookupStandard,
|
|
55
|
-
} from "../../domains/standard/operations/index.js";
|
|
56
|
-
import { listFormatters as tierListFmt } from "../../domains/tier/formatters/index.js";
|
|
57
|
-
import { listTiers } from "../../domains/tier/operations/index.js";
|
|
47
|
+
import { listDomainNames } from "../../domains/shared/suggestions/index.js";
|
|
48
|
+
import { TOKEN_READ_SURFACE_ENABLED } from "../../domains/token/featureFlag.js";
|
|
58
49
|
import {
|
|
59
50
|
createLookupFormatters as createTokenLookupFmt,
|
|
60
51
|
listFormatters as tokenListFmt,
|
|
@@ -175,58 +166,83 @@ describe("block parity", () => {
|
|
|
175
166
|
// Standard parity
|
|
176
167
|
// ---------------------------------------------------------------------------
|
|
177
168
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
169
|
+
// `standard *` is now served by the bundled `standard` story pack (the
|
|
170
|
+
// hand-written domain was deleted). Pack rows/entities are uniform
|
|
171
|
+
// `Record<string,string>` projections with expand arrays, and rendering is
|
|
172
|
+
// the generic pack renderer — so these tests assert *semantic* parity
|
|
173
|
+
// against the store (every standard reachable, by the same names, with the
|
|
174
|
+
// same category/description/dos/donts values) rather than byte equality
|
|
175
|
+
// with the removed bespoke formatters. See PARITY_GAPS in #testing for the
|
|
176
|
+
// pinned, accepted divergences.
|
|
177
|
+
describe("standard parity (bundled pack)", () => {
|
|
178
|
+
it("standard_list returns one {uri, name, category, description} row per standard", async () => {
|
|
179
|
+
const allNames = await listDomainNames(rt.store, "standard");
|
|
180
|
+
expect(allNames.length).toBeGreaterThan(0);
|
|
181
|
+
|
|
181
182
|
const mcpRes = await client.callTool({
|
|
182
183
|
name: "standard_list",
|
|
183
184
|
arguments: {},
|
|
184
185
|
});
|
|
185
|
-
|
|
186
|
+
const body = parseEnvelope(mcpRes);
|
|
187
|
+
expect(body.ok).toBe(true);
|
|
188
|
+
const rows = body.data as {
|
|
189
|
+
uri?: string;
|
|
190
|
+
name?: string;
|
|
191
|
+
category?: string;
|
|
192
|
+
description?: string;
|
|
193
|
+
}[];
|
|
194
|
+
|
|
195
|
+
// Same standards, same names — nothing dropped or invented.
|
|
196
|
+
const listed = new Set(rows.map((row) => row.name));
|
|
197
|
+
for (const name of allNames) {
|
|
198
|
+
expect(listed.has(name), `"${name}" missing from standard_list`).toBe(
|
|
199
|
+
true,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
for (const row of rows) {
|
|
203
|
+
expect(row.uri).toBeTruthy();
|
|
204
|
+
expect(row.description).toBeTruthy();
|
|
205
|
+
}
|
|
186
206
|
});
|
|
187
207
|
|
|
188
|
-
it("standard_list condensed
|
|
189
|
-
const
|
|
190
|
-
const output: StandardListOutput = {
|
|
191
|
-
items: opResult,
|
|
192
|
-
details: undefined,
|
|
193
|
-
disclosure: { level: "summary" },
|
|
194
|
-
};
|
|
195
|
-
const expectedText = standardListFmt.llm(output);
|
|
196
|
-
|
|
208
|
+
it("standard_list condensed lists every standard under the pack heading", async () => {
|
|
209
|
+
const allNames = await listDomainNames(rt.store, "standard");
|
|
197
210
|
const mcpRes = await client.callTool({
|
|
198
211
|
name: "standard_list",
|
|
199
212
|
arguments: { condensed: true },
|
|
200
213
|
});
|
|
201
214
|
const body = parseCondensed(mcpRes);
|
|
202
|
-
expect(body.text).
|
|
215
|
+
expect(body.text).toContain("## Standard");
|
|
216
|
+
for (const name of allNames) {
|
|
217
|
+
expect(body.text).toContain(name);
|
|
218
|
+
}
|
|
203
219
|
});
|
|
204
220
|
|
|
205
|
-
it("standard_lookup
|
|
206
|
-
const opResult = await lookupStandard(
|
|
207
|
-
rt.store,
|
|
208
|
-
"react/component/folder-structure",
|
|
209
|
-
);
|
|
221
|
+
it("standard_lookup returns full detail by default (MCP full-data contract)", async () => {
|
|
210
222
|
const mcpRes = await client.callTool({
|
|
211
223
|
name: "standard_lookup",
|
|
212
224
|
arguments: { names: ["react/component/folder-structure"] },
|
|
213
225
|
});
|
|
214
226
|
const body = parseEnvelope(mcpRes);
|
|
215
|
-
const data = body.data as {
|
|
216
|
-
|
|
227
|
+
const data = body.data as {
|
|
228
|
+
results: {
|
|
229
|
+
name: string;
|
|
230
|
+
category: string;
|
|
231
|
+
dos: { code?: string; language?: string }[];
|
|
232
|
+
donts: { code?: string }[];
|
|
233
|
+
}[];
|
|
234
|
+
errors: unknown[];
|
|
235
|
+
};
|
|
217
236
|
expect(data.errors).toEqual([]);
|
|
237
|
+
const entity = data.results[0];
|
|
238
|
+
expect(entity?.name).toBe("react/component/folder-structure");
|
|
239
|
+
expect(entity?.category).toBe("react");
|
|
240
|
+
expect(entity?.dos.length).toBeGreaterThan(0);
|
|
241
|
+
expect(entity?.dos.every((example) => example.code)).toBe(true);
|
|
242
|
+
expect(entity?.donts.length).toBeGreaterThan(0);
|
|
218
243
|
});
|
|
219
244
|
|
|
220
|
-
it("standard_lookup condensed
|
|
221
|
-
const opResult = await lookupStandard(
|
|
222
|
-
rt.store,
|
|
223
|
-
"react/component/folder-structure",
|
|
224
|
-
);
|
|
225
|
-
const expectedText = standardLookupFmt.llm({
|
|
226
|
-
standard: opResult,
|
|
227
|
-
detailed: true,
|
|
228
|
-
});
|
|
229
|
-
|
|
245
|
+
it("standard_lookup condensed renders the entity with its code examples", async () => {
|
|
230
246
|
const mcpRes = await client.callTool({
|
|
231
247
|
name: "standard_lookup",
|
|
232
248
|
arguments: {
|
|
@@ -235,28 +251,37 @@ describe("standard parity", () => {
|
|
|
235
251
|
},
|
|
236
252
|
});
|
|
237
253
|
const body = parseCondensed(mcpRes);
|
|
238
|
-
expect(body.text).
|
|
254
|
+
expect(body.text).toContain("## react/component/folder-structure");
|
|
255
|
+
expect(body.text).toContain("Do");
|
|
256
|
+
expect(body.text).toContain("src/lib/Button/Button.tsx");
|
|
239
257
|
});
|
|
240
258
|
|
|
241
|
-
it("standard_categories
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
name: "standard_categories",
|
|
259
|
+
it("standard_categories counts agree with the standard list", async () => {
|
|
260
|
+
const listRes = await client.callTool({
|
|
261
|
+
name: "standard_list",
|
|
245
262
|
arguments: {},
|
|
246
263
|
});
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
264
|
+
const rows = parseEnvelope(listRes).data as { category?: string }[];
|
|
265
|
+
const expected = new Map<string, number>();
|
|
266
|
+
for (const row of rows) {
|
|
267
|
+
if (row.category) {
|
|
268
|
+
expected.set(row.category, (expected.get(row.category) ?? 0) + 1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
253
271
|
|
|
254
272
|
const mcpRes = await client.callTool({
|
|
255
273
|
name: "standard_categories",
|
|
256
|
-
arguments: {
|
|
274
|
+
arguments: {},
|
|
257
275
|
});
|
|
258
|
-
const body =
|
|
259
|
-
expect(body.
|
|
276
|
+
const body = parseEnvelope(mcpRes);
|
|
277
|
+
expect(body.ok).toBe(true);
|
|
278
|
+
const categories = body.data as { name: string; count: string }[];
|
|
279
|
+
expect(categories.length).toBeGreaterThan(0);
|
|
280
|
+
for (const [category, count] of expected) {
|
|
281
|
+
const row = categories.find((entry) => entry.name === category);
|
|
282
|
+
expect(row, `category "${category}" missing`).toBeDefined();
|
|
283
|
+
expect(Number(row?.count)).toBe(count);
|
|
284
|
+
}
|
|
260
285
|
});
|
|
261
286
|
});
|
|
262
287
|
|
|
@@ -264,26 +289,51 @@ describe("standard parity", () => {
|
|
|
264
289
|
// Tier parity
|
|
265
290
|
// ---------------------------------------------------------------------------
|
|
266
291
|
|
|
267
|
-
|
|
268
|
-
|
|
292
|
+
// `tier list` / `tier_list` is now served by the bundled `tier` story pack
|
|
293
|
+
// (the hand-written domain was deleted). Pack rows are `Record<string,string>`
|
|
294
|
+
// projected from the SELECT, so the shape is intentionally uniform: `{uri,
|
|
295
|
+
// name}` with no always-zero `depth` field, and the llm renderer is the
|
|
296
|
+
// generic pack renderer. These tests assert *semantic* parity — every tier the
|
|
297
|
+
// shared operation sees is present, by the same names — rather than byte
|
|
298
|
+
// equality with the removed bespoke formatter.
|
|
299
|
+
describe("tier parity (bundled pack)", () => {
|
|
300
|
+
it("tier_list returns one {uri, name} row per ontology tier", async () => {
|
|
269
301
|
const opResult = await listTiers(rt.store);
|
|
270
|
-
const mcpRes = await client.callTool({
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
302
|
+
const mcpRes = await client.callTool({ name: "tier_list", arguments: {} });
|
|
303
|
+
|
|
304
|
+
const content = mcpRes.content as { type: string; text: string }[];
|
|
305
|
+
const envelope = JSON.parse(content[0].text) as {
|
|
306
|
+
ok: boolean;
|
|
307
|
+
data: Array<{ uri?: string; name?: string }>;
|
|
308
|
+
};
|
|
309
|
+
expect(envelope.ok).toBe(true);
|
|
310
|
+
|
|
311
|
+
// Same tiers, same names — no tier dropped or invented by the cutover.
|
|
312
|
+
// The shared op names the field `path`; the pack names it `name` (the
|
|
313
|
+
// honest `ds:name` mapping) — the values are identical.
|
|
314
|
+
expect(new Set(envelope.data.map((r) => r.name))).toEqual(
|
|
315
|
+
new Set(opResult.map((t) => t.path)),
|
|
316
|
+
);
|
|
317
|
+
// Uniform pack shape: uri + name, no bespoke `depth` field.
|
|
318
|
+
for (const row of envelope.data) {
|
|
319
|
+
expect(row.uri).toBeTruthy();
|
|
320
|
+
expect(row).not.toHaveProperty("depth");
|
|
321
|
+
}
|
|
275
322
|
});
|
|
276
323
|
|
|
277
|
-
it("tier_list condensed
|
|
324
|
+
it("tier_list condensed lists every tier under a markdown heading", async () => {
|
|
278
325
|
const opResult = await listTiers(rt.store);
|
|
279
|
-
const expectedText = tierListFmt.llm(opResult);
|
|
280
|
-
|
|
281
326
|
const mcpRes = await client.callTool({
|
|
282
327
|
name: "tier_list",
|
|
283
328
|
arguments: { condensed: true },
|
|
284
329
|
});
|
|
285
330
|
const body = parseCondensed(mcpRes);
|
|
286
|
-
|
|
331
|
+
|
|
332
|
+
// The generic pack llm renderer headings by the capitalized noun: `## Tier`.
|
|
333
|
+
expect(body.text).toContain("## Tier");
|
|
334
|
+
for (const tier of opResult) {
|
|
335
|
+
expect(body.text).toContain(tier.path);
|
|
336
|
+
}
|
|
287
337
|
});
|
|
288
338
|
});
|
|
289
339
|
|
|
@@ -341,7 +391,7 @@ describe("modifier parity", () => {
|
|
|
341
391
|
// Token parity
|
|
342
392
|
// ---------------------------------------------------------------------------
|
|
343
393
|
|
|
344
|
-
describe("token parity", () => {
|
|
394
|
+
describe.skipIf(!TOKEN_READ_SURFACE_ENABLED)("token parity", () => {
|
|
345
395
|
it("token_list: count matches", async () => {
|
|
346
396
|
const opResult = await listTokens(rt.store);
|
|
347
397
|
const mcpRes = await client.callTool({
|
|
@@ -440,14 +490,25 @@ describe("ontology parity", () => {
|
|
|
440
490
|
// ---------------------------------------------------------------------------
|
|
441
491
|
|
|
442
492
|
describe("config parity", () => {
|
|
443
|
-
|
|
493
|
+
// Both surfaces resolve from the filesystem via the shared config show
|
|
494
|
+
// story, so parity is asserted against the real config path/existence
|
|
495
|
+
// (the MCP tool previously hardcoded "pragma.config.json" / true).
|
|
496
|
+
function resolveExpectedConfigShow() {
|
|
497
|
+
const layers = readConfigLayers(rt.cwd);
|
|
444
498
|
const install = detectInstallSource();
|
|
445
|
-
|
|
499
|
+
return resolveConfigShow(layers.config, {
|
|
446
500
|
packageManager: install.packageManager,
|
|
447
501
|
installSource: install.label,
|
|
448
|
-
configFilePath:
|
|
449
|
-
configFileExists:
|
|
502
|
+
configFilePath: layers.project.path,
|
|
503
|
+
configFileExists: layers.project.exists,
|
|
504
|
+
globalConfigPath: layers.global.path,
|
|
505
|
+
globalConfigExists: layers.global.exists,
|
|
506
|
+
origins: layers.origins,
|
|
450
507
|
});
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
it("config_show: data matches resolveConfigShow", async () => {
|
|
511
|
+
const opResult = resolveExpectedConfigShow();
|
|
451
512
|
|
|
452
513
|
const mcpRes = await client.callTool({
|
|
453
514
|
name: "config_show",
|
|
@@ -458,14 +519,7 @@ describe("config parity", () => {
|
|
|
458
519
|
});
|
|
459
520
|
|
|
460
521
|
it("config_show condensed: matches llm formatter", async () => {
|
|
461
|
-
const
|
|
462
|
-
const opResult = resolveConfigShow(rt.config, {
|
|
463
|
-
packageManager: install.packageManager,
|
|
464
|
-
installSource: install.label,
|
|
465
|
-
configFilePath: "pragma.config.json",
|
|
466
|
-
configFileExists: true,
|
|
467
|
-
});
|
|
468
|
-
const expectedText = configShowFmt.llm(opResult);
|
|
522
|
+
const expectedText = configShowFmt.llm(resolveExpectedConfigShow());
|
|
469
523
|
|
|
470
524
|
const mcpRes = await client.callTool({
|
|
471
525
|
name: "config_show",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: skill discovery returned zero skills on real installs.
|
|
3
|
+
*
|
|
4
|
+
* `readPackageDir` emits one `SkillEntry.dir` per skill folder
|
|
5
|
+
* (`<package>/skills/<name>`), but `discoverSkills` treated each source
|
|
6
|
+
* directory as a *parent* of skill folders and scanned it for
|
|
7
|
+
* subdirectories containing SKILL.md. Production sources therefore never
|
|
8
|
+
* matched — `pragma skill list` errored with "No SKILL.md files found"
|
|
9
|
+
* and MCP `skill_list` returned an empty list, despite `doctor` counting
|
|
10
|
+
* skills in the very same packages. This test pins the granularity
|
|
11
|
+
* contract between the loader and discovery using both real
|
|
12
|
+
* implementations end-to-end.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { tmpdir } from "node:os";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
19
|
+
import readPackageDir from "../../domains/shared/loaders/readPackageDir.js";
|
|
20
|
+
import type { SemanticPackage } from "../../domains/shared/semanticPackage.js";
|
|
21
|
+
import { resolveSkillSources } from "../../domains/skill/helpers/index.js";
|
|
22
|
+
import discoverSkills from "../../domains/skill/operations/discover.js";
|
|
23
|
+
|
|
24
|
+
const TMP_ROOT = join(tmpdir(), `pragma-regression-0001-${Date.now()}`);
|
|
25
|
+
const PKG_DIR = join(TMP_ROOT, "node_modules/@canonical/design-system");
|
|
26
|
+
|
|
27
|
+
beforeAll(() => {
|
|
28
|
+
const skillDir = join(PKG_DIR, "skills/design-auditor");
|
|
29
|
+
mkdirSync(skillDir, { recursive: true });
|
|
30
|
+
writeFileSync(
|
|
31
|
+
join(PKG_DIR, "package.json"),
|
|
32
|
+
JSON.stringify({ name: "@canonical/design-system", version: "0.1.2" }),
|
|
33
|
+
);
|
|
34
|
+
writeFileSync(
|
|
35
|
+
join(skillDir, "SKILL.md"),
|
|
36
|
+
`---
|
|
37
|
+
name: design-auditor
|
|
38
|
+
description: Audit design system coverage, consistency, and quality
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Design Auditor
|
|
42
|
+
`,
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterAll(() => {
|
|
47
|
+
rmSync(TMP_ROOT, { recursive: true, force: true });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe("skill discovery granularity (loader -> discovery contract)", () => {
|
|
51
|
+
it("discovers skills from sources produced by readPackageDir", async () => {
|
|
52
|
+
const contents = readPackageDir(PKG_DIR);
|
|
53
|
+
expect(contents.skills).toHaveLength(1);
|
|
54
|
+
|
|
55
|
+
const pkg: SemanticPackage = {
|
|
56
|
+
name: "@canonical/design-system",
|
|
57
|
+
version: contents.version,
|
|
58
|
+
source: "local",
|
|
59
|
+
graphs: contents.graphs,
|
|
60
|
+
skills: contents.skills,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const sources = resolveSkillSources([pkg]);
|
|
64
|
+
const skills = await discoverSkills(TMP_ROOT, sources);
|
|
65
|
+
|
|
66
|
+
expect(skills).toHaveLength(1);
|
|
67
|
+
expect(skills.at(0)?.name).toBe("design-auditor");
|
|
68
|
+
expect(skills.at(0)?.folderName).toBe("design-auditor");
|
|
69
|
+
expect(skills.at(0)?.sourcePackage).toBe("@canonical/design-system");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global test setup: isolate the XDG config and data layers.
|
|
3
|
+
*
|
|
4
|
+
* The layered config reader consults `$XDG_CONFIG_HOME/pragma/config.json`
|
|
5
|
+
* on every read, and global-first writes create it; the schema artifact
|
|
6
|
+
* writes to `$XDG_DATA_HOME/pragma/schema.graphql`. Point both at
|
|
7
|
+
* per-run temp directories so tests neither observe nor pollute the
|
|
8
|
+
* developer's real global state. Individual tests that exercise XDG
|
|
9
|
+
* behavior override these values themselves.
|
|
10
|
+
*
|
|
11
|
+
* The boot-time schema artifact emission is disabled globally: it would
|
|
12
|
+
* add a full ke-graphql compile to every test that drives the real CLI
|
|
13
|
+
* pipeline and print an "Updated ..." notice on first boot. Its behavior
|
|
14
|
+
* is covered directly by ensureSchemaArtifact.test.ts; tests exercising
|
|
15
|
+
* the boot hook re-enable it explicitly.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { mkdtempSync } from "node:fs";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
|
|
22
|
+
process.env.XDG_CONFIG_HOME = mkdtempSync(join(tmpdir(), "pragma-test-xdg-"));
|
|
23
|
+
process.env.XDG_DATA_HOME = mkdtempSync(
|
|
24
|
+
join(tmpdir(), "pragma-test-xdg-data-"),
|
|
25
|
+
);
|
|
26
|
+
process.env.PRAGMA_SCHEMA_ARTIFACT = "off";
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard-noun cutover parity contract.
|
|
3
|
+
*
|
|
4
|
+
* The hand-written `standard` domain was deleted; the noun is served by
|
|
5
|
+
* the bundled pack-v1 definition (`pack/bundled/standardPack.ts`), and
|
|
6
|
+
* `standardParity.test.ts` asserts SEMANTIC parity against the real
|
|
7
|
+
* @canonical/code-standards graphs: same entities and values reachable,
|
|
8
|
+
* uniform pack row/entity shapes, generic renderers.
|
|
9
|
+
*
|
|
10
|
+
* {@link PARITY_GAPS} is the honest record of the differences that
|
|
11
|
+
* remain BY DESIGN after the cutover. Each entry names a concrete,
|
|
12
|
+
* accepted divergence from the deleted built-in — remove an entry only
|
|
13
|
+
* when the pack format gains the capability and the parity test asserts
|
|
14
|
+
* it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Accepted post-cutover divergences from the deleted built-in standard
|
|
19
|
+
* domain. These are doctrine (semantic parity, not byte parity) plus the
|
|
20
|
+
* capabilities pack v1 deliberately does not carry.
|
|
21
|
+
*/
|
|
22
|
+
export const PARITY_GAPS: readonly string[] = [
|
|
23
|
+
"list disclosure: pack lists are single-level — the old `standard list --digest/--detailed` row enrichment (extends/example/dos/donts merged into every row, disclosure meta on the MCP envelope) is gone; the same data is reachable per-entity via `standard lookup --detail digest|detailed` and `standard sample`",
|
|
24
|
+
"list empty guard: the old list raised EMPTY_RESULTS with an install-hint recovery when no standards load or a --category matched nothing; the pack format has no emptyError hook, so an empty or fully-filtered list renders zero rows successfully",
|
|
25
|
+
"lookup digest rendering: the old list digest truncated the first do-example to 120 chars; the pack `digest` level fetches the full `dos` expand instead (richer, not byte-equal)",
|
|
26
|
+
"lookup data compaction: the old domain compacted cs:extends in resolved data (JSON showed `cs:ComponentFolderStructure`); pack entities keep the raw IRI in JSON — plain/llm output still compacts at display time",
|
|
27
|
+
"lookup recovery copy: cross-domain hints (detectCrossDomain) and the curated `List available standards.` message are not authorable; pack misses carry ranked suggestions with the generic `List available standard entries.` copy",
|
|
28
|
+
'typed shapes: pack rows/entities are all-string records — category counts are strings, and dos/donts entries are `{caption?, language?, code?}` string records rather than typed CodeBlock objects (no `language: "typescript"` default, absent captions are omitted)',
|
|
29
|
+
"render templates: plain/llm output uses the generic pack renderers (aligned columns, `## Standard (n)` headings, `- key: value` collection entries), not the old bespoke standard templates",
|
|
30
|
+
"sample count flag: the pack sample takes a positional count (`standard sample 3`) instead of the old `--count 3` flag",
|
|
31
|
+
"lookup IRI display: plain/llm lookup output does not print the entity IRI (the pack renderer titles by name and projects no uri field); the IRI stays reachable via the list's IRI column, `--format json`, and the non-condensed MCP envelope",
|
|
32
|
+
"categories JSON shape: the old CategorySummary carried a numeric `standardCount`; pack category rows carry the key `count` with a string value (all-string pack rows, until pack v2 typed columns)",
|
|
33
|
+
"sample population: totalCount counts name-addressable standards (the set the sampler can actually resolve) rather than all list rows; the old op counted every list row but failed outright when it drew a standard without cs:name",
|
|
34
|
+
"ink renderers: the pack format declares no renderInk TUI views",
|
|
35
|
+
];
|
package/src/testing/store.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Test store bridge — createTestStore, PragmaTestStoreOptions.
|
|
3
3
|
*
|
|
4
4
|
* Wraps `@canonical/ke/testing` with pragma's default prefix map
|
|
5
|
-
* pre-configured so test authors do not need to repeat
|
|
5
|
+
* pre-configured so test authors do not need to repeat DEFAULT_PREFIX_MAP.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { TestStoreOptions, TestStoreResult } from "@canonical/ke/testing";
|
|
9
9
|
import { createTestStore as keCreateTestStore } from "@canonical/ke/testing";
|
|
10
|
-
import {
|
|
10
|
+
import { DEFAULT_PREFIX_MAP } from "../domains/shared/prefixes.js";
|
|
11
11
|
|
|
12
12
|
/** Options for creating a test store, with pragma prefixes pre-applied. */
|
|
13
13
|
interface PragmaTestStoreOptions extends Omit<TestStoreOptions, "prefixes"> {
|
|
@@ -18,7 +18,7 @@ interface PragmaTestStoreOptions extends Omit<TestStoreOptions, "prefixes"> {
|
|
|
18
18
|
* Create a test ke store with pragma's default prefix map.
|
|
19
19
|
*
|
|
20
20
|
* @param options - Optional overrides; additional prefixes are merged
|
|
21
|
-
* on top of the default
|
|
21
|
+
* on top of the default DEFAULT_PREFIX_MAP.
|
|
22
22
|
* @returns The test store result from ke/testing.
|
|
23
23
|
*
|
|
24
24
|
* @note Impure
|
|
@@ -29,7 +29,7 @@ async function createTestStore(
|
|
|
29
29
|
return keCreateTestStore({
|
|
30
30
|
...options,
|
|
31
31
|
prefixes: {
|
|
32
|
-
...
|
|
32
|
+
...DEFAULT_PREFIX_MAP,
|
|
33
33
|
...options.prefixes,
|
|
34
34
|
},
|
|
35
35
|
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story-pack test fixtures — a foreign (non-DS) recipe ontology plus a
|
|
3
|
+
* matching pack definition.
|
|
4
|
+
*
|
|
5
|
+
* The `ex:` namespace is deliberately outside PREFIX_MAP: tests register
|
|
6
|
+
* it via config `prefixes`, proving the DS-agnostic path end to end.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { StoryPackDefinition } from "../domains/shared/stories/pack/types.js";
|
|
10
|
+
|
|
11
|
+
/** Namespace of the foreign recipe ontology. */
|
|
12
|
+
export const RECIPE_NAMESPACE = "http://example.org/recipes/";
|
|
13
|
+
|
|
14
|
+
/** Prefix map entry tests merge into config `prefixes`. */
|
|
15
|
+
export const RECIPE_PREFIXES = { ex: RECIPE_NAMESPACE } as const;
|
|
16
|
+
|
|
17
|
+
/** A tiny foreign ontology with two recipe instances. */
|
|
18
|
+
export const RECIPE_TTL = `
|
|
19
|
+
@prefix ex: <${RECIPE_NAMESPACE}> .
|
|
20
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
21
|
+
|
|
22
|
+
ex:Recipe a rdfs:Class .
|
|
23
|
+
|
|
24
|
+
ex:pancakes a ex:Recipe ;
|
|
25
|
+
ex:name "Pancakes" ;
|
|
26
|
+
ex:category "breakfast" ;
|
|
27
|
+
ex:instructions "Mix, fry, flip." .
|
|
28
|
+
|
|
29
|
+
ex:gazpacho a ex:Recipe ;
|
|
30
|
+
ex:name "Gazpacho" ;
|
|
31
|
+
ex:category "soup" ;
|
|
32
|
+
ex:instructions "Blend everything cold." .
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
/** A valid pack definition for the recipe ontology. */
|
|
36
|
+
export const RECIPE_STORY: StoryPackDefinition = {
|
|
37
|
+
noun: "recipe",
|
|
38
|
+
description: "List recipes",
|
|
39
|
+
list: {
|
|
40
|
+
query:
|
|
41
|
+
"SELECT ?uri ?name ?category WHERE { ?uri a ex:Recipe ; ex:name ?name ; ex:category ?category } ORDER BY ?name",
|
|
42
|
+
columns: [
|
|
43
|
+
{ field: "name" },
|
|
44
|
+
{ field: "category" },
|
|
45
|
+
{ field: "uri", label: "IRI" },
|
|
46
|
+
],
|
|
47
|
+
filters: [
|
|
48
|
+
{
|
|
49
|
+
param: "category",
|
|
50
|
+
variable: "category",
|
|
51
|
+
values: ["breakfast", "soup"],
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
lookup: {
|
|
56
|
+
type: "ex:Recipe",
|
|
57
|
+
by: "ex:name",
|
|
58
|
+
fields: [{ name: "category", property: "ex:category" }],
|
|
59
|
+
sections: [
|
|
60
|
+
{ name: "instructions", property: "ex:instructions", kind: "field" },
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
};
|