@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,7 +1,13 @@
|
|
|
1
1
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
2
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
3
|
-
import { createTestMcpClient } from "#testing";
|
|
4
|
-
import { P } from "../domains/shared/prefixes.js";
|
|
3
|
+
import { createTestMcpClient, createTestStore } from "#testing";
|
|
4
|
+
import { DEFAULT_PREFIX_MAP, P } from "../domains/shared/prefixes.js";
|
|
5
|
+
import type { PragmaRuntime } from "../domains/shared/runtime.js";
|
|
6
|
+
import createClientFromRuntime from "../testing/helpers/createTestMcpClient.js";
|
|
7
|
+
import {
|
|
8
|
+
ABOX_PER_CLASS_LIMIT,
|
|
9
|
+
COMPLETION_LIMIT,
|
|
10
|
+
} from "./resources/constants.js";
|
|
5
11
|
|
|
6
12
|
let client: Client;
|
|
7
13
|
let cleanup: () => Promise<void>;
|
|
@@ -22,64 +28,183 @@ interface ResourceContent {
|
|
|
22
28
|
text: string;
|
|
23
29
|
}
|
|
24
30
|
|
|
31
|
+
interface ListedMeta {
|
|
32
|
+
"pragma/box"?: string;
|
|
33
|
+
"pragma/category"?: string;
|
|
34
|
+
"pragma/type"?: string | null;
|
|
35
|
+
"pragma/instanceCount"?: number;
|
|
36
|
+
"pragma/instancesShown"?: number;
|
|
37
|
+
"pragma/truncated"?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
function parseContents(result: { contents: unknown[] }): unknown {
|
|
26
|
-
const first = result.contents
|
|
41
|
+
const first = result.contents.at(0) as ResourceContent;
|
|
27
42
|
return JSON.parse(first.text);
|
|
28
43
|
}
|
|
29
44
|
|
|
45
|
+
function metaOf(resource: { _meta?: unknown }): ListedMeta {
|
|
46
|
+
return (resource._meta ?? {}) as ListedMeta;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Build an MCP client over a store with the given TTL and extra prefixes.
|
|
51
|
+
* Lets foreign/overlapping namespaces be registered, which the shared
|
|
52
|
+
* `createTestMcpClient` (fixed prefix set) cannot express.
|
|
53
|
+
*/
|
|
54
|
+
async function createClientForTtl(
|
|
55
|
+
ttl: string,
|
|
56
|
+
prefixes?: Record<string, string>,
|
|
57
|
+
): Promise<{ client: Client; cleanup: () => Promise<void> }> {
|
|
58
|
+
const { store, cleanup: closeStore } = await createTestStore({
|
|
59
|
+
ttl,
|
|
60
|
+
prefixes,
|
|
61
|
+
});
|
|
62
|
+
const runtime: PragmaRuntime = {
|
|
63
|
+
store,
|
|
64
|
+
config: { tier: undefined, channel: "normal" },
|
|
65
|
+
cwd: process.cwd(),
|
|
66
|
+
packages: [],
|
|
67
|
+
dispose: () => closeStore(),
|
|
68
|
+
};
|
|
69
|
+
const { client: scopedClient, cleanup: closeClient } =
|
|
70
|
+
await createClientFromRuntime(runtime);
|
|
71
|
+
return {
|
|
72
|
+
client: scopedClient,
|
|
73
|
+
cleanup: async () => {
|
|
74
|
+
await closeClient();
|
|
75
|
+
runtime.dispose();
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
30
80
|
// =============================================================================
|
|
31
|
-
// Resource
|
|
81
|
+
// Resource template
|
|
32
82
|
// =============================================================================
|
|
33
83
|
|
|
34
|
-
describe("resource
|
|
35
|
-
it("registers 1 resource template", async () => {
|
|
84
|
+
describe("resource template", () => {
|
|
85
|
+
it("registers 1 resource template with the {+uri} pattern", async () => {
|
|
36
86
|
const { resourceTemplates } = await client.listResourceTemplates();
|
|
37
87
|
expect(resourceTemplates).toHaveLength(1);
|
|
38
|
-
expect(resourceTemplates
|
|
88
|
+
expect(resourceTemplates.at(0)?.uriTemplate).toBe("{+uri}");
|
|
39
89
|
});
|
|
40
90
|
|
|
41
|
-
it("
|
|
91
|
+
it("documents the TBox/ABox split in the template description", async () => {
|
|
92
|
+
const { resourceTemplates } = await client.listResourceTemplates();
|
|
93
|
+
expect(resourceTemplates.at(0)?.description).toMatch(/TBox/);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// =============================================================================
|
|
98
|
+
// Resource listing — presence
|
|
99
|
+
// =============================================================================
|
|
100
|
+
|
|
101
|
+
describe("resource listing — presence", () => {
|
|
102
|
+
it("lists known instances, OWL classes, and code standards", async () => {
|
|
42
103
|
const { resources } = await client.listResources();
|
|
43
104
|
const uris = resources.map((r) => r.uri);
|
|
44
105
|
expect(uris).toContain(`${P.ds}global.component.button`);
|
|
45
|
-
expect(uris).toContain(`${P.ds}global.component.card`);
|
|
46
106
|
expect(uris).toContain(`${P.ds}global`);
|
|
107
|
+
expect(uris).toContain(`${P.ds}UIBlock`);
|
|
108
|
+
expect(uris).toContain(`${P.ds}Component`);
|
|
109
|
+
expect(uris).toContain(`${P.cs}react_folder`);
|
|
110
|
+
expect(uris).toContain(`${P.cs}code_purity`);
|
|
47
111
|
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// =============================================================================
|
|
115
|
+
// Resource listing — TBox/ABox separation
|
|
116
|
+
// =============================================================================
|
|
48
117
|
|
|
49
|
-
|
|
118
|
+
describe("resource listing — TBox/ABox separation", () => {
|
|
119
|
+
it("tags classes as tbox/class in _meta", async () => {
|
|
50
120
|
const { resources } = await client.listResources();
|
|
51
|
-
const
|
|
52
|
-
expect(
|
|
53
|
-
expect(
|
|
121
|
+
const uiBlock = resources.find((r) => r.uri === `${P.ds}UIBlock`);
|
|
122
|
+
expect(metaOf(uiBlock ?? {})["pragma/box"]).toBe("tbox");
|
|
123
|
+
expect(metaOf(uiBlock ?? {})["pragma/category"]).toBe("class");
|
|
54
124
|
});
|
|
55
125
|
|
|
56
|
-
it("
|
|
126
|
+
it("tags properties as tbox/property in _meta", async () => {
|
|
57
127
|
const { resources } = await client.listResources();
|
|
58
|
-
const
|
|
59
|
-
expect(
|
|
60
|
-
expect(
|
|
128
|
+
const tier = resources.find((r) => r.uri === `${P.ds}tier`);
|
|
129
|
+
expect(metaOf(tier ?? {})["pragma/box"]).toBe("tbox");
|
|
130
|
+
expect(metaOf(tier ?? {})["pragma/category"]).toBe("property");
|
|
61
131
|
});
|
|
62
132
|
|
|
63
|
-
it("
|
|
133
|
+
it("tags individuals as abox/individual with their class in _meta", async () => {
|
|
64
134
|
const { resources } = await client.listResources();
|
|
65
135
|
const button = resources.find(
|
|
66
136
|
(r) => r.uri === `${P.ds}global.component.button`,
|
|
67
137
|
);
|
|
68
|
-
expect(button
|
|
138
|
+
expect(metaOf(button ?? {})["pragma/box"]).toBe("abox");
|
|
139
|
+
expect(metaOf(button ?? {})["pragma/category"]).toBe("individual");
|
|
140
|
+
expect(metaOf(button ?? {})["pragma/type"]).toBe(`${P.ds}Component`);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("places all TBox schema before any ABox individual", async () => {
|
|
144
|
+
const { resources } = await client.listResources();
|
|
145
|
+
const firstAbox = resources.findIndex(
|
|
146
|
+
(r) => metaOf(r)["pragma/box"] === "abox",
|
|
147
|
+
);
|
|
148
|
+
const lastTbox = resources.reduce(
|
|
149
|
+
(acc, r, i) => (metaOf(r)["pragma/box"] === "tbox" ? i : acc),
|
|
150
|
+
-1,
|
|
151
|
+
);
|
|
152
|
+
expect(firstAbox).toBeGreaterThan(-1);
|
|
153
|
+
expect(lastTbox).toBeGreaterThan(-1);
|
|
154
|
+
expect(lastTbox).toBeLessThan(firstAbox);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("ranks schema above individuals via annotation priority", async () => {
|
|
158
|
+
const { resources } = await client.listResources();
|
|
159
|
+
const cls = resources.find((r) => r.uri === `${P.ds}Component`);
|
|
160
|
+
const individual = resources.find(
|
|
161
|
+
(r) => r.uri === `${P.ds}global.component.button`,
|
|
162
|
+
);
|
|
163
|
+
const clsPriority = cls?.annotations?.priority ?? 0;
|
|
164
|
+
const individualPriority = individual?.annotations?.priority ?? 1;
|
|
165
|
+
expect(clsPriority).toBeGreaterThan(individualPriority);
|
|
69
166
|
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// =============================================================================
|
|
170
|
+
// Resource listing — names, descriptions, grouping
|
|
171
|
+
// =============================================================================
|
|
70
172
|
|
|
71
|
-
|
|
173
|
+
describe("resource listing — names and grouping", () => {
|
|
174
|
+
it("prefixes class names with their category", async () => {
|
|
175
|
+
const { resources } = await client.listResources();
|
|
176
|
+
const cls = resources.find((r) => r.uri === `${P.ds}Component`);
|
|
177
|
+
expect(cls?.name).toBe("Class · Component");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("prefixes property names with their category", async () => {
|
|
181
|
+
const { resources } = await client.listResources();
|
|
182
|
+
const prop = resources.find((r) => r.uri === `${P.ds}tier`);
|
|
183
|
+
expect(prop?.name).toBe("Property · tier");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("groups individuals under their class label in the name", async () => {
|
|
72
187
|
const { resources } = await client.listResources();
|
|
73
188
|
const button = resources.find(
|
|
74
189
|
(r) => r.uri === `${P.ds}global.component.button`,
|
|
75
190
|
);
|
|
76
|
-
expect(button?.
|
|
191
|
+
expect(button?.name).toBe("Component · Button");
|
|
77
192
|
});
|
|
78
193
|
|
|
79
|
-
it("
|
|
194
|
+
it("surfaces instance counts on class entries", async () => {
|
|
80
195
|
const { resources } = await client.listResources();
|
|
81
|
-
const
|
|
82
|
-
expect(
|
|
196
|
+
const cls = resources.find((r) => r.uri === `${P.ds}Component`);
|
|
197
|
+
expect(metaOf(cls ?? {})["pragma/instanceCount"]).toBe(4);
|
|
198
|
+
expect(metaOf(cls ?? {})["pragma/truncated"]).toBe(false);
|
|
199
|
+
expect(cls?.description).toMatch(/4 individuals/);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it("leads an individual description with its class label", async () => {
|
|
203
|
+
const { resources } = await client.listResources();
|
|
204
|
+
const button = resources.find(
|
|
205
|
+
(r) => r.uri === `${P.ds}global.component.button`,
|
|
206
|
+
);
|
|
207
|
+
expect(button?.description).toMatch(/^Component/);
|
|
83
208
|
});
|
|
84
209
|
|
|
85
210
|
it("marks resources with assistant audience", async () => {
|
|
@@ -92,24 +217,197 @@ describe("resource listing", () => {
|
|
|
92
217
|
});
|
|
93
218
|
|
|
94
219
|
// =============================================================================
|
|
95
|
-
//
|
|
220
|
+
// Resource listing — capping the ABox long tail
|
|
221
|
+
// =============================================================================
|
|
222
|
+
|
|
223
|
+
describe("resource listing — capping", () => {
|
|
224
|
+
it("caps individuals per class and reports the remainder", async () => {
|
|
225
|
+
const overflow = ABOX_PER_CLASS_LIMIT + 5;
|
|
226
|
+
const individuals = Array.from(
|
|
227
|
+
{ length: overflow },
|
|
228
|
+
(_, i) => `ds:widget_${i} a ds:Gadget ; ds:name "Widget ${i}" .`,
|
|
229
|
+
).join("\n");
|
|
230
|
+
const ttl = `@prefix ds: <${DEFAULT_PREFIX_MAP.ds}> .
|
|
231
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
232
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
233
|
+
|
|
234
|
+
ds:Gadget a owl:Class ; rdfs:label "Gadget" .
|
|
235
|
+
ds:name a owl:DatatypeProperty .
|
|
236
|
+
|
|
237
|
+
${individuals}
|
|
238
|
+
`;
|
|
239
|
+
const scoped = await createClientForTtl(ttl);
|
|
240
|
+
try {
|
|
241
|
+
const { resources } = await scoped.client.listResources();
|
|
242
|
+
const shown = resources.filter(
|
|
243
|
+
(r) => metaOf(r)["pragma/type"] === `${P.ds}Gadget`,
|
|
244
|
+
);
|
|
245
|
+
expect(shown).toHaveLength(ABOX_PER_CLASS_LIMIT);
|
|
246
|
+
|
|
247
|
+
const cls = resources.find((r) => r.uri === `${P.ds}Gadget`);
|
|
248
|
+
expect(metaOf(cls ?? {})["pragma/instanceCount"]).toBe(overflow);
|
|
249
|
+
expect(metaOf(cls ?? {})["pragma/instancesShown"]).toBe(
|
|
250
|
+
ABOX_PER_CLASS_LIMIT,
|
|
251
|
+
);
|
|
252
|
+
expect(metaOf(cls ?? {})["pragma/truncated"]).toBe(true);
|
|
253
|
+
expect(cls?.description).toMatch(
|
|
254
|
+
new RegExp(`showing ${ABOX_PER_CLASS_LIMIT} of ${overflow}`),
|
|
255
|
+
);
|
|
256
|
+
} finally {
|
|
257
|
+
await scoped.cleanup();
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// =============================================================================
|
|
263
|
+
// Resource listing — foreign namespace label fallback
|
|
264
|
+
// =============================================================================
|
|
265
|
+
|
|
266
|
+
describe("resource listing — foreign namespace label fallback", () => {
|
|
267
|
+
const ttl = `
|
|
268
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
269
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
270
|
+
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
|
|
271
|
+
@prefix dcterms: <http://purl.org/dc/terms/> .
|
|
272
|
+
@prefix schema: <http://schema.org/> .
|
|
273
|
+
@prefix ex: <http://foreign.example/> .
|
|
274
|
+
|
|
275
|
+
ex:Widget a owl:Class ; skos:prefLabel "Foreign Widget" .
|
|
276
|
+
ex:gadget a ex:Widget ; dcterms:title "Shiny Gadget" .
|
|
277
|
+
ex:thing a ex:Widget ; schema:name "Plain Thing" .
|
|
278
|
+
`;
|
|
279
|
+
|
|
280
|
+
it("resolves a foreign class name via skos:prefLabel", async () => {
|
|
281
|
+
const scoped = await createClientForTtl(ttl, {
|
|
282
|
+
ex: "http://foreign.example/",
|
|
283
|
+
});
|
|
284
|
+
try {
|
|
285
|
+
const { resources } = await scoped.client.listResources();
|
|
286
|
+
const cls = resources.find((r) => r.uri === "ex:Widget");
|
|
287
|
+
expect(cls?.name).toBe("Class · Foreign Widget");
|
|
288
|
+
} finally {
|
|
289
|
+
await scoped.cleanup();
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("resolves foreign individual names via dcterms:title and schema:name", async () => {
|
|
294
|
+
const scoped = await createClientForTtl(ttl, {
|
|
295
|
+
ex: "http://foreign.example/",
|
|
296
|
+
});
|
|
297
|
+
try {
|
|
298
|
+
const { resources } = await scoped.client.listResources();
|
|
299
|
+
const gadget = resources.find((r) => r.uri === "ex:gadget");
|
|
300
|
+
const thing = resources.find((r) => r.uri === "ex:thing");
|
|
301
|
+
expect(gadget?.name).toBe("Foreign Widget · Shiny Gadget");
|
|
302
|
+
expect(thing?.name).toBe("Foreign Widget · Plain Thing");
|
|
303
|
+
} finally {
|
|
304
|
+
await scoped.cleanup();
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// =============================================================================
|
|
310
|
+
// Resource listing — longest-namespace prefix resolution
|
|
311
|
+
// =============================================================================
|
|
312
|
+
|
|
313
|
+
describe("resource listing — longest-namespace prefix resolution", () => {
|
|
314
|
+
it("compacts with the longest matching namespace", async () => {
|
|
315
|
+
const ttl = `
|
|
316
|
+
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
317
|
+
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
318
|
+
@prefix base: <http://ex.org/> .
|
|
319
|
+
@prefix sub: <http://ex.org/sub/> .
|
|
320
|
+
|
|
321
|
+
base:Thing a owl:Class ; rdfs:label "Thing" .
|
|
322
|
+
sub:Widget a owl:Class ; rdfs:label "Widget" .
|
|
323
|
+
`;
|
|
324
|
+
// `base` is registered before `sub`; first-match compaction would
|
|
325
|
+
// mis-compact to "base:sub/Widget".
|
|
326
|
+
const scoped = await createClientForTtl(ttl, {
|
|
327
|
+
base: "http://ex.org/",
|
|
328
|
+
sub: "http://ex.org/sub/",
|
|
329
|
+
});
|
|
330
|
+
try {
|
|
331
|
+
const { resources } = await scoped.client.listResources();
|
|
332
|
+
const uris = resources.map((r) => r.uri);
|
|
333
|
+
expect(uris).toContain("sub:Widget");
|
|
334
|
+
expect(uris).not.toContain("base:sub/Widget");
|
|
335
|
+
} finally {
|
|
336
|
+
await scoped.cleanup();
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// =============================================================================
|
|
342
|
+
// Autocomplete
|
|
343
|
+
// =============================================================================
|
|
344
|
+
|
|
345
|
+
async function completeUri(value: string): Promise<{
|
|
346
|
+
values: string[];
|
|
347
|
+
total?: number;
|
|
348
|
+
}> {
|
|
349
|
+
const result = await client.complete({
|
|
350
|
+
ref: { type: "ref/resource", uri: "{+uri}" },
|
|
351
|
+
argument: { name: "uri", value },
|
|
352
|
+
});
|
|
353
|
+
return result.completion;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
describe("autocomplete", () => {
|
|
357
|
+
it("matches a URI substring, not just a prefix", async () => {
|
|
358
|
+
const { values } = await completeUri("button");
|
|
359
|
+
expect(values).toContain(`${P.ds}global.component.button`);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
it("matches a human label fragment", async () => {
|
|
363
|
+
const { values } = await completeUri("Card");
|
|
364
|
+
expect(values).toContain(`${P.ds}global.component.card`);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("returns compacted URIs, not full URIs", async () => {
|
|
368
|
+
const { values } = await completeUri("button");
|
|
369
|
+
expect(values.every((v) => !v.startsWith("http"))).toBe(true);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it("ranks an exact label match above a substring match", async () => {
|
|
373
|
+
const { values } = await completeUri("component");
|
|
374
|
+
const exactIdx = values.indexOf(`${P.ds}Component`);
|
|
375
|
+
const substringIdx = values.indexOf(`${P.ds}global.component.button`);
|
|
376
|
+
expect(exactIdx).toBeGreaterThan(-1);
|
|
377
|
+
expect(substringIdx).toBeGreaterThan(-1);
|
|
378
|
+
expect(exactIdx).toBeLessThan(substringIdx);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it("caps the number of suggestions", async () => {
|
|
382
|
+
const { values } = await completeUri("");
|
|
383
|
+
expect(values.length).toBeLessThanOrEqual(COMPLETION_LIMIT);
|
|
384
|
+
expect(values).toHaveLength(COMPLETION_LIMIT);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// =============================================================================
|
|
389
|
+
// Read — component instance (ABox)
|
|
96
390
|
// =============================================================================
|
|
97
391
|
|
|
98
392
|
describe("read component instance", () => {
|
|
99
|
-
it("returns
|
|
393
|
+
it("returns an abox individual with types, label, and class pointer", async () => {
|
|
100
394
|
const result = await client.readResource({
|
|
101
395
|
uri: `${P.ds}global.component.button`,
|
|
102
396
|
});
|
|
103
397
|
const entity = parseContents(result) as {
|
|
104
|
-
uri: string;
|
|
105
398
|
prefixed: string;
|
|
399
|
+
box: string;
|
|
400
|
+
category: string;
|
|
106
401
|
types: string[];
|
|
107
402
|
label: string | null;
|
|
108
|
-
|
|
403
|
+
instanceOf: string | null;
|
|
109
404
|
};
|
|
110
405
|
expect(entity.prefixed).toBe(`${P.ds}global.component.button`);
|
|
406
|
+
expect(entity.box).toBe("abox");
|
|
407
|
+
expect(entity.category).toBe("individual");
|
|
111
408
|
expect(entity.types).toContain(`${P.ds}Component`);
|
|
112
409
|
expect(entity.label).toBe("Button");
|
|
410
|
+
expect(entity.instanceOf).toBe(`${P.ds}Component`);
|
|
113
411
|
});
|
|
114
412
|
|
|
115
413
|
it("resolves level-1 URI objects to summaries", async () => {
|
|
@@ -119,20 +417,13 @@ describe("read component instance", () => {
|
|
|
119
417
|
const entity = parseContents(result) as {
|
|
120
418
|
properties: {
|
|
121
419
|
predicate: string;
|
|
122
|
-
values: {
|
|
123
|
-
type: string;
|
|
124
|
-
uri?: string;
|
|
125
|
-
prefixed?: string;
|
|
126
|
-
label?: string | null;
|
|
127
|
-
}[];
|
|
420
|
+
values: { type: string; prefixed?: string }[];
|
|
128
421
|
}[];
|
|
129
422
|
};
|
|
130
|
-
|
|
131
423
|
const tierProp = entity.properties.find(
|
|
132
424
|
(p) => p.predicate === `${P.ds}tier`,
|
|
133
425
|
);
|
|
134
|
-
|
|
135
|
-
const tierValue = tierProp?.values[0];
|
|
426
|
+
const tierValue = tierProp?.values.at(0);
|
|
136
427
|
expect(tierValue?.type).toBe("uri");
|
|
137
428
|
expect(tierValue?.prefixed).toBe(`${P.ds}global`);
|
|
138
429
|
});
|
|
@@ -147,53 +438,85 @@ describe("read component instance", () => {
|
|
|
147
438
|
values: { type: string; value?: string }[];
|
|
148
439
|
}[];
|
|
149
440
|
};
|
|
150
|
-
|
|
151
441
|
const nameProp = entity.properties.find(
|
|
152
442
|
(p) => p.predicate === `${P.ds}name`,
|
|
153
443
|
);
|
|
154
|
-
expect(nameProp).
|
|
155
|
-
expect(nameProp?.values
|
|
156
|
-
|
|
444
|
+
expect(nameProp?.values.at(0)?.type).toBe("literal");
|
|
445
|
+
expect(nameProp?.values.at(0)?.value).toBe("Button");
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it("keeps URL-shaped literals as literals, not URIs", async () => {
|
|
449
|
+
const result = await client.readResource({
|
|
450
|
+
uri: `${P.ds}global.component.button`,
|
|
451
|
+
});
|
|
452
|
+
const entity = parseContents(result) as {
|
|
453
|
+
properties: {
|
|
454
|
+
predicate: string;
|
|
455
|
+
values: { type: string; value?: string }[];
|
|
456
|
+
}[];
|
|
457
|
+
};
|
|
458
|
+
const figma = entity.properties.find(
|
|
459
|
+
(p) => p.predicate === `${P.ds}figmaLink`,
|
|
460
|
+
);
|
|
461
|
+
const value = figma?.values.at(0);
|
|
462
|
+
expect(value?.type).toBe("literal");
|
|
463
|
+
expect(value?.value).toBe("https://figma.com/design/example/Button");
|
|
157
464
|
});
|
|
158
465
|
});
|
|
159
466
|
|
|
160
467
|
// =============================================================================
|
|
161
|
-
// Read OWL
|
|
468
|
+
// Read — OWL class (TBox)
|
|
162
469
|
// =============================================================================
|
|
163
470
|
|
|
164
471
|
describe("read OWL class", () => {
|
|
165
|
-
it("returns class with
|
|
166
|
-
const result = await client.readResource({
|
|
167
|
-
uri: `${P.ds}UIBlock`,
|
|
168
|
-
});
|
|
472
|
+
it("returns a tbox class enriched with schema relations", async () => {
|
|
473
|
+
const result = await client.readResource({ uri: `${P.ds}UIBlock` });
|
|
169
474
|
const entity = parseContents(result) as {
|
|
475
|
+
box: string;
|
|
476
|
+
category: string;
|
|
170
477
|
types: string[];
|
|
171
|
-
|
|
478
|
+
subClasses?: string[];
|
|
479
|
+
instanceCount?: number;
|
|
480
|
+
declaredProperties?: string[];
|
|
172
481
|
properties: {
|
|
173
482
|
predicate: string;
|
|
174
483
|
values: { type: string; value?: string }[];
|
|
175
484
|
}[];
|
|
176
485
|
};
|
|
486
|
+
expect(entity.box).toBe("tbox");
|
|
487
|
+
expect(entity.category).toBe("class");
|
|
177
488
|
expect(entity.types).toContain(`${P.owl}Class`);
|
|
489
|
+
expect(entity.subClasses).toContain(`${P.ds}Component`);
|
|
490
|
+
expect(entity.subClasses).toContain(`${P.ds}Subcomponent`);
|
|
491
|
+
expect(entity.declaredProperties).toContain(`${P.ds}tier`);
|
|
492
|
+
expect(entity.instanceCount).toBe(0);
|
|
493
|
+
|
|
178
494
|
const labelProp = entity.properties.find(
|
|
179
495
|
(p) => p.predicate === `${P.rdfs}label`,
|
|
180
496
|
);
|
|
181
|
-
expect(labelProp?.values
|
|
497
|
+
expect(labelProp?.values.at(0)?.value).toBe("UI Block");
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
it("reports superclasses and instance count for a subclass", async () => {
|
|
501
|
+
const result = await client.readResource({ uri: `${P.ds}Component` });
|
|
502
|
+
const entity = parseContents(result) as {
|
|
503
|
+
superClasses?: string[];
|
|
504
|
+
instanceCount?: number;
|
|
505
|
+
};
|
|
506
|
+
expect(entity.superClasses).toContain(`${P.ds}UIBlock`);
|
|
507
|
+
expect(entity.instanceCount).toBe(4);
|
|
182
508
|
});
|
|
183
509
|
});
|
|
184
510
|
|
|
185
511
|
// =============================================================================
|
|
186
|
-
// Read code
|
|
512
|
+
// Read — code standard and tier
|
|
187
513
|
// =============================================================================
|
|
188
514
|
|
|
189
515
|
describe("read code standard", () => {
|
|
190
516
|
it("returns standard with properties", async () => {
|
|
191
|
-
const result = await client.readResource({
|
|
192
|
-
uri: `${P.cs}code_purity`,
|
|
193
|
-
});
|
|
517
|
+
const result = await client.readResource({ uri: `${P.cs}code_purity` });
|
|
194
518
|
const entity = parseContents(result) as {
|
|
195
519
|
types: string[];
|
|
196
|
-
label: string | null;
|
|
197
520
|
properties: {
|
|
198
521
|
predicate: string;
|
|
199
522
|
values: { type: string; value?: string }[];
|
|
@@ -204,41 +527,28 @@ describe("read code standard", () => {
|
|
|
204
527
|
const nameProp = entity.properties.find(
|
|
205
528
|
(p) => p.predicate === `${P.cs}name`,
|
|
206
529
|
);
|
|
207
|
-
expect(nameProp?.values
|
|
530
|
+
expect(nameProp?.values.at(0)?.value).toBe("code/function/purity");
|
|
208
531
|
|
|
209
532
|
const doProp = entity.properties.find((p) => p.predicate === `${P.cs}do`);
|
|
210
|
-
expect(doProp).toBeDefined();
|
|
211
533
|
expect(doProp?.values.length).toBeGreaterThan(0);
|
|
212
|
-
|
|
213
|
-
const dontProp = entity.properties.find(
|
|
214
|
-
(p) => p.predicate === `${P.cs}dont`,
|
|
215
|
-
);
|
|
216
|
-
expect(dontProp).toBeDefined();
|
|
217
534
|
});
|
|
218
535
|
});
|
|
219
536
|
|
|
220
|
-
// =============================================================================
|
|
221
|
-
// Read tiers
|
|
222
|
-
// =============================================================================
|
|
223
|
-
|
|
224
537
|
describe("read tier", () => {
|
|
225
538
|
it("returns tier with name", async () => {
|
|
226
|
-
const result = await client.readResource({
|
|
227
|
-
uri: `${P.ds}apps_lxd`,
|
|
228
|
-
});
|
|
539
|
+
const result = await client.readResource({ uri: `${P.ds}apps_lxd` });
|
|
229
540
|
const entity = parseContents(result) as {
|
|
230
541
|
types: string[];
|
|
231
542
|
properties: {
|
|
232
543
|
predicate: string;
|
|
233
|
-
values: { type: string; value?: string
|
|
544
|
+
values: { type: string; value?: string }[];
|
|
234
545
|
}[];
|
|
235
546
|
};
|
|
236
547
|
expect(entity.types).toContain(`${P.ds}Tier`);
|
|
237
|
-
|
|
238
548
|
const nameProp = entity.properties.find(
|
|
239
549
|
(p) => p.predicate === `${P.ds}name`,
|
|
240
550
|
);
|
|
241
|
-
expect(nameProp?.values
|
|
551
|
+
expect(nameProp?.values.at(0)?.value).toBe("apps/lxd");
|
|
242
552
|
});
|
|
243
553
|
});
|
|
244
554
|
|
|
@@ -248,10 +558,8 @@ describe("read tier", () => {
|
|
|
248
558
|
|
|
249
559
|
describe("error handling", () => {
|
|
250
560
|
it("returns text/plain error for unknown entity", async () => {
|
|
251
|
-
const result = await client.readResource({
|
|
252
|
-
|
|
253
|
-
});
|
|
254
|
-
const first = result.contents[0] as ResourceContent;
|
|
561
|
+
const result = await client.readResource({ uri: `${P.ds}nonexistent` });
|
|
562
|
+
const first = result.contents.at(0) as ResourceContent;
|
|
255
563
|
expect(first.mimeType).toBe("text/plain");
|
|
256
564
|
expect(first.text).toContain("ENTITY_NOT_FOUND");
|
|
257
565
|
});
|