@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
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP tool specs for the standard domain.
|
|
3
|
-
*
|
|
4
|
-
* Declarative definitions — no MCP imports. The adapter layer
|
|
5
|
-
* converts these into registered MCP tools via `registerFromSpec()`.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { ToolSpec } from "../../shared/ToolSpec.js";
|
|
9
|
-
import {
|
|
10
|
-
type StandardListOutput,
|
|
11
|
-
categoriesFormatters as standardCatFmt,
|
|
12
|
-
listFormatters as standardListFmt,
|
|
13
|
-
lookupFormatters as standardLookupFmt,
|
|
14
|
-
sampleFormatters as standardSampleFmt,
|
|
15
|
-
} from "../formatters/index.js";
|
|
16
|
-
import { listCategories, sampleStandards } from "../operations/index.js";
|
|
17
|
-
import {
|
|
18
|
-
resolveStandardList,
|
|
19
|
-
resolveStandardLookup,
|
|
20
|
-
} from "../orchestration/index.js";
|
|
21
|
-
|
|
22
|
-
const specs: readonly ToolSpec[] = [
|
|
23
|
-
{
|
|
24
|
-
name: "standard_list",
|
|
25
|
-
description:
|
|
26
|
-
"List code standards. Optionally filter by category or search term. Use digest/detailed for progressive disclosure.",
|
|
27
|
-
params: {
|
|
28
|
-
category: {
|
|
29
|
-
type: "string",
|
|
30
|
-
description: "Filter by category name",
|
|
31
|
-
optional: true,
|
|
32
|
-
},
|
|
33
|
-
search: {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Search in name and description",
|
|
36
|
-
optional: true,
|
|
37
|
-
},
|
|
38
|
-
digest: {
|
|
39
|
-
type: "boolean",
|
|
40
|
-
description: "Show description and first example for each standard",
|
|
41
|
-
optional: true,
|
|
42
|
-
},
|
|
43
|
-
detailed: {
|
|
44
|
-
type: "boolean",
|
|
45
|
-
description: "Show full dos/donts for each standard",
|
|
46
|
-
optional: true,
|
|
47
|
-
},
|
|
48
|
-
condensed: {
|
|
49
|
-
type: "boolean",
|
|
50
|
-
description: "Token-optimized output",
|
|
51
|
-
optional: true,
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
readOnly: true,
|
|
55
|
-
async execute(rt, { category, search, digest, detailed, condensed }) {
|
|
56
|
-
const resolution = await resolveStandardList(rt, {
|
|
57
|
-
category: category as string | undefined,
|
|
58
|
-
search: search as string | undefined,
|
|
59
|
-
digest: digest === true,
|
|
60
|
-
detailed: detailed === true,
|
|
61
|
-
});
|
|
62
|
-
const output: StandardListOutput = {
|
|
63
|
-
items: resolution.items,
|
|
64
|
-
details: resolution.details,
|
|
65
|
-
disclosure: resolution.disclosure,
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
if (condensed) {
|
|
69
|
-
const text = standardListFmt.llm(output);
|
|
70
|
-
return {
|
|
71
|
-
condensed: true,
|
|
72
|
-
text,
|
|
73
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (resolution.disclosure.level === "summary") {
|
|
78
|
-
return {
|
|
79
|
-
data: resolution.items,
|
|
80
|
-
meta: { count: resolution.items.length },
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
data: JSON.parse(standardListFmt.json(output)),
|
|
86
|
-
meta: {
|
|
87
|
-
count: resolution.items.length,
|
|
88
|
-
disclosure: resolution.disclosure.level,
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
{
|
|
95
|
-
name: "standard_lookup",
|
|
96
|
-
description:
|
|
97
|
-
"Get detailed information about one or more code standards including dos and donts with code examples.",
|
|
98
|
-
params: {
|
|
99
|
-
names: {
|
|
100
|
-
type: "string[]",
|
|
101
|
-
description: "Standard names or IRIs to look up",
|
|
102
|
-
optional: false,
|
|
103
|
-
},
|
|
104
|
-
detailed: {
|
|
105
|
-
type: "boolean",
|
|
106
|
-
description:
|
|
107
|
-
"Return full details with dos/donts (default: true for MCP)",
|
|
108
|
-
optional: true,
|
|
109
|
-
},
|
|
110
|
-
condensed: {
|
|
111
|
-
type: "boolean",
|
|
112
|
-
description: "Token-optimized output",
|
|
113
|
-
optional: true,
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
readOnly: true,
|
|
117
|
-
async execute(rt, { names, detailed, condensed }) {
|
|
118
|
-
const showDetailed = (detailed as boolean | undefined) ?? true;
|
|
119
|
-
const contract = await resolveStandardLookup(rt.store, names as string[]);
|
|
120
|
-
const result = contract.result;
|
|
121
|
-
|
|
122
|
-
if (condensed) {
|
|
123
|
-
const textParts = result.results.map((standard) =>
|
|
124
|
-
standardLookupFmt.llm({
|
|
125
|
-
standard,
|
|
126
|
-
detailed: showDetailed,
|
|
127
|
-
}),
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
if (result.errors.length > 0) {
|
|
131
|
-
textParts.push(
|
|
132
|
-
[
|
|
133
|
-
"### Errors",
|
|
134
|
-
...result.errors.map(
|
|
135
|
-
(error) => `- ${error.query}: ${error.message}`,
|
|
136
|
-
),
|
|
137
|
-
].join("\n"),
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const text = textParts.join("\n\n");
|
|
142
|
-
return {
|
|
143
|
-
condensed: true,
|
|
144
|
-
text,
|
|
145
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (!showDetailed) {
|
|
150
|
-
return {
|
|
151
|
-
data: {
|
|
152
|
-
results: result.results.map(
|
|
153
|
-
({ uri, name, category, description }) => ({
|
|
154
|
-
uri,
|
|
155
|
-
name,
|
|
156
|
-
category,
|
|
157
|
-
description,
|
|
158
|
-
}),
|
|
159
|
-
),
|
|
160
|
-
errors: result.errors,
|
|
161
|
-
},
|
|
162
|
-
meta: { count: result.results.length },
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return { data: result, meta: { count: result.results.length } };
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
|
|
170
|
-
{
|
|
171
|
-
name: "standard_categories",
|
|
172
|
-
description: "List all code standard categories.",
|
|
173
|
-
params: {
|
|
174
|
-
condensed: {
|
|
175
|
-
type: "boolean",
|
|
176
|
-
description: "Token-optimized output",
|
|
177
|
-
optional: true,
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
readOnly: true,
|
|
181
|
-
async execute(rt, { condensed }) {
|
|
182
|
-
const result = await listCategories(rt.store);
|
|
183
|
-
|
|
184
|
-
if (condensed) {
|
|
185
|
-
const text = standardCatFmt.llm(result);
|
|
186
|
-
return {
|
|
187
|
-
condensed: true,
|
|
188
|
-
text,
|
|
189
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return { data: result, meta: { count: result.length } };
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
{
|
|
198
|
-
name: "standard_sample",
|
|
199
|
-
description:
|
|
200
|
-
"Return 1–5 randomly selected complete code standard instances as exemplars. Use BEFORE writing queries to see actual data shapes, property names, and value formats. Each call returns different instances.",
|
|
201
|
-
params: {
|
|
202
|
-
count: {
|
|
203
|
-
type: "string",
|
|
204
|
-
description: "Number of samples (1–5, default 2)",
|
|
205
|
-
optional: true,
|
|
206
|
-
},
|
|
207
|
-
condensed: {
|
|
208
|
-
type: "boolean",
|
|
209
|
-
description: "Token-optimized output",
|
|
210
|
-
optional: true,
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
readOnly: true,
|
|
214
|
-
async execute(rt, { count, condensed }) {
|
|
215
|
-
const n = Number(count ?? 2);
|
|
216
|
-
const result = await sampleStandards(rt.store, n);
|
|
217
|
-
const nextSteps = [
|
|
218
|
-
`These are ${result.samples.length} of ${result.totalCount} total standards.`,
|
|
219
|
-
"Use standard_lookup to inspect specific standards by name.",
|
|
220
|
-
"Use standard_list with category param to filter by category.",
|
|
221
|
-
];
|
|
222
|
-
|
|
223
|
-
if (condensed) {
|
|
224
|
-
const text = standardSampleFmt.llm({ ...result, nextSteps });
|
|
225
|
-
return {
|
|
226
|
-
condensed: true,
|
|
227
|
-
text,
|
|
228
|
-
tokens: `~${Math.ceil(text.length / 4)}`,
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
data: {
|
|
234
|
-
samples: result.samples,
|
|
235
|
-
totalCount: result.totalCount,
|
|
236
|
-
nextSteps,
|
|
237
|
-
},
|
|
238
|
-
meta: { count: result.samples.length },
|
|
239
|
-
};
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
];
|
|
243
|
-
|
|
244
|
-
export default specs;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
4
|
-
import { PREFIX_MAP } from "../../shared/prefixes.js";
|
|
5
|
-
import listCategories from "./categories.js";
|
|
6
|
-
|
|
7
|
-
let store: Store;
|
|
8
|
-
let cleanup: () => void;
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
12
|
-
store = result.store;
|
|
13
|
-
cleanup = result.cleanup;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterAll(() => cleanup());
|
|
17
|
-
|
|
18
|
-
describe("listCategories", () => {
|
|
19
|
-
it("returns categories with standard counts", async () => {
|
|
20
|
-
const result = await listCategories(store);
|
|
21
|
-
expect(result.length).toBe(2);
|
|
22
|
-
|
|
23
|
-
const react = result.find((c) => c.name === "react");
|
|
24
|
-
expect(react?.standardCount).toBe(2);
|
|
25
|
-
|
|
26
|
-
const code = result.find((c) => c.name === "code");
|
|
27
|
-
expect(code?.standardCount).toBe(1);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("returns sorted by name", async () => {
|
|
31
|
-
const result = await listCategories(store);
|
|
32
|
-
const names = result.map((c) => c.name);
|
|
33
|
-
const sorted = [...names].sort();
|
|
34
|
-
expect(names).toEqual(sorted);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("includes categories with zero standards", async () => {
|
|
38
|
-
const ttlWithEmptyCategory = `
|
|
39
|
-
@prefix cs: <${PREFIX_MAP.cs}> .
|
|
40
|
-
cs:empty_cat a cs:Category ; cs:slug "empty" .
|
|
41
|
-
cs:filled_cat a cs:Category ; cs:slug "filled" .
|
|
42
|
-
cs:s1 a cs:CodeStandard ;
|
|
43
|
-
cs:name "filled/one" ;
|
|
44
|
-
cs:hasCategory cs:filled_cat ;
|
|
45
|
-
cs:description "A standard" .
|
|
46
|
-
`;
|
|
47
|
-
const { store: testStore, cleanup: testCleanup } = await createTestStore({
|
|
48
|
-
ttl: ttlWithEmptyCategory,
|
|
49
|
-
});
|
|
50
|
-
try {
|
|
51
|
-
const result = await listCategories(testStore);
|
|
52
|
-
const empty = result.find((c) => c.name === "empty");
|
|
53
|
-
expect(empty).toBeDefined();
|
|
54
|
-
expect(empty?.standardCount).toBe(0);
|
|
55
|
-
const filled = result.find((c) => c.name === "filled");
|
|
56
|
-
expect(filled?.standardCount).toBe(1);
|
|
57
|
-
} finally {
|
|
58
|
-
testCleanup();
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lists all standard categories with the number of standards in each.
|
|
3
|
-
*
|
|
4
|
-
* @param store - ke store to query
|
|
5
|
-
* @returns array of category summaries ordered by name, empty when none exist
|
|
6
|
-
* @note Queries ke store
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { Store } from "@canonical/ke";
|
|
10
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
11
|
-
import { P } from "../../shared/prefixes.js";
|
|
12
|
-
import type { CategorySummary } from "../../shared/types/index.js";
|
|
13
|
-
|
|
14
|
-
export default async function listCategories(
|
|
15
|
-
store: Store,
|
|
16
|
-
): Promise<CategorySummary[]> {
|
|
17
|
-
const result = await store.query(
|
|
18
|
-
buildQuery(`
|
|
19
|
-
SELECT ?categoryName (COUNT(?standard) AS ?count)
|
|
20
|
-
WHERE {
|
|
21
|
-
?cat a ${P.cs}Category ;
|
|
22
|
-
${P.cs}slug ?categoryName .
|
|
23
|
-
OPTIONAL {
|
|
24
|
-
?standard a ${P.cs}CodeStandard ;
|
|
25
|
-
${P.cs}hasCategory ?cat .
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
GROUP BY ?categoryName
|
|
29
|
-
ORDER BY ?categoryName
|
|
30
|
-
`),
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
if (result.type !== "select") return [];
|
|
34
|
-
return result.bindings.map((b) => ({
|
|
35
|
-
name: b.categoryName ?? "",
|
|
36
|
-
standardCount: Number.parseInt(b.count ?? "0", 10) || 0,
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/** @module Re-exports standard operations (`listCategories`, `listStandards`, `lookupStandard`, `sampleStandards`). */
|
|
2
|
-
|
|
3
|
-
export { default as listCategories } from "./categories.js";
|
|
4
|
-
export { default as listStandards } from "./list.js";
|
|
5
|
-
export { default as lookupStandard } from "./lookup.js";
|
|
6
|
-
export { default as sampleStandards } from "./sample.js";
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
4
|
-
import listStandards from "./list.js";
|
|
5
|
-
|
|
6
|
-
let store: Store;
|
|
7
|
-
let cleanup: () => void;
|
|
8
|
-
|
|
9
|
-
beforeAll(async () => {
|
|
10
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
11
|
-
store = result.store;
|
|
12
|
-
cleanup = result.cleanup;
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
afterAll(() => cleanup());
|
|
16
|
-
|
|
17
|
-
describe("listStandards", () => {
|
|
18
|
-
it("returns all standards", async () => {
|
|
19
|
-
const result = await listStandards(store);
|
|
20
|
-
expect(result.length).toBe(3);
|
|
21
|
-
const names = result.map((s) => s.name);
|
|
22
|
-
expect(names).toContain("react/component/folder-structure");
|
|
23
|
-
expect(names).toContain("react/component/props");
|
|
24
|
-
expect(names).toContain("code/function/purity");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("includes category names", async () => {
|
|
28
|
-
const result = await listStandards(store);
|
|
29
|
-
const folder = result.find(
|
|
30
|
-
(s) => s.name === "react/component/folder-structure",
|
|
31
|
-
);
|
|
32
|
-
expect(folder?.category).toBe("react");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("returns sorted by name", async () => {
|
|
36
|
-
const result = await listStandards(store);
|
|
37
|
-
const names = result.map((s) => s.name);
|
|
38
|
-
const sorted = [...names].sort();
|
|
39
|
-
expect(names).toEqual(sorted);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("filters by category", async () => {
|
|
43
|
-
const result = await listStandards(store, { category: "react" });
|
|
44
|
-
expect(result.length).toBe(2);
|
|
45
|
-
for (const s of result) {
|
|
46
|
-
expect(s.category).toBe("react");
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("filters by search term in name", async () => {
|
|
51
|
-
const result = await listStandards(store, { search: "folder" });
|
|
52
|
-
expect(result.length).toBe(1);
|
|
53
|
-
expect(result[0]?.name).toBe("react/component/folder-structure");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("filters by search term in description", async () => {
|
|
57
|
-
const result = await listStandards(store, { search: "pure" });
|
|
58
|
-
expect(result.length).toBe(1);
|
|
59
|
-
expect(result[0]?.name).toBe("code/function/purity");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("returns empty for non-matching category", async () => {
|
|
63
|
-
const result = await listStandards(store, { category: "nonexistent" });
|
|
64
|
-
expect(result.length).toBe(0);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("combines category and search filters", async () => {
|
|
68
|
-
const result = await listStandards(store, {
|
|
69
|
-
category: "react",
|
|
70
|
-
search: "props",
|
|
71
|
-
});
|
|
72
|
-
expect(result.length).toBe(1);
|
|
73
|
-
expect(result[0]?.name).toBe("react/component/props");
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lists all code standards, optionally filtered by category or search term.
|
|
3
|
-
*
|
|
4
|
-
* @param store - ke store to query
|
|
5
|
-
* @param filters - optional category and/or search text filters
|
|
6
|
-
* @returns array of standard summaries ordered by name, empty when none match
|
|
7
|
-
* @note Queries ke store
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { Store, URI } from "@canonical/ke";
|
|
11
|
-
import { escapeSparqlValue } from "@canonical/ke";
|
|
12
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
13
|
-
import { P } from "../../shared/prefixes.js";
|
|
14
|
-
import type {
|
|
15
|
-
StandardListFilters,
|
|
16
|
-
StandardSummary,
|
|
17
|
-
} from "../../shared/types/index.js";
|
|
18
|
-
|
|
19
|
-
export default async function listStandards(
|
|
20
|
-
store: Store,
|
|
21
|
-
filters?: StandardListFilters,
|
|
22
|
-
): Promise<StandardSummary[]> {
|
|
23
|
-
const filterClauses: string[] = [];
|
|
24
|
-
|
|
25
|
-
if (filters?.category) {
|
|
26
|
-
const escaped = escapeSparqlValue(filters.category.toLowerCase());
|
|
27
|
-
filterClauses.push(
|
|
28
|
-
`?standard ${P.cs}hasCategory ?filterCat . ?filterCat ${P.cs}slug ?catSlug . FILTER(?catSlug = ${escaped})`,
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (filters?.search) {
|
|
33
|
-
const escaped = escapeSparqlValue(filters.search.toLowerCase());
|
|
34
|
-
filterClauses.push(
|
|
35
|
-
`FILTER(CONTAINS(LCASE(?name), ${escaped}) || CONTAINS(LCASE(?description), ${escaped}))`,
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const result = await store.query(
|
|
40
|
-
buildQuery(`
|
|
41
|
-
SELECT ?standard ?name ?categoryName ?description
|
|
42
|
-
WHERE {
|
|
43
|
-
?standard a ${P.cs}CodeStandard ;
|
|
44
|
-
${P.cs}name ?name ;
|
|
45
|
-
${P.cs}description ?description .
|
|
46
|
-
OPTIONAL {
|
|
47
|
-
?standard ${P.cs}hasCategory ?cat .
|
|
48
|
-
?cat ${P.cs}slug ?categoryName .
|
|
49
|
-
}
|
|
50
|
-
${filterClauses.join("\n ")}
|
|
51
|
-
}
|
|
52
|
-
ORDER BY ?name
|
|
53
|
-
`),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
if (result.type !== "select") return [];
|
|
57
|
-
|
|
58
|
-
return result.bindings.map((b) => ({
|
|
59
|
-
uri: (b.standard ?? "") as URI,
|
|
60
|
-
name: b.name ?? "",
|
|
61
|
-
category: b.categoryName ?? "",
|
|
62
|
-
description: b.description ?? "",
|
|
63
|
-
}));
|
|
64
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { Store } from "@canonical/ke";
|
|
2
|
-
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { PragmaError } from "#error";
|
|
4
|
-
import { createTestStore, DS_ALL_TTL } from "#testing";
|
|
5
|
-
import lookupStandard from "./lookup.js";
|
|
6
|
-
|
|
7
|
-
let store: Store;
|
|
8
|
-
let cleanup: () => void;
|
|
9
|
-
|
|
10
|
-
beforeAll(async () => {
|
|
11
|
-
const result = await createTestStore({ ttl: DS_ALL_TTL });
|
|
12
|
-
store = result.store;
|
|
13
|
-
cleanup = result.cleanup;
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterAll(() => cleanup());
|
|
17
|
-
|
|
18
|
-
describe("lookupStandard", () => {
|
|
19
|
-
it("returns detailed data with dos and donts", async () => {
|
|
20
|
-
const result = await lookupStandard(
|
|
21
|
-
store,
|
|
22
|
-
"react/component/folder-structure",
|
|
23
|
-
);
|
|
24
|
-
expect(result.name).toBe("react/component/folder-structure");
|
|
25
|
-
expect(result.category).toBe("react");
|
|
26
|
-
expect(result.dos.length).toBeGreaterThan(0);
|
|
27
|
-
expect(result.donts.length).toBeGreaterThan(0);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("throws PragmaError.notFound for unknown standard", async () => {
|
|
31
|
-
await expect(lookupStandard(store, "nonexistent")).rejects.toThrow(
|
|
32
|
-
PragmaError,
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await lookupStandard(store, "nonexistent");
|
|
37
|
-
} catch (e) {
|
|
38
|
-
expect((e as PragmaError).code).toBe("ENTITY_NOT_FOUND");
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("resolves prefixed IRIs and compacts extends", async () => {
|
|
43
|
-
const result = await lookupStandard(store, "cs:react_props");
|
|
44
|
-
expect(result.name).toBe("react/component/props");
|
|
45
|
-
expect(result.extends).toBe("cs:react_folder");
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it("resolves full IRIs", async () => {
|
|
49
|
-
const result = await lookupStandard(
|
|
50
|
-
store,
|
|
51
|
-
"http://pragma.canonical.com/codestandards#react_props",
|
|
52
|
-
);
|
|
53
|
-
expect(result.name).toBe("react/component/props");
|
|
54
|
-
expect(result.uri).toBe(
|
|
55
|
-
"http://pragma.canonical.com/codestandards#react_props",
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Look up detailed information for a single code standard by name.
|
|
3
|
-
*
|
|
4
|
-
* Queries the base standard data plus its dos and donts code blocks,
|
|
5
|
-
* then assembles a {@link StandardDetailed} object.
|
|
6
|
-
*
|
|
7
|
-
* @param store - ke store to query
|
|
8
|
-
* @param name - standard name (e.g. "react/component/folder-structure")
|
|
9
|
-
* @returns full standard detail including dos/donts code blocks
|
|
10
|
-
* @throws PragmaError.notFound if the standard does not exist
|
|
11
|
-
* @note Queries ke store
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import type { Store, URI } from "@canonical/ke";
|
|
15
|
-
import { escapeSparqlValue } from "@canonical/ke";
|
|
16
|
-
import { PragmaError } from "#error";
|
|
17
|
-
import resolveUri from "../../graph/helpers/resolveUri.js";
|
|
18
|
-
import { buildQuery } from "../../shared/buildQuery.js";
|
|
19
|
-
import compactUri from "../../shared/compactUri.js";
|
|
20
|
-
import { P } from "../../shared/prefixes.js";
|
|
21
|
-
import {
|
|
22
|
-
detectCrossDomain,
|
|
23
|
-
listDomainNames,
|
|
24
|
-
suggestNames,
|
|
25
|
-
} from "../../shared/suggestions/index.js";
|
|
26
|
-
import type { CodeBlock, StandardDetailed } from "../../shared/types/index.js";
|
|
27
|
-
|
|
28
|
-
export default async function lookupStandard(
|
|
29
|
-
store: Store,
|
|
30
|
-
nameOrUri: string,
|
|
31
|
-
): Promise<StandardDetailed> {
|
|
32
|
-
const subjectClause = buildLookupSubjectClause(nameOrUri, store.prefixes);
|
|
33
|
-
const bindClause =
|
|
34
|
-
subjectClause === null ? "" : `BIND(${subjectClause} AS ?standard)`;
|
|
35
|
-
const matchClause =
|
|
36
|
-
subjectClause === null
|
|
37
|
-
? `?standard ${P.cs}name ${escapeSparqlValue(nameOrUri)} .`
|
|
38
|
-
: "";
|
|
39
|
-
|
|
40
|
-
const baseResult = await store.query(
|
|
41
|
-
buildQuery(`
|
|
42
|
-
SELECT ?standard ?name ?categoryName ?description ?extends
|
|
43
|
-
WHERE {
|
|
44
|
-
${bindClause}
|
|
45
|
-
?standard a ${P.cs}CodeStandard ;
|
|
46
|
-
${P.cs}name ?name ;
|
|
47
|
-
${P.cs}description ?description .
|
|
48
|
-
${matchClause}
|
|
49
|
-
OPTIONAL {
|
|
50
|
-
?standard ${P.cs}hasCategory ?cat .
|
|
51
|
-
?cat ${P.cs}slug ?categoryName .
|
|
52
|
-
}
|
|
53
|
-
OPTIONAL { ?standard ${P.cs}extends ?extends }
|
|
54
|
-
}
|
|
55
|
-
LIMIT 1
|
|
56
|
-
`),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
if (baseResult.type !== "select" || baseResult.bindings.length === 0) {
|
|
60
|
-
const candidates = await listDomainNames(store, "standard");
|
|
61
|
-
const crossDomain = await detectCrossDomain(nameOrUri, "standard", store);
|
|
62
|
-
throw PragmaError.notFound("standard", nameOrUri, {
|
|
63
|
-
suggestions: suggestNames(nameOrUri, candidates),
|
|
64
|
-
recovery: {
|
|
65
|
-
message: "List available standards.",
|
|
66
|
-
cli: "pragma standard list",
|
|
67
|
-
mcp: { tool: "standard_list" },
|
|
68
|
-
},
|
|
69
|
-
crossDomain: crossDomain ?? undefined,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Safe: length check above guarantees bindings[0] exists
|
|
74
|
-
const base = baseResult.bindings[0] as (typeof baseResult.bindings)[number];
|
|
75
|
-
const standardUri = base.standard;
|
|
76
|
-
|
|
77
|
-
// Fetch dos (cs:do → cs:Example with cs:description, cs:language, cs:code)
|
|
78
|
-
const dosResult = await store.query(
|
|
79
|
-
buildQuery(`
|
|
80
|
-
SELECT ?description ?language ?code
|
|
81
|
-
WHERE {
|
|
82
|
-
<${standardUri}> ${P.cs}do ?example .
|
|
83
|
-
OPTIONAL { ?example ${P.cs}description ?description }
|
|
84
|
-
OPTIONAL { ?example ${P.cs}language ?language }
|
|
85
|
-
OPTIONAL { ?example ${P.cs}code ?code }
|
|
86
|
-
}
|
|
87
|
-
`),
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const dos: CodeBlock[] =
|
|
91
|
-
dosResult.type === "select"
|
|
92
|
-
? dosResult.bindings.map((b) => ({
|
|
93
|
-
language: b.language ?? "typescript",
|
|
94
|
-
code: b.code ?? "",
|
|
95
|
-
caption: b.description,
|
|
96
|
-
}))
|
|
97
|
-
: [];
|
|
98
|
-
|
|
99
|
-
// Fetch donts (cs:dont → cs:Example with cs:description, cs:language, cs:code)
|
|
100
|
-
const dontsResult = await store.query(
|
|
101
|
-
buildQuery(`
|
|
102
|
-
SELECT ?description ?language ?code
|
|
103
|
-
WHERE {
|
|
104
|
-
<${standardUri}> ${P.cs}dont ?example .
|
|
105
|
-
OPTIONAL { ?example ${P.cs}description ?description }
|
|
106
|
-
OPTIONAL { ?example ${P.cs}language ?language }
|
|
107
|
-
OPTIONAL { ?example ${P.cs}code ?code }
|
|
108
|
-
}
|
|
109
|
-
`),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const donts: CodeBlock[] =
|
|
113
|
-
dontsResult.type === "select"
|
|
114
|
-
? dontsResult.bindings.map((b) => ({
|
|
115
|
-
language: b.language ?? "typescript",
|
|
116
|
-
code: b.code ?? "",
|
|
117
|
-
caption: b.description,
|
|
118
|
-
}))
|
|
119
|
-
: [];
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
uri: (standardUri ?? "") as URI,
|
|
123
|
-
name: base.name ?? nameOrUri,
|
|
124
|
-
category: base.categoryName ?? "",
|
|
125
|
-
description: base.description ?? "",
|
|
126
|
-
extends: base.extends
|
|
127
|
-
? compactUri(base.extends, store.prefixes)
|
|
128
|
-
: undefined,
|
|
129
|
-
dos,
|
|
130
|
-
donts,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function buildLookupSubjectClause(
|
|
135
|
-
query: string,
|
|
136
|
-
prefixes: Readonly<Record<string, string>>,
|
|
137
|
-
): string | null {
|
|
138
|
-
if (!looksLikeUri(query)) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return `<${resolveUri(query, prefixes)}>`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function looksLikeUri(query: string): boolean {
|
|
146
|
-
return (
|
|
147
|
-
query.startsWith("http://") ||
|
|
148
|
-
query.startsWith("https://") ||
|
|
149
|
-
query.includes(":")
|
|
150
|
-
);
|
|
151
|
-
}
|