@canonical/pragma-cli 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +128 -47
- package/dist/pragma +0 -0
- package/package.json +15 -13
- package/src/completions/constants.ts +7 -0
- package/src/completions/handleQuery.test.ts +32 -0
- package/src/completions/handleQuery.ts +20 -1
- package/src/completions/queryCompletions.test.ts +5 -0
- package/src/completions/queryCompletions.ts +17 -3
- package/src/completions/querySocket.test.ts +31 -0
- package/src/completions/querySocket.ts +36 -9
- package/src/config/defaultConfig.test.ts +33 -0
- package/src/config/defaultConfig.ts +59 -0
- package/src/config/defaults.json +17 -0
- package/src/config/findProjectConfigPath.test.ts +53 -0
- package/src/config/findProjectConfigPath.ts +36 -0
- package/src/config/index.ts +17 -2
- package/src/config/mergeConfigFileUpdate.ts +58 -0
- package/src/config/parseConfigValues.ts +217 -0
- package/src/config/readConfig.test.ts +104 -13
- package/src/config/readConfig.ts +12 -153
- package/src/config/readConfigLayers.test.ts +109 -0
- package/src/config/readConfigLayers.ts +118 -0
- package/src/config/resolveGlobalConfigPath.ts +13 -0
- package/src/config/resolveWriteConfigPath.test.ts +53 -0
- package/src/config/resolveWriteConfigPath.ts +31 -0
- package/src/config/types.ts +83 -1
- package/src/config/writeConfig.ts +25 -55
- package/src/constants.ts +3 -1
- package/src/domains/block/commands/list.ts +5 -90
- package/src/domains/block/commands/lookup.ts +8 -167
- package/src/domains/block/commands/sample.ts +2 -1
- package/src/domains/block/formatters/list.test.ts +3 -3
- package/src/domains/block/formatters/lookup.test.ts +5 -5
- package/src/domains/block/mcp/specs.ts +16 -196
- package/src/domains/block/orchestration/enrichBlocks.ts +6 -3
- package/src/domains/block/orchestration/resolveBlockLookup.ts +2 -1
- package/src/domains/block/stories.test.ts +28 -0
- package/src/domains/block/stories.ts +260 -0
- package/src/domains/config/commands/channel.test.ts +30 -3
- package/src/domains/config/commands/channel.ts +25 -8
- package/src/domains/config/commands/configScope.ts +46 -0
- package/src/domains/config/commands/framework.test.ts +32 -1
- package/src/domains/config/commands/framework.ts +26 -8
- package/src/domains/config/commands/show.ts +5 -45
- package/src/domains/config/commands/tier.test.ts +20 -2
- package/src/domains/config/commands/tier.ts +25 -8
- package/src/domains/config/commands/trace.test.ts +19 -2
- package/src/domains/config/commands/trace.ts +6 -3
- package/src/domains/config/formatters/channel.test.ts +20 -6
- package/src/domains/config/formatters/channel.ts +14 -11
- package/src/domains/config/formatters/framework.ts +14 -11
- package/src/domains/config/formatters/show.test.ts +27 -0
- package/src/domains/config/formatters/show.ts +27 -4
- package/src/domains/config/formatters/tier.test.ts +26 -10
- package/src/domains/config/formatters/tier.ts +19 -11
- package/src/domains/config/formatters/trace.ts +7 -7
- package/src/domains/config/mcp/specs.ts +33 -53
- package/src/domains/config/operations/show.test.ts +18 -0
- package/src/domains/config/operations/show.ts +7 -1
- package/src/domains/config/operations/types.ts +7 -0
- package/src/domains/config/operations/validateTier.test.ts +9 -0
- package/src/domains/config/operations/validateTier.ts +10 -2
- package/src/domains/config/stories.ts +42 -0
- package/src/domains/config/tasks/index.ts +1 -0
- package/src/domains/config/tasks/setChannel.ts +13 -28
- package/src/domains/config/tasks/setFramework.ts +11 -30
- package/src/domains/config/tasks/setTier.ts +10 -29
- package/src/domains/config/tasks/setTrace.ts +10 -28
- package/src/domains/config/tasks/writeConfigField.ts +41 -0
- package/src/domains/create/generatorPack/bundled.ts +49 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.test.ts +159 -0
- package/src/domains/create/generatorPack/compileGeneratorPack.ts +312 -0
- package/src/domains/create/index.ts +13 -7
- package/src/domains/create/mcp/specs.ts +6 -161
- package/src/domains/create/renderGeneratorUi.test.ts +103 -0
- package/src/domains/create/renderGeneratorUi.ts +65 -0
- package/src/domains/doctor/formatters/doctor.test.ts +50 -2
- package/src/domains/doctor/formatters/doctor.ts +90 -38
- package/src/domains/doctor/operations/checks/checkConfigFile.ts +19 -5
- package/src/domains/doctor/operations/checks/checkMcpCommands.ts +133 -0
- package/src/domains/doctor/operations/checks/checkMcpConfigured.ts +1 -1
- package/src/domains/doctor/operations/checks/checkPackageRefs.ts +32 -26
- package/src/domains/doctor/operations/checks/checkSkillsSymlinked.ts +1 -1
- package/src/domains/doctor/operations/checks/index.ts +1 -0
- package/src/domains/doctor/operations/checks.test.ts +160 -7
- package/src/domains/doctor/operations/runChecks.test.ts +15 -6
- package/src/domains/doctor/operations/runChecks.ts +2 -0
- package/src/domains/doctor/operations/types.ts +23 -1
- package/src/domains/graph/commands/inspect.test.ts +2 -2
- package/src/domains/graph/commands/query.test.ts +5 -3
- package/src/domains/graph/formatters/inspect.ts +7 -7
- package/src/domains/graph/formatters/query.test.ts +87 -0
- package/src/domains/graph/formatters/query.ts +42 -5
- package/src/domains/graph/helpers/resolveUri.test.ts +50 -0
- package/src/domains/graph/helpers/resolveUri.ts +28 -21
- package/src/domains/graph/operations/inspectUri.test.ts +5 -5
- package/src/domains/graphql/commands/build.test.ts +5 -3
- package/src/domains/graphql/commands/build.ts +8 -16
- package/src/domains/graphql/commands/check.test.ts +5 -3
- package/src/domains/graphql/commands/check.ts +7 -13
- package/src/domains/graphql/commands/index.ts +1 -0
- package/src/domains/graphql/commands/serve.test.ts +46 -0
- package/src/domains/graphql/commands/serve.ts +141 -0
- package/src/domains/graphql/constants.ts +10 -0
- package/src/domains/graphql/helpers/gatherSources.test.ts +92 -0
- package/src/domains/graphql/helpers/gatherSources.ts +58 -0
- package/src/domains/graphql/helpers/index.ts +2 -0
- package/src/domains/graphql/helpers/parsePrefixes.test.ts +3 -3
- package/src/domains/graphql/helpers/parsePrefixes.ts +3 -3
- package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +9 -0
- package/src/domains/graphql/helpers/resolveSourceFiles.ts +24 -3
- package/src/domains/graphql/helpers/routeGraphql.test.ts +43 -0
- package/src/domains/graphql/helpers/routeGraphql.ts +28 -0
- package/src/domains/graphql/index.ts +9 -6
- package/src/domains/graphql/operations/compileSchema.test.ts +23 -47
- package/src/domains/graphql/operations/compileSchema.ts +23 -25
- package/src/domains/graphql/operations/createSchemaServer.test.ts +50 -0
- package/src/domains/graphql/operations/createSchemaServer.ts +75 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.test.ts +167 -0
- package/src/domains/graphql/operations/ensureSchemaArtifact.ts +178 -0
- package/src/domains/graphql/operations/index.ts +10 -0
- package/src/domains/info/formatters/upgrade.test.ts +7 -4
- package/src/domains/info/formatters/upgrade.ts +3 -1
- package/src/domains/info/operations/collectEntityCounts.test.ts +156 -0
- package/src/domains/info/operations/collectEntityCounts.ts +123 -0
- package/src/domains/info/operations/collectInfo.test.ts +14 -3
- package/src/domains/info/operations/collectInfo.ts +12 -15
- package/src/domains/info/operations/index.ts +1 -0
- package/src/domains/info/types.ts +13 -0
- package/src/domains/llm/capabilities.test.ts +24 -4
- package/src/domains/llm/commands/capabilities.ts +12 -3
- package/src/domains/llm/commands/llm.ts +5 -1
- package/src/domains/llm/data/commandReference.ts +20 -11
- package/src/domains/llm/data/decisionTrees.ts +10 -5
- package/src/domains/llm/data/toolCatalog.ts +55 -18
- package/src/domains/llm/formatters/orientation.ts +5 -1
- package/src/domains/llm/llmCommand.test.ts +11 -3
- package/src/domains/llm/mcp/specs.ts +3 -4
- package/src/domains/llm/operations/collectContext.test.ts +64 -0
- package/src/domains/llm/operations/collectContext.ts +7 -17
- package/src/domains/modifier/commands/list.ts +5 -38
- package/src/domains/modifier/commands/lookup.ts +8 -79
- package/src/domains/modifier/commands/sample.ts +2 -1
- package/src/domains/modifier/mcp/specs.ts +15 -94
- package/src/domains/modifier/operations/lookup.ts +5 -3
- package/src/domains/modifier/orchestration/resolveModifierLookup.ts +2 -1
- package/src/domains/modifier/stories.test.ts +20 -0
- package/src/domains/modifier/stories.ts +86 -0
- package/src/domains/ontology/commands/list.test.ts +5 -3
- package/src/domains/ontology/commands/list.ts +5 -58
- package/src/domains/ontology/commands/show.test.ts +85 -9
- package/src/domains/ontology/commands/show.ts +6 -58
- package/src/domains/ontology/formatters/index.ts +1 -0
- package/src/domains/ontology/formatters/list.ts +37 -12
- package/src/domains/ontology/formatters/show.ts +361 -64
- package/src/domains/ontology/helpers/buildClassTree.ts +89 -0
- package/src/domains/ontology/helpers/completeClassNames.ts +43 -0
- package/src/domains/ontology/helpers/expandOntologyIris.ts +79 -0
- package/src/domains/ontology/helpers/index.ts +14 -0
- package/src/domains/ontology/helpers/queryClasses.ts +32 -16
- package/src/domains/ontology/helpers/queryProperties.ts +39 -6
- package/src/domains/ontology/helpers/queryTboxFacts.ts +160 -0
- package/src/domains/ontology/mcp/specs.ts +7 -84
- package/src/domains/ontology/operations/listOntologies.test.ts +80 -3
- package/src/domains/ontology/operations/listOntologies.ts +126 -30
- package/src/domains/ontology/operations/showOntology.test.ts +131 -12
- package/src/domains/ontology/operations/showOntology.ts +289 -7
- package/src/domains/ontology/operations/showOntologyRaw.test.ts +4 -2
- package/src/domains/ontology/stories.test.ts +36 -0
- package/src/domains/ontology/stories.ts +153 -0
- package/src/domains/refs/operations/updateRefs.ts +2 -38
- package/src/domains/setup/commands/index.ts +1 -0
- package/src/domains/setup/commands/setup.ts +70 -0
- package/src/domains/setup/commands/skills.test.ts +6 -2
- package/src/domains/setup/commands/skills.ts +6 -2
- package/src/domains/setup/helpers/runSetupTask.test.ts +148 -150
- package/src/domains/setup/helpers/runSetupTask.ts +62 -70
- package/src/domains/setup/index.ts +7 -3
- package/src/domains/setup/operations/setupLsp.test.ts +3 -2
- package/src/domains/setup/operations/setupLsp.ts +7 -2
- package/src/domains/setup/operations/setupMcp.test.ts +6 -1
- package/src/domains/shared/bootStore.bareCore.test.ts +63 -0
- package/src/domains/shared/bootStore.test.ts +82 -0
- package/src/domains/shared/bootStore.ts +57 -18
- package/src/domains/shared/compactUri.test.ts +11 -0
- package/src/domains/shared/compactUri.ts +10 -5
- package/src/domains/shared/context.ts +2 -2
- package/src/domains/shared/contracts.ts +11 -0
- package/src/domains/shared/createInteractivePromptSession.test.ts +439 -0
- package/src/domains/shared/createInteractivePromptSession.ts +236 -0
- package/src/domains/shared/emptyErrorRecovery.test.ts +23 -26
- package/src/domains/shared/extractLocalName.test.ts +3 -3
- package/src/domains/shared/formatters.ts +23 -2
- package/src/domains/shared/listTiers.ts +40 -0
- package/src/domains/shared/loaders/bundledLoader.test.ts +248 -0
- package/src/domains/shared/loaders/bundledLoader.ts +158 -12
- package/src/domains/shared/loaders/gitLoader.ts +1 -2
- package/src/domains/shared/loaders/index.ts +4 -1
- package/src/domains/shared/loaders/localLoader.ts +2 -4
- package/src/domains/shared/loaders/readPackageDir.test.ts +58 -0
- package/src/domains/shared/loaders/readPackageDir.ts +82 -9
- package/src/domains/shared/loaders/storyAssetsPlugin.test.ts +84 -0
- package/src/domains/shared/loaders/storyAssetsPlugin.ts +46 -0
- package/src/domains/shared/lookupMany.test.ts +135 -0
- package/src/domains/shared/lookupMany.ts +50 -2
- package/src/domains/shared/mergeAndParseRefs.test.ts +89 -0
- package/src/domains/shared/mergeAndParseRefs.ts +44 -0
- package/src/domains/shared/namespaces.ts +13 -5
- package/src/domains/shared/packages.ts +10 -17
- package/src/domains/shared/parseSampleCount.test.ts +47 -0
- package/src/domains/shared/parseSampleCount.ts +45 -0
- package/src/domains/shared/prefixes.test.ts +211 -0
- package/src/domains/shared/prefixes.ts +182 -15
- package/src/domains/shared/renderers.ts +5 -5
- package/src/domains/shared/resolveConfiguredGraphs.test.ts +27 -0
- package/src/domains/shared/resolveConfiguredGraphs.ts +41 -0
- package/src/domains/shared/resolveLookupExitCode.test.ts +48 -0
- package/src/domains/shared/resolveLookupExitCode.ts +42 -0
- package/src/domains/shared/runtime.ts +4 -63
- package/src/domains/shared/semanticPackage.test.ts +89 -0
- package/src/domains/shared/semanticPackage.ts +34 -3
- package/src/domains/shared/stories/compileLookupCommand.test.ts +145 -0
- package/src/domains/shared/stories/compileLookupCommand.ts +102 -0
- package/src/domains/shared/stories/compileLookupTool.test.ts +105 -0
- package/src/domains/shared/stories/compileLookupTool.ts +96 -0
- package/src/domains/shared/stories/compileReadCommand.test.ts +121 -0
- package/src/domains/shared/stories/compileReadCommand.ts +48 -0
- package/src/domains/shared/stories/compileReadTool.test.ts +64 -0
- package/src/domains/shared/stories/compileReadTool.ts +38 -0
- package/src/domains/shared/stories/condense.test.ts +18 -0
- package/src/domains/shared/stories/condense.ts +15 -0
- package/src/domains/shared/stories/index.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.test.ts +20 -0
- package/src/domains/shared/stories/normalizeNames.ts +22 -0
- package/src/domains/shared/stories/pack/applyPackFilters.test.ts +151 -0
- package/src/domains/shared/stories/pack/applyPackFilters.ts +111 -0
- package/src/domains/shared/stories/pack/applyPackSearch.test.ts +57 -0
- package/src/domains/shared/stories/pack/applyPackSearch.ts +41 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.test.ts +81 -0
- package/src/domains/shared/stories/pack/buildLookupQuery.ts +154 -0
- package/src/domains/shared/stories/pack/bundled/index.ts +23 -0
- package/src/domains/shared/stories/pack/bundled/standardPack.ts +164 -0
- package/src/domains/shared/stories/pack/bundled/tierPack.ts +50 -0
- package/src/domains/shared/stories/pack/collectPackStories.test.ts +406 -0
- package/src/domains/shared/stories/pack/collectPackStories.ts +158 -0
- package/src/domains/shared/stories/pack/compilePackCommands.ts +50 -0
- package/src/domains/shared/stories/pack/compilePackStories.test.ts +751 -0
- package/src/domains/shared/stories/pack/compilePackStories.ts +724 -0
- package/src/domains/shared/stories/pack/compilePackToolSpecs.ts +55 -0
- package/src/domains/shared/stories/pack/index.ts +42 -0
- package/src/domains/shared/stories/pack/reservedVerbs.test.ts +213 -0
- package/src/domains/shared/stories/pack/reservedVerbs.ts +170 -0
- package/src/domains/shared/stories/pack/runSelectQuery.ts +31 -0
- package/src/domains/shared/stories/pack/standardParity.test.ts +381 -0
- package/src/domains/shared/stories/pack/types.ts +224 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.test.ts +742 -0
- package/src/domains/shared/stories/pack/validateStoryPackDefinition.ts +859 -0
- package/src/domains/shared/stories/projectCliParameters.test.ts +59 -0
- package/src/domains/shared/stories/projectCliParameters.ts +57 -0
- package/src/domains/shared/stories/projectToolParams.test.ts +50 -0
- package/src/domains/shared/stories/projectToolParams.ts +32 -0
- package/src/domains/shared/stories/requirePragmaContext.test.ts +23 -0
- package/src/domains/shared/stories/requirePragmaContext.ts +23 -0
- package/src/domains/shared/stories/resolveLookupDetailed.test.ts +57 -0
- package/src/domains/shared/stories/resolveLookupDetailed.ts +27 -0
- package/src/domains/shared/stories/types.ts +179 -0
- package/src/domains/shared/suggestions/expandGlob.ts +1 -0
- package/src/domains/shared/suggestions/suggestNames.ts +43 -10
- package/src/domains/shared/types/index.ts +5 -9
- package/src/domains/shared/types/ontology.ts +119 -24
- package/src/domains/shared/types/standard.ts +9 -52
- package/src/domains/skill/commands/index.ts +3 -1
- package/src/domains/skill/commands/list.test.ts +6 -2
- package/src/domains/skill/commands/list.ts +5 -63
- package/src/domains/skill/commands/lookup.test.ts +118 -0
- package/src/domains/skill/commands/lookup.ts +14 -0
- package/src/domains/skill/formatters/index.ts +1 -0
- package/src/domains/skill/formatters/lookup.test.ts +46 -0
- package/src/domains/skill/formatters/lookup.ts +57 -0
- package/src/domains/skill/helpers/resolveSkillSources.ts +0 -1
- package/src/domains/skill/index.ts +7 -3
- package/src/domains/skill/mcp/specs.ts +10 -29
- package/src/domains/skill/operations/discover.test.ts +61 -30
- package/src/domains/skill/operations/discover.ts +28 -37
- package/src/domains/skill/operations/index.ts +2 -1
- package/src/domains/skill/operations/list.test.ts +15 -7
- package/src/domains/skill/operations/lookup.test.ts +91 -0
- package/src/domains/skill/operations/lookup.ts +70 -0
- package/src/domains/skill/stories.test.ts +43 -0
- package/src/domains/skill/stories.ts +103 -0
- package/src/domains/skill/types.ts +8 -0
- package/src/domains/token/commands/lookup.test.ts +8 -0
- package/src/domains/token/commands/lookup.ts +12 -0
- package/src/domains/token/commands/sample.ts +2 -1
- package/src/domains/token/featureFlag.ts +17 -0
- package/src/domains/token/index.ts +5 -0
- package/src/domains/token/mcp/specs.ts +18 -2
- package/src/domains/token/orchestration/resolveTokenLookup.ts +2 -1
- package/src/domains/trace/commands/resolveTraceLimit.test.ts +31 -0
- package/src/domains/trace/commands/show.ts +30 -4
- package/src/domains/trace/tracePlugin.test.ts +1 -1
- package/src/index.ts +1 -13
- package/src/mcp/registerResources.test.ts +382 -74
- package/src/mcp/registerResources.ts +5 -348
- package/src/mcp/resources/buildGraphIndex.ts +167 -0
- package/src/mcp/resources/buildResourceList.test.ts +97 -0
- package/src/mcp/resources/buildResourceList.ts +176 -0
- package/src/mcp/resources/classifyEntity.test.ts +40 -0
- package/src/mcp/resources/classifyEntity.ts +27 -0
- package/src/mcp/resources/constants.ts +105 -0
- package/src/mcp/resources/displayPredicates.ts +62 -0
- package/src/mcp/resources/pickFirstValue.test.ts +29 -0
- package/src/mcp/resources/pickFirstValue.ts +26 -0
- package/src/mcp/resources/pickPrimaryType.test.ts +41 -0
- package/src/mcp/resources/pickPrimaryType.ts +26 -0
- package/src/mcp/resources/rankUriCompletions.test.ts +52 -0
- package/src/mcp/resources/rankUriCompletions.ts +64 -0
- package/src/mcp/resources/readEntity.ts +169 -0
- package/src/mcp/resources/registerResources.ts +126 -0
- package/src/mcp/resources/types.ts +128 -0
- package/src/mcp/tools/index.ts +22 -5
- package/src/mcp/tools/registerTools.test.ts +167 -34
- package/src/mcp/types.ts +4 -0
- package/src/pipeline/collectCommands.test.ts +151 -1
- package/src/pipeline/collectCommands.ts +35 -13
- package/src/pipeline/createProgram.test.ts +5 -1
- package/src/pipeline/createProgram.ts +2 -2
- package/src/pipeline/firstRun.test.ts +80 -0
- package/src/pipeline/firstRun.ts +99 -0
- package/src/pipeline/parseGlobalFlags.test.ts +102 -1
- package/src/pipeline/parseGlobalFlags.ts +98 -9
- package/src/pipeline/resolveCommandKind.test.ts +12 -0
- package/src/pipeline/resolveCommandKind.ts +4 -0
- package/src/pipeline/rootHelp.test.ts +87 -0
- package/src/pipeline/rootHelp.ts +265 -0
- package/src/pipeline/runCli.orchestration.test.ts +28 -12
- package/src/pipeline/runCli.test.ts +17 -4
- package/src/pipeline/runCli.ts +202 -25
- package/src/testing/cli.ts +30 -2
- package/src/testing/createTestMcpClient.ts +4 -1
- package/src/testing/dsFixtures.ts +21 -4
- package/src/testing/index.ts +7 -0
- package/src/testing/integration/__snapshots__/executor-golden.test.ts.snap +1207 -0
- package/src/testing/integration/cli-user-stories.test.ts +63 -0
- package/src/testing/integration/cross-binary-byte-equality.test.ts +129 -0
- package/src/testing/integration/edge-cases.test.ts +62 -50
- package/src/testing/integration/executor-execution.test.ts +103 -0
- package/src/testing/integration/executor-golden.test.ts +145 -0
- package/src/testing/integration/mcp-surface.test.ts +40 -15
- package/src/testing/integration/parity.test.ts +136 -82
- package/src/testing/regression/0001-skill-discovery-granularity.test.ts +71 -0
- package/src/testing/setupXdgIsolation.ts +26 -0
- package/src/testing/standardParityFixtures.ts +35 -0
- package/src/testing/store.ts +4 -4
- package/src/testing/storyFixtures.ts +63 -0
- package/src/domains/create/commands/component.test.ts +0 -166
- package/src/domains/create/commands/component.ts +0 -123
- package/src/domains/create/commands/index.ts +0 -3
- package/src/domains/create/commands/package.test.ts +0 -35
- package/src/domains/create/commands/package.ts +0 -21
- package/src/domains/create/generators.ts +0 -8
- package/src/domains/standard/commands/categories.test.ts +0 -70
- package/src/domains/standard/commands/categories.ts +0 -48
- package/src/domains/standard/commands/index.ts +0 -6
- package/src/domains/standard/commands/list.test.ts +0 -105
- package/src/domains/standard/commands/list.ts +0 -90
- package/src/domains/standard/commands/lookup.test.ts +0 -135
- package/src/domains/standard/commands/lookup.ts +0 -99
- package/src/domains/standard/commands/sample.ts +0 -57
- package/src/domains/standard/formatters/categories.test.ts +0 -44
- package/src/domains/standard/formatters/categories.ts +0 -38
- package/src/domains/standard/formatters/index.ts +0 -10
- package/src/domains/standard/formatters/list.test.ts +0 -169
- package/src/domains/standard/formatters/list.ts +0 -184
- package/src/domains/standard/formatters/lookup.test.ts +0 -95
- package/src/domains/standard/formatters/lookup.ts +0 -101
- package/src/domains/standard/formatters/sample.ts +0 -15
- package/src/domains/standard/formatters/types.ts +0 -31
- package/src/domains/standard/index.ts +0 -40
- package/src/domains/standard/mcp/index.ts +0 -2
- package/src/domains/standard/mcp/specs.ts +0 -244
- package/src/domains/standard/operations/categories.test.ts +0 -61
- package/src/domains/standard/operations/categories.ts +0 -38
- package/src/domains/standard/operations/index.ts +0 -6
- package/src/domains/standard/operations/list.test.ts +0 -75
- package/src/domains/standard/operations/list.ts +0 -64
- package/src/domains/standard/operations/lookup.test.ts +0 -58
- package/src/domains/standard/operations/lookup.ts +0 -151
- package/src/domains/standard/operations/sample.ts +0 -35
- package/src/domains/standard/orchestration/buildStandardFilters.ts +0 -11
- package/src/domains/standard/orchestration/index.ts +0 -4
- package/src/domains/standard/orchestration/resolveStandardList.ts +0 -45
- package/src/domains/standard/orchestration/resolveStandardLookup.ts +0 -32
- package/src/domains/standard/orchestration/standardEmptyError.test.ts +0 -33
- package/src/domains/standard/orchestration/standardEmptyError.ts +0 -29
- package/src/domains/standard/standardConfig.ts +0 -42
- package/src/domains/standard/types.ts +0 -15
- package/src/domains/tier/commands/index.ts +0 -3
- package/src/domains/tier/commands/list.test.ts +0 -67
- package/src/domains/tier/commands/list.ts +0 -59
- package/src/domains/tier/formatters/index.ts +0 -3
- package/src/domains/tier/formatters/list.test.ts +0 -33
- package/src/domains/tier/formatters/list.ts +0 -45
- package/src/domains/tier/index.ts +0 -17
- package/src/domains/tier/mcp/index.ts +0 -2
- package/src/domains/tier/mcp/specs.ts +0 -38
- package/src/domains/tier/operations/index.ts +0 -3
- package/src/domains/tier/operations/list.test.ts +0 -32
- package/src/domains/tier/operations/list.ts +0 -33
- package/src/pipeline/runInteractiveCommand.ts +0 -198
|
@@ -9,9 +9,19 @@ import { tmpdir } from "node:os";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
11
11
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
createTestMcpClient,
|
|
14
|
+
RECIPE_PREFIXES,
|
|
15
|
+
RECIPE_STORY,
|
|
16
|
+
RECIPE_TTL,
|
|
17
|
+
} from "#testing";
|
|
18
|
+
import { TOKEN_READ_SURFACE_ENABLED } from "../../domains/token/featureFlag.js";
|
|
13
19
|
import type { McpErrorPayload } from "../types.js";
|
|
14
20
|
|
|
21
|
+
// token_list, token_lookup, and token_sample are gated behind the token
|
|
22
|
+
// read-surface feature flag.
|
|
23
|
+
const EXPECTED_TOOL_COUNT = TOKEN_READ_SURFACE_ENABLED ? 34 : 31;
|
|
24
|
+
|
|
15
25
|
let client: Client;
|
|
16
26
|
let cleanup: () => Promise<void>;
|
|
17
27
|
|
|
@@ -52,9 +62,9 @@ function parseData(result: Record<string, unknown>): unknown {
|
|
|
52
62
|
// =============================================================================
|
|
53
63
|
|
|
54
64
|
describe("tool listing", () => {
|
|
55
|
-
it("registers
|
|
65
|
+
it("registers the expected number of tools", async () => {
|
|
56
66
|
const { tools } = await client.listTools();
|
|
57
|
-
expect(tools).toHaveLength(
|
|
67
|
+
expect(tools).toHaveLength(EXPECTED_TOOL_COUNT);
|
|
58
68
|
});
|
|
59
69
|
|
|
60
70
|
it("all tools have descriptions", async () => {
|
|
@@ -75,8 +85,10 @@ describe("tool listing", () => {
|
|
|
75
85
|
expect(names).toContain("standard_categories");
|
|
76
86
|
expect(names).toContain("modifier_list");
|
|
77
87
|
expect(names).toContain("modifier_lookup");
|
|
78
|
-
|
|
79
|
-
|
|
88
|
+
if (TOKEN_READ_SURFACE_ENABLED) {
|
|
89
|
+
expect(names).toContain("token_list");
|
|
90
|
+
expect(names).toContain("token_lookup");
|
|
91
|
+
}
|
|
80
92
|
expect(names).toContain("tier_list");
|
|
81
93
|
expect(names).toContain("config_show");
|
|
82
94
|
expect(names).toContain("config_tier");
|
|
@@ -97,7 +109,9 @@ describe("tool listing", () => {
|
|
|
97
109
|
// Sample tools
|
|
98
110
|
expect(names).toContain("block_sample");
|
|
99
111
|
expect(names).toContain("standard_sample");
|
|
100
|
-
|
|
112
|
+
if (TOKEN_READ_SURFACE_ENABLED) {
|
|
113
|
+
expect(names).toContain("token_sample");
|
|
114
|
+
}
|
|
101
115
|
expect(names).toContain("modifier_sample");
|
|
102
116
|
});
|
|
103
117
|
|
|
@@ -107,6 +121,67 @@ describe("tool listing", () => {
|
|
|
107
121
|
expect(tool.name).not.toMatch(/^pragma_/);
|
|
108
122
|
}
|
|
109
123
|
});
|
|
124
|
+
|
|
125
|
+
// Golden surface: the full built-in tool set plus bundled packs, in
|
|
126
|
+
// registration order. The per-(noun, verb) reserved-guard flip must leave
|
|
127
|
+
// this byte-identical AND order-identical — registration order is the tool
|
|
128
|
+
// surface a client sees.
|
|
129
|
+
it("has a stable built-in tool surface", async () => {
|
|
130
|
+
const names = (await client.listTools()).tools.map((tool) => tool.name);
|
|
131
|
+
|
|
132
|
+
expect(names).toEqual([
|
|
133
|
+
"block_list",
|
|
134
|
+
"block_lookup",
|
|
135
|
+
"block_sample",
|
|
136
|
+
"modifier_list",
|
|
137
|
+
"modifier_lookup",
|
|
138
|
+
"modifier_sample",
|
|
139
|
+
...(TOKEN_READ_SURFACE_ENABLED ? ["token_list", "token_lookup"] : []),
|
|
140
|
+
"tokens_add_config",
|
|
141
|
+
...(TOKEN_READ_SURFACE_ENABLED ? ["token_sample"] : []),
|
|
142
|
+
"config_show",
|
|
143
|
+
"config_tier",
|
|
144
|
+
"config_channel",
|
|
145
|
+
"ontology_list",
|
|
146
|
+
"ontology_show",
|
|
147
|
+
"graph_query",
|
|
148
|
+
"graph_inspect",
|
|
149
|
+
"skill_list",
|
|
150
|
+
"skill_lookup",
|
|
151
|
+
"doctor",
|
|
152
|
+
"info",
|
|
153
|
+
"capabilities",
|
|
154
|
+
"llm",
|
|
155
|
+
"create_component",
|
|
156
|
+
"create_package",
|
|
157
|
+
"create_application",
|
|
158
|
+
"create_domain",
|
|
159
|
+
"create_route",
|
|
160
|
+
"create_wrapper",
|
|
161
|
+
// Bundled packs register after the built-in tools: `tier_list` and the
|
|
162
|
+
// whole `standard` noun are served by bundled story packs — the
|
|
163
|
+
// hand-written tier and standard domains were deleted.
|
|
164
|
+
"tier_list",
|
|
165
|
+
"standard_list",
|
|
166
|
+
"standard_lookup",
|
|
167
|
+
"standard_categories",
|
|
168
|
+
"standard_sample",
|
|
169
|
+
]);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("serves the standard tools from the bundled pack, not built-ins", async () => {
|
|
173
|
+
const { tools } = await client.listTools();
|
|
174
|
+
const standardList = tools.find((tool) => tool.name === "standard_list");
|
|
175
|
+
// Pack-compiled tool descriptions carry no story-pack suffix here only
|
|
176
|
+
// because the bundled pack curates them; the giveaway is the derived
|
|
177
|
+
// `search`/`category` params on the pack projection.
|
|
178
|
+
const params = Object.keys(
|
|
179
|
+
(standardList?.inputSchema as { properties?: object })?.properties ?? {},
|
|
180
|
+
);
|
|
181
|
+
expect(params).toContain("category");
|
|
182
|
+
expect(params).toContain("search");
|
|
183
|
+
expect(params).toContain("condensed");
|
|
184
|
+
});
|
|
110
185
|
});
|
|
111
186
|
|
|
112
187
|
// =============================================================================
|
|
@@ -414,7 +489,7 @@ describe("modifier_lookup", () => {
|
|
|
414
489
|
// Token tools
|
|
415
490
|
// =============================================================================
|
|
416
491
|
|
|
417
|
-
describe("token_list", () => {
|
|
492
|
+
describe.skipIf(!TOKEN_READ_SURFACE_ENABLED)("token_list", () => {
|
|
418
493
|
it("returns tokens", async () => {
|
|
419
494
|
const result = await client.callTool({
|
|
420
495
|
name: "token_list",
|
|
@@ -425,7 +500,7 @@ describe("token_list", () => {
|
|
|
425
500
|
});
|
|
426
501
|
});
|
|
427
502
|
|
|
428
|
-
describe("token_lookup", () => {
|
|
503
|
+
describe.skipIf(!TOKEN_READ_SURFACE_ENABLED)("token_lookup", () => {
|
|
429
504
|
it("returns token with theme values", async () => {
|
|
430
505
|
const result = await client.callTool({
|
|
431
506
|
name: "token_lookup",
|
|
@@ -463,10 +538,11 @@ describe("tier_list", () => {
|
|
|
463
538
|
name: "tier_list",
|
|
464
539
|
arguments: {},
|
|
465
540
|
});
|
|
466
|
-
|
|
541
|
+
// The bundled tier pack names the field `name` (its `ds:name` value).
|
|
542
|
+
const data = parseData(result) as { name: string }[];
|
|
467
543
|
expect(data.length).toBeGreaterThan(0);
|
|
468
|
-
const
|
|
469
|
-
expect(
|
|
544
|
+
const names = data.map((t) => t.name);
|
|
545
|
+
expect(names).toContain("global");
|
|
470
546
|
});
|
|
471
547
|
});
|
|
472
548
|
|
|
@@ -508,6 +584,8 @@ describe("config_show", () => {
|
|
|
508
584
|
describe("config_tier", () => {
|
|
509
585
|
it("sets, queries, and resets tier in workspace config", async () => {
|
|
510
586
|
const dir = mkdtempSync(join(tmpdir(), "pragma-mcp-tier-"));
|
|
587
|
+
// Seed a project file so global-first writes stay in this workspace.
|
|
588
|
+
writeFileSync(join(dir, "pragma.config.json"), "{}");
|
|
511
589
|
|
|
512
590
|
try {
|
|
513
591
|
const scoped = await createTestMcpClient({ cwd: dir });
|
|
@@ -517,7 +595,10 @@ describe("config_tier", () => {
|
|
|
517
595
|
name: "config_tier",
|
|
518
596
|
arguments: { path: "global" },
|
|
519
597
|
});
|
|
520
|
-
expect(parseData(setResult)).
|
|
598
|
+
expect(parseData(setResult)).toMatchObject({
|
|
599
|
+
tier: "global",
|
|
600
|
+
action: "set",
|
|
601
|
+
});
|
|
521
602
|
|
|
522
603
|
const queryResult = await scoped.client.callTool({
|
|
523
604
|
name: "config_tier",
|
|
@@ -532,7 +613,10 @@ describe("config_tier", () => {
|
|
|
532
613
|
name: "config_tier",
|
|
533
614
|
arguments: { reset: true },
|
|
534
615
|
});
|
|
535
|
-
expect(parseData(resetResult)).
|
|
616
|
+
expect(parseData(resetResult)).toMatchObject({
|
|
617
|
+
tier: null,
|
|
618
|
+
action: "reset",
|
|
619
|
+
});
|
|
536
620
|
|
|
537
621
|
const queriedAfterReset = await scoped.client.callTool({
|
|
538
622
|
name: "config_tier",
|
|
@@ -554,6 +638,8 @@ describe("config_tier", () => {
|
|
|
554
638
|
describe("config_channel", () => {
|
|
555
639
|
it("sets, queries, and resets channel in workspace config", async () => {
|
|
556
640
|
const dir = mkdtempSync(join(tmpdir(), "pragma-mcp-channel-"));
|
|
641
|
+
// Seed a project file so global-first writes stay in this workspace.
|
|
642
|
+
writeFileSync(join(dir, "pragma.config.json"), "{}");
|
|
557
643
|
|
|
558
644
|
try {
|
|
559
645
|
const scoped = await createTestMcpClient({ cwd: dir });
|
|
@@ -563,7 +649,7 @@ describe("config_channel", () => {
|
|
|
563
649
|
name: "config_channel",
|
|
564
650
|
arguments: { value: "experimental" },
|
|
565
651
|
});
|
|
566
|
-
expect(parseData(setResult)).
|
|
652
|
+
expect(parseData(setResult)).toMatchObject({
|
|
567
653
|
channel: "experimental",
|
|
568
654
|
action: "set",
|
|
569
655
|
});
|
|
@@ -581,7 +667,7 @@ describe("config_channel", () => {
|
|
|
581
667
|
name: "config_channel",
|
|
582
668
|
arguments: { reset: true },
|
|
583
669
|
});
|
|
584
|
-
expect(parseData(resetResult)).
|
|
670
|
+
expect(parseData(resetResult)).toMatchObject({
|
|
585
671
|
channel: "normal",
|
|
586
672
|
action: "reset",
|
|
587
673
|
});
|
|
@@ -699,7 +785,7 @@ describe("create_component", () => {
|
|
|
699
785
|
const result = await client.callTool({
|
|
700
786
|
name: "create_component",
|
|
701
787
|
arguments: {
|
|
702
|
-
|
|
788
|
+
variant: "react",
|
|
703
789
|
componentPath: "src/components/Button",
|
|
704
790
|
},
|
|
705
791
|
});
|
|
@@ -714,7 +800,7 @@ describe("create_component", () => {
|
|
|
714
800
|
const result = await client.callTool({
|
|
715
801
|
name: "create_component",
|
|
716
802
|
arguments: {
|
|
717
|
-
|
|
803
|
+
variant: "svelte",
|
|
718
804
|
componentPath: "src/lib/components/Toggle",
|
|
719
805
|
},
|
|
720
806
|
});
|
|
@@ -723,11 +809,11 @@ describe("create_component", () => {
|
|
|
723
809
|
expect((data.generator as { name: string }).name).toBe("component/svelte");
|
|
724
810
|
});
|
|
725
811
|
|
|
726
|
-
it("returns error for invalid
|
|
812
|
+
it("returns error for invalid variant", async () => {
|
|
727
813
|
const result = await client.callTool({
|
|
728
814
|
name: "create_component",
|
|
729
815
|
arguments: {
|
|
730
|
-
|
|
816
|
+
variant: "angular",
|
|
731
817
|
componentPath: "src/components/Button",
|
|
732
818
|
},
|
|
733
819
|
});
|
|
@@ -769,7 +855,7 @@ describe("llm", () => {
|
|
|
769
855
|
expect(data.context.counts.blocks).toBeGreaterThan(0);
|
|
770
856
|
expect(data.context.counts.standards).toBeGreaterThan(0);
|
|
771
857
|
expect(data.context.namespaces.length).toBeGreaterThan(0);
|
|
772
|
-
expect(data.decisionTrees).toHaveLength(5);
|
|
858
|
+
expect(data.decisionTrees).toHaveLength(TOKEN_READ_SURFACE_ENABLED ? 5 : 4);
|
|
773
859
|
expect(data.commandReference.length).toBeGreaterThan(0);
|
|
774
860
|
});
|
|
775
861
|
});
|
|
@@ -783,7 +869,9 @@ describe("error handling", () => {
|
|
|
783
869
|
const notFoundCalls = [
|
|
784
870
|
{ name: "block_lookup", arguments: { names: ["X"] } },
|
|
785
871
|
{ name: "modifier_lookup", arguments: { names: ["X"] } },
|
|
786
|
-
|
|
872
|
+
...(TOKEN_READ_SURFACE_ENABLED
|
|
873
|
+
? [{ name: "token_lookup", arguments: { names: ["X"] } }]
|
|
874
|
+
: []),
|
|
787
875
|
{ name: "standard_lookup", arguments: { names: ["X"] } },
|
|
788
876
|
] as const;
|
|
789
877
|
|
|
@@ -857,7 +945,7 @@ describe("ontology_show", () => {
|
|
|
857
945
|
const envelope = parseEnvelope(result);
|
|
858
946
|
expect(envelope.ok).toBe(true);
|
|
859
947
|
expect(envelope.condensed).toBe(true);
|
|
860
|
-
expect(envelope.text).toEqual(expect.stringContaining("## ds:"));
|
|
948
|
+
expect(envelope.text).toEqual(expect.stringContaining("## Ontology ds:"));
|
|
861
949
|
});
|
|
862
950
|
});
|
|
863
951
|
|
|
@@ -964,6 +1052,48 @@ describe("graph_inspect", () => {
|
|
|
964
1052
|
// Skill tools
|
|
965
1053
|
// =============================================================================
|
|
966
1054
|
|
|
1055
|
+
describe("story-pack tools", () => {
|
|
1056
|
+
it("registers <noun>_list and <noun>_lookup from a stories config", async () => {
|
|
1057
|
+
const scoped = await createTestMcpClient({
|
|
1058
|
+
ttl: RECIPE_TTL,
|
|
1059
|
+
config: {
|
|
1060
|
+
tier: undefined,
|
|
1061
|
+
channel: "normal",
|
|
1062
|
+
stories: [RECIPE_STORY],
|
|
1063
|
+
prefixes: RECIPE_PREFIXES,
|
|
1064
|
+
},
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
try {
|
|
1068
|
+
const tools = (await scoped.client.listTools()).tools.map(
|
|
1069
|
+
(tool) => tool.name,
|
|
1070
|
+
);
|
|
1071
|
+
expect(tools).toHaveLength(EXPECTED_TOOL_COUNT + 2);
|
|
1072
|
+
expect(tools).toContain("recipe_list");
|
|
1073
|
+
expect(tools).toContain("recipe_lookup");
|
|
1074
|
+
|
|
1075
|
+
const listResult = await scoped.client.callTool({
|
|
1076
|
+
name: "recipe_list",
|
|
1077
|
+
arguments: {},
|
|
1078
|
+
});
|
|
1079
|
+
const rows = parseData(listResult) as { name: string }[];
|
|
1080
|
+
expect(rows.map((row) => row.name)).toEqual(["Gazpacho", "Pancakes"]);
|
|
1081
|
+
|
|
1082
|
+
const lookupResult = await scoped.client.callTool({
|
|
1083
|
+
name: "recipe_lookup",
|
|
1084
|
+
arguments: { names: ["pancakes"] },
|
|
1085
|
+
});
|
|
1086
|
+
const data = parseData(lookupResult) as {
|
|
1087
|
+
results: { name: string; instructions: string }[];
|
|
1088
|
+
};
|
|
1089
|
+
expect(data.results.at(0)?.name).toBe("Pancakes");
|
|
1090
|
+
expect(data.results.at(0)?.instructions).toBe("Mix, fry, flip.");
|
|
1091
|
+
} finally {
|
|
1092
|
+
await scoped.cleanup();
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
});
|
|
1096
|
+
|
|
967
1097
|
describe("skill_list", () => {
|
|
968
1098
|
it("returns skills data", async () => {
|
|
969
1099
|
const result = await client.callTool({
|
|
@@ -1048,9 +1178,9 @@ describe("capabilities", () => {
|
|
|
1048
1178
|
expect(toolNames).toContain("block_list");
|
|
1049
1179
|
expect(toolNames).toContain("capabilities");
|
|
1050
1180
|
expect(data.tools.every((t) => t.use_when.length > 0)).toBe(true);
|
|
1051
|
-
expect(data.counts.total).toBe(
|
|
1181
|
+
expect(data.counts.total).toBe(EXPECTED_TOOL_COUNT);
|
|
1052
1182
|
expect(data.counts.read).toBeGreaterThan(0);
|
|
1053
|
-
expect(data.counts.write).toBe(
|
|
1183
|
+
expect(data.counts.write).toBe(9);
|
|
1054
1184
|
expect(data.counts.orientation).toBe(2);
|
|
1055
1185
|
expect(data.counts.diagnostic).toBe(2);
|
|
1056
1186
|
expect(data.version).toBeDefined();
|
|
@@ -1131,14 +1261,17 @@ describe("condensed parameter", () => {
|
|
|
1131
1261
|
expect((envelope.text as string).length).toBeGreaterThan(0);
|
|
1132
1262
|
});
|
|
1133
1263
|
|
|
1134
|
-
it(
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1264
|
+
it.skipIf(!TOKEN_READ_SURFACE_ENABLED)(
|
|
1265
|
+
"token_lookup returns condensed text",
|
|
1266
|
+
async () => {
|
|
1267
|
+
const result = await client.callTool({
|
|
1268
|
+
name: "token_lookup",
|
|
1269
|
+
arguments: { names: ["color.primary"], condensed: true },
|
|
1270
|
+
});
|
|
1271
|
+
const envelope = parseEnvelope(result);
|
|
1272
|
+
expect(envelope.ok).toBe(true);
|
|
1273
|
+
expect(envelope.condensed).toBe(true);
|
|
1274
|
+
expect(typeof envelope.text).toBe("string");
|
|
1275
|
+
},
|
|
1276
|
+
);
|
|
1144
1277
|
});
|
package/src/mcp/types.ts
CHANGED
|
@@ -25,6 +25,8 @@ export type ToolPayload =
|
|
|
25
25
|
readonly meta?: {
|
|
26
26
|
readonly count?: number;
|
|
27
27
|
readonly filters?: Record<string, string>;
|
|
28
|
+
/** Queries that failed unexpectedly (surfaced only when > 0). */
|
|
29
|
+
readonly internalErrorCount?: number;
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
| {
|
|
@@ -47,6 +49,8 @@ export interface ToolResponse<T = unknown> {
|
|
|
47
49
|
readonly meta: {
|
|
48
50
|
readonly count?: number;
|
|
49
51
|
readonly filters?: Record<string, string>;
|
|
52
|
+
/** Queries that failed unexpectedly (surfaced only when > 0). */
|
|
53
|
+
readonly internalErrorCount?: number;
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
2
2
|
import type { PragmaContext } from "../domains/shared/context.js";
|
|
3
3
|
import type { PragmaRuntime } from "../domains/shared/runtime.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveReservedVerbs,
|
|
6
|
+
isReserved,
|
|
7
|
+
nounVerbFromPath,
|
|
8
|
+
nounVerbFromToolName,
|
|
9
|
+
} from "../domains/shared/stories/pack/index.js";
|
|
10
|
+
import { TOKEN_READ_SURFACE_ENABLED } from "../domains/token/featureFlag.js";
|
|
11
|
+
import { allSpecs } from "../mcp/tools/index.js";
|
|
4
12
|
import createTestRuntime from "../testing/helpers/createTestRuntime.js";
|
|
5
|
-
import collectCommands from "./collectCommands.js";
|
|
13
|
+
import collectCommands, { builtInCommands } from "./collectCommands.js";
|
|
6
14
|
|
|
7
15
|
let runtime: PragmaRuntime;
|
|
8
16
|
|
|
@@ -34,4 +42,146 @@ describe("collectCommands", () => {
|
|
|
34
42
|
expect(paths).toContain("graph query");
|
|
35
43
|
expect(paths).toContain("graph inspect");
|
|
36
44
|
});
|
|
45
|
+
|
|
46
|
+
// Golden surface: the full built-in command set, in emission order. The
|
|
47
|
+
// per-(noun, verb) reserved-guard flip must not add, drop, rename, or REORDER
|
|
48
|
+
// a single built-in command — order drives help output and registration.
|
|
49
|
+
// `tier list` and the whole `standard` noun are no longer here: the
|
|
50
|
+
// hand-written domains were deleted and are served by bundled story packs
|
|
51
|
+
// (asserted below).
|
|
52
|
+
it("has a stable built-in command surface", () => {
|
|
53
|
+
const paths = builtInCommands(makeCtx()).map((command) =>
|
|
54
|
+
command.path.join(" "),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(paths).toEqual([
|
|
58
|
+
"config tier",
|
|
59
|
+
"config channel",
|
|
60
|
+
"config trace",
|
|
61
|
+
"config framework",
|
|
62
|
+
"config show",
|
|
63
|
+
"create component",
|
|
64
|
+
"create package",
|
|
65
|
+
"create application",
|
|
66
|
+
"create domain",
|
|
67
|
+
"create route",
|
|
68
|
+
"create wrapper",
|
|
69
|
+
"setup",
|
|
70
|
+
"setup lsp",
|
|
71
|
+
"setup mcp",
|
|
72
|
+
"setup completions",
|
|
73
|
+
"setup skills",
|
|
74
|
+
"modifier list",
|
|
75
|
+
"modifier lookup",
|
|
76
|
+
"modifier sample",
|
|
77
|
+
...(TOKEN_READ_SURFACE_ENABLED ? ["token list", "token lookup"] : []),
|
|
78
|
+
"tokens add-config",
|
|
79
|
+
...(TOKEN_READ_SURFACE_ENABLED ? ["token sample"] : []),
|
|
80
|
+
"block list",
|
|
81
|
+
"block lookup",
|
|
82
|
+
"block sample",
|
|
83
|
+
"ontology list",
|
|
84
|
+
"ontology show",
|
|
85
|
+
"graph query",
|
|
86
|
+
"graph inspect",
|
|
87
|
+
"graphql build",
|
|
88
|
+
"graphql check",
|
|
89
|
+
"graphql serve",
|
|
90
|
+
"skill list",
|
|
91
|
+
"skill lookup",
|
|
92
|
+
"doctor",
|
|
93
|
+
"info",
|
|
94
|
+
"upgrade",
|
|
95
|
+
"llm",
|
|
96
|
+
"capabilities",
|
|
97
|
+
]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("serves `tier list` from the bundled pack, not a built-in", () => {
|
|
101
|
+
const builtInPaths = builtInCommands(makeCtx()).map((c) =>
|
|
102
|
+
c.path.join(" "),
|
|
103
|
+
);
|
|
104
|
+
const allPaths = collectCommands(makeCtx()).map((c) => c.path.join(" "));
|
|
105
|
+
|
|
106
|
+
expect(builtInPaths).not.toContain("tier list");
|
|
107
|
+
expect(allPaths).toContain("tier list");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("serves the whole `standard` noun from the bundled pack", () => {
|
|
111
|
+
const builtInPaths = builtInCommands(makeCtx()).map((c) =>
|
|
112
|
+
c.path.join(" "),
|
|
113
|
+
);
|
|
114
|
+
const allPaths = collectCommands(makeCtx()).map((c) => c.path.join(" "));
|
|
115
|
+
|
|
116
|
+
const standardVerbs = [
|
|
117
|
+
"standard list",
|
|
118
|
+
"standard lookup",
|
|
119
|
+
"standard categories",
|
|
120
|
+
"standard sample",
|
|
121
|
+
];
|
|
122
|
+
for (const path of standardVerbs) {
|
|
123
|
+
expect(builtInPaths).not.toContain(path);
|
|
124
|
+
expect(allPaths).toContain(path);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Cross-surface skew invariant (FIX 2 / R4-F1): the CLI and MCP surfaces both
|
|
130
|
+
// derive their reserved map through the single shared deriveReservedVerbs, so
|
|
131
|
+
// they MUST agree on every leaf read (noun, verb) reservation. If they drifted,
|
|
132
|
+
// a pack migrating a `list`/`lookup` verb could be admitted on one surface and
|
|
133
|
+
// blocked on the other. Operational nouns legitimately differ (graphql/setup/
|
|
134
|
+
// upgrade are CLI-only), so the invariant is scoped to the read verbs that
|
|
135
|
+
// packs actually emit.
|
|
136
|
+
describe("cross-surface reserved-verb parity", () => {
|
|
137
|
+
const READ_VERBS = ["list", "lookup"] as const;
|
|
138
|
+
|
|
139
|
+
it("CLI and MCP reserve the same list/lookup verbs for every leaf read noun", () => {
|
|
140
|
+
// Both surfaces derive reservations from BUILT-INS only (production reserves
|
|
141
|
+
// from built-ins, before appending packs), so a bundled/config/package pack
|
|
142
|
+
// never inflates the reserved map. Using collectCommands here would fold the
|
|
143
|
+
// bundled tier pack into the CLI side and break the symmetry.
|
|
144
|
+
const cliPairs = builtInCommands(makeCtx()).map((command) =>
|
|
145
|
+
nounVerbFromPath(command.path),
|
|
146
|
+
);
|
|
147
|
+
const mcpPairs = allSpecs.map((spec) => nounVerbFromToolName(spec.name));
|
|
148
|
+
|
|
149
|
+
const cliReserved = deriveReservedVerbs(cliPairs);
|
|
150
|
+
const mcpReserved = deriveReservedVerbs(mcpPairs);
|
|
151
|
+
|
|
152
|
+
// FIX 1 on the real CLI surface: operational nouns own no list/lookup, so
|
|
153
|
+
// they are reserved wholesale — a pack emitting `list` stays blocked.
|
|
154
|
+
for (const noun of ["config", "graph", "graphql", "setup", "create"]) {
|
|
155
|
+
expect(isReserved(cliReserved, noun, "list")).toBe(true);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Leaf read nouns: those that own a `list`/`lookup` verb on either surface.
|
|
159
|
+
const readNouns = new Set(
|
|
160
|
+
[...cliPairs, ...mcpPairs]
|
|
161
|
+
.filter(([, verb]) => verb === "list" || verb === "lookup")
|
|
162
|
+
.map(([noun]) => noun),
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// Sanity: the real leaf-migration targets are present, so this asserts
|
|
166
|
+
// something (a silently empty set would make the test vacuous). `tier`
|
|
167
|
+
// and `standard` are no longer here — both were cut over to bundled
|
|
168
|
+
// packs, so they are correctly absent from the built-in reserved
|
|
169
|
+
// surface on both sides. The token noun only owns read verbs while its
|
|
170
|
+
// feature flag is on.
|
|
171
|
+
const expectedReadNouns = ["block", "modifier"];
|
|
172
|
+
if (TOKEN_READ_SURFACE_ENABLED) expectedReadNouns.push("token");
|
|
173
|
+
for (const noun of expectedReadNouns) {
|
|
174
|
+
expect(readNouns.has(noun)).toBe(true);
|
|
175
|
+
}
|
|
176
|
+
expect(readNouns.has("standard")).toBe(false);
|
|
177
|
+
|
|
178
|
+
for (const noun of readNouns) {
|
|
179
|
+
for (const verb of READ_VERBS) {
|
|
180
|
+
expect(
|
|
181
|
+
isReserved(cliReserved, noun, verb),
|
|
182
|
+
`CLI/MCP disagree on ${noun} ${verb}`,
|
|
183
|
+
).toBe(isReserved(mcpReserved, noun, verb));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
});
|
|
37
187
|
});
|
|
@@ -14,30 +14,27 @@ import { commands as modifierCommands } from "../domains/modifier/index.js";
|
|
|
14
14
|
import { commands as ontologyCommands } from "../domains/ontology/index.js";
|
|
15
15
|
import { commands as setupCommands } from "../domains/setup/index.js";
|
|
16
16
|
import type { PragmaContext } from "../domains/shared/context.js";
|
|
17
|
+
import {
|
|
18
|
+
compilePackCommands,
|
|
19
|
+
deriveReservedVerbs,
|
|
20
|
+
nounVerbFromPath,
|
|
21
|
+
} from "../domains/shared/stories/pack/index.js";
|
|
17
22
|
import { commands as skillCommands } from "../domains/skill/index.js";
|
|
18
|
-
import { commands as standardCommands } from "../domains/standard/index.js";
|
|
19
|
-
import { commands as tierCommands } from "../domains/tier/index.js";
|
|
20
23
|
import { commands as tokenCommands } from "../domains/token/index.js";
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* Extracted from runCli so the completions server can import
|
|
26
|
-
* the command list independently without running the full CLI pipeline.
|
|
26
|
+
* The built-in (hand-written domain) command surface, in emission order.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* Excludes story-pack commands (bundled, config, or package). Exported so the
|
|
29
|
+
* reserved-verb derivation and its tests share the exact input production uses
|
|
30
|
+
* — the reserved map is built from built-ins only, never from packs.
|
|
30
31
|
*/
|
|
31
|
-
export
|
|
32
|
-
ctx: PragmaContext,
|
|
33
|
-
): CommandDefinition[] {
|
|
32
|
+
export function builtInCommands(ctx: PragmaContext): CommandDefinition[] {
|
|
34
33
|
return [
|
|
35
34
|
...configCommands(ctx),
|
|
36
35
|
...createCommands(),
|
|
37
36
|
...setupCommands(),
|
|
38
|
-
...standardCommands(ctx),
|
|
39
37
|
...modifierCommands(ctx),
|
|
40
|
-
...tierCommands(ctx),
|
|
41
38
|
...tokenCommands(ctx),
|
|
42
39
|
...blockCommands(ctx),
|
|
43
40
|
...ontologyCommands(ctx),
|
|
@@ -51,3 +48,28 @@ export default function collectCommands(
|
|
|
51
48
|
buildCapabilitiesCommand(),
|
|
52
49
|
];
|
|
53
50
|
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Collect all CLI command definitions: built-in domains plus story packs.
|
|
54
|
+
*
|
|
55
|
+
* Extracted from runCli so the completions server can import the command list
|
|
56
|
+
* independently without running the full CLI pipeline.
|
|
57
|
+
*
|
|
58
|
+
* Story packs (bundled transitional packs, plus config- and package-declared
|
|
59
|
+
* stories) project onto the same surface. Leaf read nouns reserve only the
|
|
60
|
+
* (noun, verb) pairs they own, so a pack can add a verb no built-in owns and,
|
|
61
|
+
* once a built-in leaf is deleted, its bundled pack takes over the freed noun;
|
|
62
|
+
* operational nouns (config, graph, setup, …) stay reserved wholesale.
|
|
63
|
+
*
|
|
64
|
+
* @param ctx - The pragma context providing store, config, and global flags.
|
|
65
|
+
* @returns The full array of command definitions for all domains.
|
|
66
|
+
*/
|
|
67
|
+
export default function collectCommands(
|
|
68
|
+
ctx: PragmaContext,
|
|
69
|
+
): CommandDefinition[] {
|
|
70
|
+
const builtIn = builtInCommands(ctx);
|
|
71
|
+
const reserved = deriveReservedVerbs(
|
|
72
|
+
builtIn.map((command) => nounVerbFromPath(command.path)),
|
|
73
|
+
);
|
|
74
|
+
return [...builtIn, ...compilePackCommands(ctx, reserved)];
|
|
75
|
+
}
|
|
@@ -36,9 +36,13 @@ describe("createProgram", () => {
|
|
|
36
36
|
}
|
|
37
37
|
)._events.beforeAllHelp({ command: program, write });
|
|
38
38
|
|
|
39
|
+
// Assert on single-chalk-span strings so the check is robust whether or
|
|
40
|
+
// not color is enabled (CI renders with color; ANSI resets would otherwise
|
|
41
|
+
// split a multi-word phrase like "Usage: pragma").
|
|
39
42
|
expect(write).toHaveBeenCalledWith(
|
|
40
|
-
expect.stringContaining("
|
|
43
|
+
expect.stringContaining("For AI agents"),
|
|
41
44
|
);
|
|
45
|
+
expect(write).toHaveBeenCalledWith(expect.stringContaining("Global flags"));
|
|
42
46
|
});
|
|
43
47
|
|
|
44
48
|
it("uses llm root help when llm is enabled", async () => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type CommandDefinition,
|
|
3
3
|
detectRenderMode,
|
|
4
|
-
formatHelp,
|
|
5
4
|
formatLlmHelp,
|
|
6
5
|
type HandleResultOptions,
|
|
7
6
|
registerAll,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
import { Command } from "commander";
|
|
10
9
|
import { PROGRAM_DESCRIPTION, PROGRAM_NAME, VERSION } from "../constants.js";
|
|
11
10
|
import type { PragmaContext } from "../domains/shared/context.js";
|
|
11
|
+
import formatRootHelp from "./rootHelp.js";
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Build and configure the top-level Commander program.
|
|
@@ -57,7 +57,7 @@ export default function createProgram(
|
|
|
57
57
|
if (ctx.globalFlags.llm) {
|
|
58
58
|
return formatLlmHelp(PROGRAM_NAME, commands);
|
|
59
59
|
}
|
|
60
|
-
return
|
|
60
|
+
return formatRootHelp(PROGRAM_NAME, PROGRAM_DESCRIPTION, commands);
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
program.helpOption("-h, --help", "Show help");
|