@canonical/pragma-cli 0.38.0 → 0.42.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 +3 -3
- package/dist/package.json +16 -16
- package/dist/pragma.conf.js +273 -176
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/capabilities/capabilities/capabilities.verb.js +2 -0
- package/dist/src/capabilities/capabilities/capabilities.verb.js.map +1 -1
- package/dist/src/capabilities/capabilities/catalog.js +47 -51
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
- package/dist/src/capabilities/capabilities/index.js +2 -0
- package/dist/src/capabilities/capabilities/index.js.map +1 -1
- package/dist/src/capabilities/capabilities/types.js +5 -5
- package/dist/src/capabilities/colophon/colophon.render.js +7 -4
- package/dist/src/capabilities/colophon/colophon.render.js.map +1 -1
- package/dist/src/capabilities/colophon/colophon.verb.js +1 -0
- package/dist/src/capabilities/colophon/colophon.verb.js.map +1 -1
- package/dist/src/capabilities/colophon/markdownTerminal.js.map +1 -1
- package/dist/src/capabilities/config/get.verb.js +2 -0
- package/dist/src/capabilities/config/get.verb.js.map +1 -1
- package/dist/src/capabilities/config/runField.js +2 -2
- package/dist/src/capabilities/config/runField.js.map +1 -1
- package/dist/src/capabilities/config/set.verb.js +2 -0
- package/dist/src/capabilities/config/set.verb.js.map +1 -1
- package/dist/src/capabilities/config/show.render.js.map +1 -1
- package/dist/src/capabilities/config/show.verb.js +1 -0
- package/dist/src/capabilities/config/show.verb.js.map +1 -1
- package/dist/src/capabilities/config/unset.verb.js +2 -0
- package/dist/src/capabilities/config/unset.verb.js.map +1 -1
- package/dist/src/capabilities/create/constants.js +8 -5
- package/dist/src/capabilities/create/constants.js.map +1 -1
- package/dist/src/capabilities/create/create.render.js.map +1 -1
- package/dist/src/capabilities/create/create.verb.js +36 -7
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/create/createSurface.generated.js +22 -0
- package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
- package/dist/src/capabilities/create/index.js +1 -1
- package/dist/src/capabilities/create/pickGenerator.js +1 -0
- package/dist/src/capabilities/create/pickGenerator.js.map +1 -1
- package/dist/src/capabilities/distribution.js +3 -1
- package/dist/src/capabilities/distribution.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +10 -2
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
- package/dist/src/capabilities/doctor/doctor.verb.js +2 -0
- package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -1
- package/dist/src/capabilities/graph/connect.verb.js +2 -0
- package/dist/src/capabilities/graph/connect.verb.js.map +1 -1
- package/dist/src/capabilities/graph/inspect.render.js +7 -1
- package/dist/src/capabilities/graph/inspect.render.js.map +1 -1
- package/dist/src/capabilities/graph/inspect.verb.js +2 -0
- package/dist/src/capabilities/graph/inspect.verb.js.map +1 -1
- package/dist/src/capabilities/graph/query.render.js +37 -5
- package/dist/src/capabilities/graph/query.render.js.map +1 -1
- package/dist/src/capabilities/graph/query.verb.js +2 -0
- package/dist/src/capabilities/graph/query.verb.js.map +1 -1
- package/dist/src/capabilities/graph/queryText.js +28 -0
- package/dist/src/capabilities/graph/queryText.js.map +1 -1
- package/dist/src/capabilities/graph/runConnect.js +3 -3
- package/dist/src/capabilities/graph/runConnect.js.map +1 -1
- package/dist/src/capabilities/graph/runQuery.js +8 -6
- package/dist/src/capabilities/graph/runQuery.js.map +1 -1
- package/dist/src/capabilities/info/info.verb.js +2 -0
- package/dist/src/capabilities/info/info.verb.js.map +1 -1
- package/dist/src/capabilities/meta/mcp.verb.js +1 -0
- package/dist/src/capabilities/meta/mcp.verb.js.map +1 -1
- package/dist/src/capabilities/ontology/verbs.js +7 -10
- package/dist/src/capabilities/ontology/verbs.js.map +1 -1
- package/dist/src/capabilities/prompt/verbs.js +5 -4
- package/dist/src/capabilities/prompt/verbs.js.map +1 -1
- package/dist/src/capabilities/resources/provider.js +6 -3
- package/dist/src/capabilities/resources/provider.js.map +1 -1
- package/dist/src/capabilities/setup/operations/writability.js.map +1 -1
- package/dist/src/capabilities/setup/plan.render.js.map +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +13 -5
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/shared/calls.js +16 -0
- package/dist/src/capabilities/shared/calls.js.map +1 -0
- package/dist/src/capabilities/shared/packageManager.js.map +1 -1
- package/dist/src/capabilities/skill/discover.js.map +1 -1
- package/dist/src/capabilities/skill/render.js +7 -5
- package/dist/src/capabilities/skill/render.js.map +1 -1
- package/dist/src/capabilities/skill/verbs.js +5 -4
- package/dist/src/capabilities/skill/verbs.js.map +1 -1
- package/dist/src/capabilities/sources/collectStatus.js +6 -1
- package/dist/src/capabilities/sources/collectStatus.js.map +1 -1
- package/dist/src/capabilities/sources/index.js +4 -3
- package/dist/src/capabilities/sources/index.js.map +1 -1
- package/dist/src/capabilities/sources/reset.render.js +37 -0
- package/dist/src/capabilities/sources/reset.render.js.map +1 -0
- package/dist/src/capabilities/sources/reset.verb.js +51 -0
- package/dist/src/capabilities/sources/reset.verb.js.map +1 -0
- package/dist/src/capabilities/sources/runReset.js +59 -0
- package/dist/src/capabilities/sources/runReset.js.map +1 -0
- package/dist/src/capabilities/sources/runUpdate.js +7 -6
- package/dist/src/capabilities/sources/runUpdate.js.map +1 -1
- package/dist/src/capabilities/sources/status.render.js +24 -8
- package/dist/src/capabilities/sources/status.render.js.map +1 -1
- package/dist/src/capabilities/sources/status.verb.js +1 -0
- package/dist/src/capabilities/sources/status.verb.js.map +1 -1
- package/dist/src/capabilities/sources/update.verb.js +2 -0
- package/dist/src/capabilities/sources/update.verb.js.map +1 -1
- package/dist/src/capabilities/upgrade/upgrade.verb.js +1 -0
- package/dist/src/capabilities/upgrade/upgrade.verb.js.map +1 -1
- package/dist/src/capabilities/version/version.verb.js +1 -0
- package/dist/src/capabilities/version/version.verb.js.map +1 -1
- package/dist/src/constants.js +4 -3
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/completion/complete.js.map +1 -1
- package/dist/src/kernel/completion/emitScripts.js.map +1 -1
- package/dist/src/kernel/completion/parse.js.map +1 -1
- package/dist/src/kernel/completion/rank.js.map +1 -1
- package/dist/src/kernel/completion/resolve.js.map +1 -1
- package/dist/src/kernel/config/readConfig.js.map +1 -1
- package/dist/src/kernel/error/PragmaError.js.map +1 -1
- package/dist/src/kernel/error/index.js +1 -1
- package/dist/src/kernel/error/index.js.map +1 -1
- package/dist/src/kernel/error/recovery.js +24 -42
- package/dist/src/kernel/error/recovery.js.map +1 -1
- package/dist/src/kernel/packs/collect.js +123 -9
- package/dist/src/kernel/packs/collect.js.map +1 -1
- package/dist/src/kernel/packs/compile.js +74 -15
- package/dist/src/kernel/packs/compile.js.map +1 -1
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js +3 -3
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js.map +1 -1
- package/dist/src/kernel/packs/iri.js +2 -4
- package/dist/src/kernel/packs/iri.js.map +1 -1
- package/dist/src/kernel/packs/renderPack.js +90 -50
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +202 -90
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +89 -30
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +66 -12
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/buildListQuery.js +80 -13
- package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +41 -13
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/filterValues.js +32 -23
- package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -1
- package/dist/src/kernel/packs/sparql/runSelect.js +3 -5
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
- package/dist/src/kernel/packs/storyRules.js +31 -4
- package/dist/src/kernel/packs/storyRules.js.map +1 -1
- package/dist/src/kernel/packs/tierScope.js +3 -3
- package/dist/src/kernel/packs/tierScope.js.map +1 -1
- package/dist/src/kernel/packs/types.js +4 -0
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +4 -0
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +32 -8
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/globalFlags.js.map +1 -1
- package/dist/src/kernel/project/cli/suggestNames.js +44 -1
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
- package/dist/src/kernel/project/cli/verbHelp.js +17 -18
- package/dist/src/kernel/project/cli/verbHelp.js.map +1 -1
- package/dist/src/kernel/project/mcp/buildServer.js +11 -4
- package/dist/src/kernel/project/mcp/buildServer.js.map +1 -1
- package/dist/src/kernel/project/mcp/envelope.js +3 -2
- package/dist/src/kernel/project/mcp/envelope.js.map +1 -1
- package/dist/src/kernel/project/mcp/instructions.js +101 -31
- package/dist/src/kernel/project/mcp/instructions.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +59 -23
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/envelope.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +3 -3
- package/dist/src/kernel/render/renderers.js.map +1 -1
- package/dist/src/kernel/render/turtle.js +21 -4
- package/dist/src/kernel/render/turtle.js.map +1 -1
- package/dist/src/kernel/runtime/boot.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/build.js +54 -1
- package/dist/src/kernel/runtime/graphpack/build.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/manifest.js +14 -0
- package/dist/src/kernel/runtime/graphpack/manifest.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +3 -5
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/schemas.js +1 -0
- package/dist/src/kernel/runtime/graphpack/schemas.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +8 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/packVersion.js +75 -0
- package/dist/src/kernel/runtime/packVersion.js.map +1 -0
- package/dist/src/kernel/runtime/readEntity.js +43 -4
- package/dist/src/kernel/runtime/readEntity.js.map +1 -1
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
- package/dist/src/kernel/runtime/resolveSources.js +61 -9
- package/dist/src/kernel/runtime/resolveSources.js.map +1 -1
- package/dist/src/kernel/runtime/storeReadiness.js +3 -2
- package/dist/src/kernel/runtime/storeReadiness.js.map +1 -1
- package/dist/src/kernel/spec/call.js +167 -0
- package/dist/src/kernel/spec/call.js.map +1 -0
- package/dist/src/kernel/spec/emitReference.js +9 -13
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/dist/src/kernel/spec/emitSurface.js +8 -1
- package/dist/src/kernel/spec/emitSurface.js.map +1 -1
- package/dist/src/kernel/spec/guidance.js +63 -0
- package/dist/src/kernel/spec/guidance.js.map +1 -0
- package/dist/src/kernel/spec/wireType.js +36 -0
- package/dist/src/kernel/spec/wireType.js.map +1 -0
- package/package.json +16 -16
- package/pragma.conf.ts +294 -177
- package/src/capabilities/block.parity.test.ts +1 -1
- package/src/capabilities/callRule.test.ts +147 -0
- package/src/capabilities/capabilities/capabilities.test.ts +47 -19
- package/src/capabilities/capabilities/capabilities.verb.ts +2 -0
- package/src/capabilities/capabilities/catalog.ts +60 -55
- package/src/capabilities/capabilities/index.ts +2 -0
- package/src/capabilities/capabilities/types.ts +16 -19
- package/src/capabilities/colophon/colophon.render.ts +9 -5
- package/src/capabilities/colophon/colophon.verb.ts +1 -0
- package/src/capabilities/config/get.verb.ts +2 -0
- package/src/capabilities/config/runField.ts +3 -3
- package/src/capabilities/config/set.verb.ts +3 -0
- package/src/capabilities/config/show.verb.ts +2 -0
- package/src/capabilities/config/unset.verb.ts +2 -0
- package/src/capabilities/create/constants.ts +8 -5
- package/src/capabilities/create/create.mcp.test.ts +173 -1
- package/src/capabilities/create/create.test.ts +4 -2
- package/src/capabilities/create/create.verb.ts +45 -3
- package/src/capabilities/create/createGrammar.test.ts +41 -5
- package/src/capabilities/create/createSurface.generated.ts +22 -0
- package/src/capabilities/create/crossCli.subprocess.test.ts +53 -14
- package/src/capabilities/create/index.ts +1 -1
- package/src/capabilities/create/pickGenerator.ts +1 -0
- package/src/capabilities/create/shippedCreate.subprocess.test.ts +28 -7
- package/src/capabilities/distribution.test.ts +6 -3
- package/src/capabilities/distribution.ts +6 -0
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +14 -2
- package/src/capabilities/doctor/doctor.test.ts +38 -1
- package/src/capabilities/doctor/doctor.verb.ts +2 -0
- package/src/capabilities/emptyRecovery.test.ts +5 -0
- package/src/capabilities/graph/connect.verb.ts +2 -0
- package/src/capabilities/graph/inspect.render.ts +9 -1
- package/src/capabilities/graph/inspect.test.ts +73 -0
- package/src/capabilities/graph/inspect.verb.ts +2 -0
- package/src/capabilities/graph/query.render.test.ts +35 -0
- package/src/capabilities/graph/query.render.ts +45 -7
- package/src/capabilities/graph/query.shipped.exec.test.ts +44 -0
- package/src/capabilities/graph/query.verb.ts +2 -0
- package/src/capabilities/graph/queryText.test.ts +55 -1
- package/src/capabilities/graph/queryText.ts +47 -0
- package/src/capabilities/graph/runConnect.ts +4 -5
- package/src/capabilities/graph/runQuery.ts +23 -9
- package/src/capabilities/info/info.verb.ts +2 -0
- package/src/capabilities/links.shipped.exec.test.ts +398 -0
- package/src/capabilities/listBudget.shipped.exec.test.ts +2 -2
- package/src/capabilities/listLookup.shipped.exec.test.ts +122 -13
- package/src/capabilities/listQuery.shipped.exec.test.ts +39 -16
- package/src/capabilities/lookupBudget.shipped.exec.test.ts +208 -0
- package/src/capabilities/meta/mcp.verb.ts +2 -0
- package/src/capabilities/ontology/ontology.test.ts +24 -0
- package/src/capabilities/ontology/verbs.ts +16 -12
- package/src/capabilities/prompt/verbs.ts +10 -4
- package/src/capabilities/resources/provider.ts +7 -3
- package/src/capabilities/resources/resources.test.ts +2 -1
- package/src/capabilities/setup/setup.verb.ts +16 -0
- package/src/capabilities/shared/calls.ts +20 -0
- package/src/capabilities/skill/render.ts +9 -6
- package/src/capabilities/skill/verbs.ts +8 -4
- package/src/capabilities/sources/collectStatus.ts +6 -1
- package/src/capabilities/sources/index.ts +4 -3
- package/src/capabilities/sources/reset.render.test.ts +33 -0
- package/src/capabilities/sources/reset.render.ts +43 -0
- package/src/capabilities/sources/reset.verb.ts +59 -0
- package/src/capabilities/sources/runReset.ts +65 -0
- package/src/capabilities/sources/runUpdate.ts +12 -11
- package/src/capabilities/sources/sources.test.ts +158 -3
- package/src/capabilities/sources/status.render.test.ts +63 -1
- package/src/capabilities/sources/status.render.ts +25 -8
- package/src/capabilities/sources/status.verb.ts +2 -0
- package/src/capabilities/sources/types.ts +26 -0
- package/src/capabilities/sources/update.verb.ts +3 -0
- package/src/capabilities/surface.test.ts +29 -4
- package/src/capabilities/token.parity.test.ts +3 -2
- package/src/capabilities/tokenGraph.shipped.exec.test.ts +14 -2
- package/src/capabilities/upgrade/upgrade.verb.ts +1 -0
- package/src/capabilities/variable.parity.test.ts +2 -1
- package/src/capabilities/version/version.verb.ts +1 -0
- package/src/capabilities/wireContract.test.ts +110 -0
- package/src/constants.ts +4 -3
- package/src/kernel/completion/shellDrive.test.ts +2 -2
- package/src/kernel/copy.test.ts +1 -1
- package/src/kernel/error/PragmaError.test.ts +7 -3
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +52 -18
- package/src/kernel/error/recovery.ts +25 -46
- package/src/kernel/error/types.ts +1 -1
- package/src/kernel/packs/collect.test.ts +79 -0
- package/src/kernel/packs/collect.ts +151 -11
- package/src/kernel/packs/compile.test.ts +107 -10
- package/src/kernel/packs/compile.ts +100 -11
- package/src/kernel/packs/filteredEmpty.test.ts +22 -5
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +5 -6
- package/src/kernel/packs/graphqlSource.test.ts +42 -0
- package/src/kernel/packs/iri.ts +5 -4
- package/src/kernel/packs/listNotice.test.ts +1 -1
- package/src/kernel/packs/nounLink.test.ts +385 -0
- package/src/kernel/packs/renderPack.ts +137 -57
- package/src/kernel/packs/resolveEntity.test.ts +170 -1
- package/src/kernel/packs/resolveEntity.ts +281 -101
- package/src/kernel/packs/runBodies.ts +133 -31
- package/src/kernel/packs/schema.ts +77 -12
- package/src/kernel/packs/sparql/buildListQuery.test.ts +78 -1
- package/src/kernel/packs/sparql/buildListQuery.ts +106 -16
- package/src/kernel/packs/sparql/buildLookupQuery.ts +44 -13
- package/src/kernel/packs/sparql/filterValues.test.ts +36 -4
- package/src/kernel/packs/sparql/filterValues.ts +50 -31
- package/src/kernel/packs/sparql/runSelect.ts +4 -6
- package/src/kernel/packs/storyRules.ts +37 -4
- package/src/kernel/packs/tierScope.test.ts +120 -6
- package/src/kernel/packs/tierScope.ts +5 -7
- package/src/kernel/packs/toolDescription.test.ts +59 -74
- package/src/kernel/packs/types.ts +93 -11
- package/src/kernel/project/cli/buildProgram.ts +4 -0
- package/src/kernel/project/cli/dispatch.ts +34 -8
- package/src/kernel/project/cli/suggest.test.ts +77 -0
- package/src/kernel/project/cli/suggestNames.ts +47 -1
- package/src/kernel/project/cli/verbHelp.ts +16 -19
- package/src/kernel/project/mcp/buildServer.ts +15 -4
- package/src/kernel/project/mcp/envelope.ts +3 -2
- package/src/kernel/project/mcp/instructions.ts +123 -35
- package/src/kernel/project/mcp/prompts/prompts.test.ts +136 -20
- package/src/kernel/project/mcp/registerVerb.test.ts +28 -0
- package/src/kernel/project/mcp/registerVerb.ts +67 -29
- package/src/kernel/render/__snapshots__/renderers.test.ts.snap +1 -1
- package/src/kernel/render/renderers.test.ts +2 -2
- package/src/kernel/render/renderers.ts +3 -3
- package/src/kernel/render/turtle.ts +24 -4
- package/src/kernel/runtime/graphpack/build.ts +58 -1
- package/src/kernel/runtime/graphpack/graphpack.test.ts +20 -0
- package/src/kernel/runtime/graphpack/manifest.ts +15 -0
- package/src/kernel/runtime/graphpack/read.ts +4 -6
- package/src/kernel/runtime/graphpack/schemas.ts +1 -0
- package/src/kernel/runtime/graphpack/types.ts +13 -0
- package/src/kernel/runtime/loadSession.ts +8 -1
- package/src/kernel/runtime/packVersion.test.ts +61 -0
- package/src/kernel/runtime/packVersion.ts +84 -0
- package/src/kernel/runtime/readEntity.ts +61 -6
- package/src/kernel/runtime/resolveSources.test.ts +90 -7
- package/src/kernel/runtime/resolveSources.ts +91 -10
- package/src/kernel/runtime/storeReadiness.ts +4 -4
- package/src/kernel/runtime/types.ts +12 -0
- package/src/kernel/spec/call.test.ts +95 -0
- package/src/kernel/spec/call.ts +186 -0
- package/src/kernel/spec/emitReference.ts +9 -13
- package/src/kernel/spec/emitSurface.ts +9 -1
- package/src/kernel/spec/guidance.test.ts +49 -0
- package/src/kernel/spec/guidance.ts +68 -0
- package/src/kernel/spec/index.ts +4 -0
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/types.ts +64 -7
- package/src/kernel/spec/wireType.ts +53 -0
- package/src/testing/behavioral/README.md +1 -1
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +2 -1
- package/src/testing/behavioral/journeys.firstInstall.test.ts +72 -2
- package/src/testing/behavioral/parity.test.ts +40 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +1 -1
- package/src/testing/eval/cases/assembly.ts +4 -3
- package/src/testing/eval/cases/stable.ts +2 -3
- package/src/testing/helpers/callSchema.ts +40 -0
- package/src/testing/helpers/parity.ts +35 -2
- package/src/testing/setupCallChecking.ts +30 -0
- package/dist/src/capabilities/capabilities/hints.js +0 -223
- package/dist/src/capabilities/capabilities/hints.js.map +0 -1
- package/src/capabilities/capabilities/hints.ts +0 -266
|
@@ -28,9 +28,11 @@ import type { ConfigLayers } from "../config/index.js";
|
|
|
28
28
|
import { PragmaError } from "../error/index.js";
|
|
29
29
|
import type { PackStoryRecord } from "../runtime/graphpack/stories.js";
|
|
30
30
|
import type { CapabilityModule } from "../spec/index.js";
|
|
31
|
-
import { compileStoryModule } from "./compile.js";
|
|
31
|
+
import { compileStoryModule, storyOf } from "./compile.js";
|
|
32
32
|
import { parsePackDefinition } from "./schema.js";
|
|
33
|
-
import
|
|
33
|
+
import { nounsNamed } from "./storyRules.js";
|
|
34
|
+
import type { NounLookups, PackDefinition, PackEntry } from "./types.js";
|
|
35
|
+
import { VERB_PATH_PATTERN } from "./types.js";
|
|
34
36
|
import { assertUniqueVerbs } from "./uniqueness.js";
|
|
35
37
|
|
|
36
38
|
/** One package-declared story that could not be used, and why. */
|
|
@@ -83,10 +85,14 @@ export function validateStories(
|
|
|
83
85
|
const problems: StoryProblem[] = [];
|
|
84
86
|
for (const record of records) {
|
|
85
87
|
try {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
const migrated = migrateLegacyRecoveries(JSON.parse(record.content));
|
|
89
|
+
for (const hint of migrated.dropped) {
|
|
90
|
+
problems.push({
|
|
91
|
+
source: record.source,
|
|
92
|
+
message: `its story is kept, but its emptyRecovery.cli hint "${hint}" is not a verb path and was dropped; the key is now emptyRecovery.call.`,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const definition = parsePackDefinition(migrated.raw, record.source);
|
|
90
96
|
if (reserved.has(definition.noun)) {
|
|
91
97
|
problems.push({
|
|
92
98
|
source: record.source,
|
|
@@ -112,6 +118,55 @@ export function validateStories(
|
|
|
112
118
|
return { entries: [...byNoun.values()], problems };
|
|
113
119
|
}
|
|
114
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Carry a PACKAGE story written against the old grammar forward.
|
|
123
|
+
*
|
|
124
|
+
* `emptyRecovery.cli: "sources update"` became `emptyRecovery.call: { verb }`. A
|
|
125
|
+
* project's own config gets the hard error that names the change — its author
|
|
126
|
+
* can fix it. A package is third-party data, often already built into a pack on
|
|
127
|
+
* disk, and refusing the key would cost the user the whole noun for the sake of
|
|
128
|
+
* a hint. So the old string becomes a call when it IS a verb path, and
|
|
129
|
+
* otherwise only the hint is dropped, reported once under `doctor`.
|
|
130
|
+
*
|
|
131
|
+
* @param raw - The parsed story JSON (untrusted; returned unchanged when it
|
|
132
|
+
* carries no legacy key).
|
|
133
|
+
* @returns The story to validate, and the legacy hints that could not be kept.
|
|
134
|
+
*/
|
|
135
|
+
export function migrateLegacyRecoveries(raw: unknown): {
|
|
136
|
+
raw: unknown;
|
|
137
|
+
dropped: string[];
|
|
138
|
+
} {
|
|
139
|
+
const dropped: string[] = [];
|
|
140
|
+
const migrateHalf = (half: unknown): unknown => {
|
|
141
|
+
const recovery = (
|
|
142
|
+
half as { emptyRecovery?: Record<string, unknown> } | null
|
|
143
|
+
)?.emptyRecovery;
|
|
144
|
+
if (typeof recovery?.cli !== "string") return half;
|
|
145
|
+
const { cli, ...rest } = recovery;
|
|
146
|
+
const keep = VERB_PATH_PATTERN.test(cli);
|
|
147
|
+
if (!keep) dropped.push(cli);
|
|
148
|
+
return {
|
|
149
|
+
...(half as object),
|
|
150
|
+
emptyRecovery:
|
|
151
|
+
keep && rest.call === undefined
|
|
152
|
+
? { ...rest, call: { verb: cli } }
|
|
153
|
+
: rest,
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
if (typeof raw !== "object" || raw === null) return { raw, dropped };
|
|
157
|
+
const story = raw as { list?: unknown; verbs?: unknown };
|
|
158
|
+
return {
|
|
159
|
+
raw: {
|
|
160
|
+
...story,
|
|
161
|
+
...(story.list === undefined ? {} : { list: migrateHalf(story.list) }),
|
|
162
|
+
...(Array.isArray(story.verbs)
|
|
163
|
+
? { verbs: story.verbs.map(migrateHalf) }
|
|
164
|
+
: {}),
|
|
165
|
+
},
|
|
166
|
+
dropped,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
115
170
|
/**
|
|
116
171
|
* The PROJECT's config-declared stories, weakest tier first.
|
|
117
172
|
*
|
|
@@ -147,8 +202,8 @@ function projectStoryTiers(layers: ConfigLayers): readonly unknown[][] {
|
|
|
147
202
|
* carries (see {@link validateStories}); weaker than either config tier.
|
|
148
203
|
* @returns The effective modules, uniqueness-checked.
|
|
149
204
|
* @throws PragmaError CONFIG_ERROR on an invalid CONFIG story, a config story
|
|
150
|
-
* claiming an authored non-story noun,
|
|
151
|
-
* tier. Package stories were already screened and never throw here.
|
|
205
|
+
* claiming an authored non-story noun, a duplicate noun within one config
|
|
206
|
+
* tier, or a config or shipped story naming a noun no story declares. Package stories were already screened and never throw here.
|
|
152
207
|
*/
|
|
153
208
|
export function assembleEffectiveModules(
|
|
154
209
|
staticModules: readonly CapabilityModule[],
|
|
@@ -171,6 +226,19 @@ export function assembleEffectiveModules(
|
|
|
171
226
|
// Keyed by noun so the stronger tier REPLACES the weaker one — declaring a
|
|
172
227
|
// story both on its pack and at the top level is a refinement, not an error.
|
|
173
228
|
const dynamic = new Map<string, CapabilityModule>();
|
|
229
|
+
// The EFFECTIVE lookup of a noun, for shipped and project stories alike.
|
|
230
|
+
// Read at run time, so it sees every tier whatever order they compile in.
|
|
231
|
+
const nouns: NounLookups = (noun) => {
|
|
232
|
+
const module =
|
|
233
|
+
dynamic.get(noun) ?? staticModules.find((m) => m.name === noun);
|
|
234
|
+
const story = module && storyOf(module);
|
|
235
|
+
if (story && !story.definition.lookup) {
|
|
236
|
+
throw PragmaError.configError(
|
|
237
|
+
`The "${noun}" story in ${story.source.label} declares no lookup, so a filter that takes a ${noun} cannot resolve its value. Add a lookup to that story.`,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
return story?.definition.lookup;
|
|
241
|
+
};
|
|
174
242
|
for (const entry of packageStories) {
|
|
175
243
|
dynamic.set(
|
|
176
244
|
entry.definition.noun,
|
|
@@ -178,6 +246,7 @@ export function assembleEffectiveModules(
|
|
|
178
246
|
entry.definition,
|
|
179
247
|
{ label: entry.source, origin: "package" },
|
|
180
248
|
prefixes,
|
|
249
|
+
nouns,
|
|
181
250
|
),
|
|
182
251
|
);
|
|
183
252
|
}
|
|
@@ -205,6 +274,7 @@ export function assembleEffectiveModules(
|
|
|
205
274
|
definition,
|
|
206
275
|
{ label: "config", origin: "config" },
|
|
207
276
|
prefixes,
|
|
277
|
+
nouns,
|
|
208
278
|
),
|
|
209
279
|
);
|
|
210
280
|
}
|
|
@@ -212,12 +282,79 @@ export function assembleEffectiveModules(
|
|
|
212
282
|
|
|
213
283
|
// Drop the static module for any noun a config story overrides, then append
|
|
214
284
|
// the dynamic modules.
|
|
215
|
-
const kept = staticModules
|
|
285
|
+
const kept = staticModules
|
|
286
|
+
.filter((module) => !dynamic.has(module.name))
|
|
287
|
+
// Recompiled so a shipped filter naming an overridden noun resolves
|
|
288
|
+
// through the project's lookup, as the project's own stories do.
|
|
289
|
+
.map((module) => {
|
|
290
|
+
const story = storyOf(module);
|
|
291
|
+
return story
|
|
292
|
+
? compileStoryModule(
|
|
293
|
+
story.definition,
|
|
294
|
+
story.source,
|
|
295
|
+
story.prefixes,
|
|
296
|
+
nouns,
|
|
297
|
+
)
|
|
298
|
+
: module;
|
|
299
|
+
});
|
|
216
300
|
const effective = [...kept, ...dynamic.values()];
|
|
301
|
+
// A noun some story declares without a lookup is refused when a filter on it
|
|
302
|
+
// is used, not here: only a noun NO story declares is a declaration error.
|
|
303
|
+
// Package stories never throw; {@link screenPackageStories} drops them.
|
|
304
|
+
for (const module of effective) {
|
|
305
|
+
const story = storyOf(module);
|
|
306
|
+
const unknown =
|
|
307
|
+
story && story.source.origin !== "package"
|
|
308
|
+
? undeclaredNoun(story.definition, effective)
|
|
309
|
+
: undefined;
|
|
310
|
+
if (story && unknown) {
|
|
311
|
+
throw PragmaError.configError(
|
|
312
|
+
`Invalid story in ${story.source.label}: "${module.name}" names the noun "${unknown}", and no story declares it.`,
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
217
316
|
assertUniqueVerbs(effective.flatMap((module) => [...module.verbs]));
|
|
218
317
|
return effective;
|
|
219
318
|
}
|
|
220
319
|
|
|
320
|
+
/** The first noun a story names that no effective story declares. */
|
|
321
|
+
function undeclaredNoun(
|
|
322
|
+
definition: PackDefinition,
|
|
323
|
+
effective: readonly CapabilityModule[],
|
|
324
|
+
): string | undefined {
|
|
325
|
+
return nounsNamed(definition).find(
|
|
326
|
+
(noun) => !effective.some((m) => m.name === noun && storyOf(m)),
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Drop each PACKAGE story naming a noun no effective story declares, reporting
|
|
332
|
+
* it — judged over the assembled set, so the order of declaration is nothing.
|
|
333
|
+
*
|
|
334
|
+
* @param effective - The assembled modules.
|
|
335
|
+
* @returns The modules kept, and one problem per story dropped.
|
|
336
|
+
*/
|
|
337
|
+
export function screenPackageStories(effective: readonly CapabilityModule[]): {
|
|
338
|
+
readonly modules: readonly CapabilityModule[];
|
|
339
|
+
readonly problems: readonly StoryProblem[];
|
|
340
|
+
} {
|
|
341
|
+
const problems: StoryProblem[] = [];
|
|
342
|
+
const modules = effective.filter((module) => {
|
|
343
|
+
const story = storyOf(module);
|
|
344
|
+
const unknown =
|
|
345
|
+
story?.source.origin === "package"
|
|
346
|
+
? undeclaredNoun(story.definition, effective)
|
|
347
|
+
: undefined;
|
|
348
|
+
if (!story || unknown === undefined) return true;
|
|
349
|
+
problems.push({
|
|
350
|
+
source: story.source.label,
|
|
351
|
+
message: `it names the noun "${unknown}", and no story declares it.`,
|
|
352
|
+
});
|
|
353
|
+
return false;
|
|
354
|
+
});
|
|
355
|
+
return { modules: problems.length === 0 ? effective : modules, problems };
|
|
356
|
+
}
|
|
357
|
+
|
|
221
358
|
/**
|
|
222
359
|
* Load the effective modules for a real invocation: read the layered config and
|
|
223
360
|
* the answering pack's carried stories, and merge both into the static
|
|
@@ -252,8 +389,11 @@ export async function loadEffectiveModules(
|
|
|
252
389
|
activeStories(resolveSources(layers, cwd)),
|
|
253
390
|
staticModules,
|
|
254
391
|
);
|
|
392
|
+
const screened = screenPackageStories(
|
|
393
|
+
assembleEffectiveModules(staticModules, layers, entries),
|
|
394
|
+
);
|
|
255
395
|
return {
|
|
256
|
-
modules:
|
|
257
|
-
problems,
|
|
396
|
+
modules: screened.modules,
|
|
397
|
+
problems: [...problems, ...screened.problems],
|
|
258
398
|
};
|
|
259
399
|
}
|
|
@@ -12,6 +12,7 @@ import { RECOVERY_CLI_PREFIX } from "../../constants.js";
|
|
|
12
12
|
import { buildFixtureRuntime } from "../../testing/helpers/packRuntime.js";
|
|
13
13
|
import { PragmaError } from "../error/index.js";
|
|
14
14
|
import type { PragmaRuntime } from "../runtime/types.js";
|
|
15
|
+
import { declareVerbs } from "../spec/call.js";
|
|
15
16
|
import { kebabCase } from "../spec/emitSurface.js";
|
|
16
17
|
import type { VerbSpec } from "../spec/types.js";
|
|
17
18
|
import { compileListable, compilePack, compileStoryModule } from "./compile.js";
|
|
@@ -362,19 +363,28 @@ describe("the grammar rejects what the compiler cannot build (PROTECTED)", () =>
|
|
|
362
363
|
);
|
|
363
364
|
});
|
|
364
365
|
|
|
365
|
-
it("rejects
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
const
|
|
366
|
+
it("rejects the retired emptyRecovery.cli and a call that is a command line, naming the change", () => {
|
|
367
|
+
// A recovery names a CALL — a verb path and a param bag — and the consuming
|
|
368
|
+
// distribution spells it per surface. Third-party packs are third-party
|
|
369
|
+
// DATA: the old `cli` string gets an error that names the grammar change,
|
|
370
|
+
// and a command line in `verb` would render `pragma pragma sources update`.
|
|
371
|
+
const withRecovery = (recovery: Record<string, unknown>) => ({
|
|
371
372
|
noun: "widget",
|
|
372
|
-
list: { ...listShape, emptyRecovery: { message: "None.",
|
|
373
|
+
list: { ...listShape, emptyRecovery: { message: "None.", ...recovery } },
|
|
373
374
|
});
|
|
374
|
-
expect(parse(
|
|
375
|
-
/
|
|
375
|
+
expect(parse(withRecovery({ cli: "sources update" }))).toThrow(
|
|
376
|
+
/emptyRecovery\.cli is now emptyRecovery\.call/,
|
|
376
377
|
);
|
|
377
|
-
expect(
|
|
378
|
+
expect(
|
|
379
|
+
parse(
|
|
380
|
+
withRecovery({
|
|
381
|
+
call: { verb: `${RECOVERY_CLI_PREFIX}sources update` },
|
|
382
|
+
}),
|
|
383
|
+
),
|
|
384
|
+
).toThrow(/a call names a verb path/);
|
|
385
|
+
expect(
|
|
386
|
+
parse(withRecovery({ call: { verb: "sources update" } })),
|
|
387
|
+
).not.toThrow();
|
|
378
388
|
});
|
|
379
389
|
});
|
|
380
390
|
|
|
@@ -387,6 +397,11 @@ describe("pack compiler — SPARQL fetch path (PROTECTED)", () => {
|
|
|
387
397
|
prefixes: PREFIXES,
|
|
388
398
|
detail: "detailed",
|
|
389
399
|
}));
|
|
400
|
+
// A miss recovers to `widget list`; the suite checks every call it renders
|
|
401
|
+
// against the declared verbs, and a fixture's are not the distribution's.
|
|
402
|
+
declareVerbs(
|
|
403
|
+
compilePack(WIDGET_PACK, distributionSource("bundled:widget"), PREFIXES),
|
|
404
|
+
);
|
|
390
405
|
});
|
|
391
406
|
|
|
392
407
|
afterAll(async () => {
|
|
@@ -563,6 +578,88 @@ describe("pack compiler — SPARQL fetch path (PROTECTED)", () => {
|
|
|
563
578
|
* once, for the name resolve, and the resource listing reads that same
|
|
564
579
|
* declaration. Nothing to keep in sync because there is nothing written twice.
|
|
565
580
|
*/
|
|
581
|
+
describe("a lookup that declares no disclosure can still be asked for less", () => {
|
|
582
|
+
/** The widget lookup with every trace of disclosure removed. */
|
|
583
|
+
const BARE_PACK: PackDefinition = {
|
|
584
|
+
noun: "widget",
|
|
585
|
+
lookup: {
|
|
586
|
+
source: "sparql",
|
|
587
|
+
by: "ex:name",
|
|
588
|
+
type: "ex:Widget",
|
|
589
|
+
fields: [{ name: "description", property: "ex:description" }],
|
|
590
|
+
expand: [
|
|
591
|
+
{
|
|
592
|
+
name: "parts",
|
|
593
|
+
relation: "ex:hasPart",
|
|
594
|
+
select: [{ name: "name", property: "ex:name" }],
|
|
595
|
+
},
|
|
596
|
+
],
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
const lookupVerb = compilePack(
|
|
600
|
+
BARE_PACK,
|
|
601
|
+
distributionSource("bundled:widget"),
|
|
602
|
+
PREFIXES,
|
|
603
|
+
).find((v) => verbKey(v.path) === "widget lookup") as VerbSpec;
|
|
604
|
+
|
|
605
|
+
const lookupAt = async (options: {
|
|
606
|
+
detail?: "summary" | "standard" | "detailed";
|
|
607
|
+
configDetail?: "summary";
|
|
608
|
+
}) => {
|
|
609
|
+
const { rt } = await buildFixtureRuntime({
|
|
610
|
+
ttl: TTL,
|
|
611
|
+
prefixes: PREFIXES,
|
|
612
|
+
...(options.detail ? { detail: options.detail } : {}),
|
|
613
|
+
...(options.configDetail
|
|
614
|
+
? { configDetail: options.configDetail, detailOrigin: "project" }
|
|
615
|
+
: {}),
|
|
616
|
+
});
|
|
617
|
+
try {
|
|
618
|
+
const out = (await lookupVerb.run(
|
|
619
|
+
{ name: ["Button"] },
|
|
620
|
+
rt,
|
|
621
|
+
)) as LookupOutput;
|
|
622
|
+
return out.results.at(0);
|
|
623
|
+
} finally {
|
|
624
|
+
(await rt.store.get()).store.dispose();
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
it("advertises the canonical levels, defaulting to the fullest", () => {
|
|
629
|
+
expect(lookupVerb.disclosure).toEqual({
|
|
630
|
+
levels: ["summary", "standard", "detailed"],
|
|
631
|
+
default: "detailed",
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
it("answers exactly as before when nothing is asked for", async () => {
|
|
636
|
+
expect(await lookupAt({})).toEqual(await lookupAt({ detail: "detailed" }));
|
|
637
|
+
expect((await lookupAt({}))?.parts).toEqual([{ name: "Label" }]);
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
it("is the fields alone at summary, and everything from standard", async () => {
|
|
641
|
+
const summary = await lookupAt({ detail: "summary" });
|
|
642
|
+
expect(summary).toMatchObject({ description: "A button." });
|
|
643
|
+
expect(summary).not.toHaveProperty("parts");
|
|
644
|
+
expect(await lookupAt({ detail: "standard" })).toHaveProperty("parts");
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
it("follows a configured detail, as a declared disclosure always did", async () => {
|
|
648
|
+
expect(await lookupAt({ configDetail: "summary" })).not.toHaveProperty(
|
|
649
|
+
"parts",
|
|
650
|
+
);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
it("leaves a declared disclosure exactly as its author wrote it", () => {
|
|
654
|
+
const declared = compilePack(
|
|
655
|
+
WIDGET_PACK,
|
|
656
|
+
distributionSource("bundled:widget"),
|
|
657
|
+
PREFIXES,
|
|
658
|
+
).find((v) => verbKey(v.path) === "widget lookup");
|
|
659
|
+
expect(declared?.disclosure?.default).toBe("summary");
|
|
660
|
+
});
|
|
661
|
+
});
|
|
662
|
+
|
|
566
663
|
describe("declared listing (derived from the lookup's types)", () => {
|
|
567
664
|
it("derives one collection per declared type, unweighted types at 1", () => {
|
|
568
665
|
expect(
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* facade).
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { BIN_NAME } from "../../constants.js";
|
|
17
|
+
import { BIN_NAME, DETAIL_LEVELS } from "../../constants.js";
|
|
18
18
|
import { PragmaError } from "../error/index.js";
|
|
19
19
|
import { compactUri, DEFAULT_PREFIX_MAP } from "../render/index.js";
|
|
20
20
|
import type { PragmaRuntime } from "../runtime/index.js";
|
|
@@ -42,8 +42,10 @@ import {
|
|
|
42
42
|
import { storyIssues } from "./storyRules.js";
|
|
43
43
|
import {
|
|
44
44
|
EVERY_TIER,
|
|
45
|
+
type NounLookups,
|
|
45
46
|
type PackDefinition,
|
|
46
47
|
type PackFilter,
|
|
48
|
+
type PackGuidance,
|
|
47
49
|
type PackList,
|
|
48
50
|
type PackLookup,
|
|
49
51
|
type PackPage,
|
|
@@ -74,17 +76,22 @@ const READ_CAPABILITY = {
|
|
|
74
76
|
* @param definition - A validated pack definition.
|
|
75
77
|
* @param source - Where the definition came from, for diagnostics.
|
|
76
78
|
* @param prefixes - The merged prefix map used for display compaction.
|
|
79
|
+
* @param nouns - The other stories' lookups, which a filter naming a noun
|
|
80
|
+
* resolves its values through. Read at run time only.
|
|
77
81
|
* @returns The compiled verbs (list, extra verbs, lookup, sample), in order.
|
|
78
82
|
*/
|
|
79
83
|
export function compilePack(
|
|
80
84
|
definition: PackDefinition,
|
|
81
85
|
source: StorySource,
|
|
82
86
|
prefixes: Readonly<Record<string, string>>,
|
|
87
|
+
nouns?: NounLookups,
|
|
83
88
|
): VerbSpec[] {
|
|
84
89
|
const { noun } = definition;
|
|
85
90
|
const verbs: VerbSpec[] = [];
|
|
86
91
|
|
|
87
92
|
const tierScope = definition.tierScope;
|
|
93
|
+
// A story may declare a lookup alone; a miss must not point at a `list` it lacks.
|
|
94
|
+
const hasList = definition.list !== undefined;
|
|
88
95
|
|
|
89
96
|
if (definition.list) {
|
|
90
97
|
verbs.push(
|
|
@@ -93,8 +100,10 @@ export function compilePack(
|
|
|
93
100
|
verb: "list",
|
|
94
101
|
summary: definition.description ?? `List ${noun} entries.`,
|
|
95
102
|
doc: definition.toolDescription,
|
|
103
|
+
...guidanceOf(definition),
|
|
96
104
|
source,
|
|
97
105
|
prefixes,
|
|
106
|
+
...(nouns ? { nouns } : {}),
|
|
98
107
|
...(tierScope ? { tierScope } : {}),
|
|
99
108
|
}),
|
|
100
109
|
);
|
|
@@ -107,19 +116,24 @@ export function compilePack(
|
|
|
107
116
|
verb: verb.verb,
|
|
108
117
|
summary: verb.description ?? `List ${noun} ${verb.verb}.`,
|
|
109
118
|
doc: verb.toolDescription,
|
|
119
|
+
...guidanceOf(verb),
|
|
110
120
|
source,
|
|
111
121
|
prefixes,
|
|
122
|
+
...(nouns ? { nouns } : {}),
|
|
112
123
|
...(tierScope ? { tierScope } : {}),
|
|
113
124
|
}),
|
|
114
125
|
);
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
if (definition.lookup) {
|
|
129
|
+
// Normalised ONCE, here, so the lookup verb, its run body, both fetch lanes
|
|
130
|
+
// and the sample all read the same declaration.
|
|
131
|
+
const lookup = withDisclosure(definition.lookup);
|
|
118
132
|
verbs.push(
|
|
119
|
-
compileLookupVerb(
|
|
133
|
+
compileLookupVerb(lookup, noun, source, prefixes, hasList, tierScope),
|
|
120
134
|
);
|
|
121
|
-
if (
|
|
122
|
-
verbs.push(compileSampleVerb(
|
|
135
|
+
if (lookup.sample) {
|
|
136
|
+
verbs.push(compileSampleVerb(lookup, noun, source, prefixes, hasList));
|
|
123
137
|
}
|
|
124
138
|
}
|
|
125
139
|
|
|
@@ -195,6 +209,7 @@ export function compileListable(
|
|
|
195
209
|
* @param definition - A validated pack definition.
|
|
196
210
|
* @param source - Where the definition came from, for diagnostics.
|
|
197
211
|
* @param prefixes - The merged prefix map used for display compaction.
|
|
212
|
+
* @param nouns - As {@link compilePack}.
|
|
198
213
|
* @returns The module: the compiled verbs plus the story's module-level data.
|
|
199
214
|
* @throws PragmaError CONFIG_ERROR when the definition cannot be compiled,
|
|
200
215
|
* naming the field and the rule.
|
|
@@ -203,6 +218,7 @@ export function compileStoryModule(
|
|
|
203
218
|
definition: PackDefinition,
|
|
204
219
|
source: StorySource,
|
|
205
220
|
prefixes: Readonly<Record<string, string>>,
|
|
221
|
+
nouns?: NounLookups,
|
|
206
222
|
): CapabilityModule {
|
|
207
223
|
const issue = storyIssues(definition)[0];
|
|
208
224
|
if (issue) {
|
|
@@ -211,17 +227,47 @@ export function compileStoryModule(
|
|
|
211
227
|
);
|
|
212
228
|
}
|
|
213
229
|
const listable = compileListable(definition);
|
|
214
|
-
|
|
230
|
+
const module: CapabilityModule = {
|
|
215
231
|
name: definition.noun,
|
|
216
232
|
story: true,
|
|
217
|
-
verbs: compilePack(definition, source, prefixes),
|
|
233
|
+
verbs: compilePack(definition, source, prefixes, nouns),
|
|
218
234
|
colophon: definition.colophon,
|
|
219
235
|
...(listable ? { mcpListable: listable } : {}),
|
|
220
236
|
};
|
|
237
|
+
compiledFrom.set(module, { definition, source, prefixes });
|
|
238
|
+
return module;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** What each story module was compiled from. */
|
|
242
|
+
const compiledFrom = new WeakMap<
|
|
243
|
+
CapabilityModule,
|
|
244
|
+
{
|
|
245
|
+
readonly definition: PackDefinition;
|
|
246
|
+
readonly source: StorySource;
|
|
247
|
+
readonly prefixes: Readonly<Record<string, string>>;
|
|
248
|
+
}
|
|
249
|
+
>();
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* The story a module was compiled from by {@link compileStoryModule}, with the
|
|
253
|
+
* source and prefixes it was compiled under; `undefined` for any other module.
|
|
254
|
+
*/
|
|
255
|
+
export function storyOf(
|
|
256
|
+
module: CapabilityModule,
|
|
257
|
+
): ReturnType<(typeof compiledFrom)["get"]> {
|
|
258
|
+
return compiledFrom.get(module);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Carry a story half's declared guidance onto its verb, omitting what is absent. */
|
|
262
|
+
function guidanceOf(half: PackGuidance): Pick<VerbSpec, "useWhen" | "example"> {
|
|
263
|
+
return {
|
|
264
|
+
...(half.useWhen ? { useWhen: half.useWhen } : {}),
|
|
265
|
+
...(half.example ? { example: half.example } : {}),
|
|
266
|
+
};
|
|
221
267
|
}
|
|
222
268
|
|
|
223
269
|
/** Presentation facts for one compiled list-shaped verb. */
|
|
224
|
-
interface ListVerbMeta {
|
|
270
|
+
interface ListVerbMeta extends PackGuidance {
|
|
225
271
|
readonly noun: string;
|
|
226
272
|
readonly verb: string;
|
|
227
273
|
readonly summary: string;
|
|
@@ -229,6 +275,8 @@ interface ListVerbMeta {
|
|
|
229
275
|
readonly doc?: string;
|
|
230
276
|
readonly source: StorySource;
|
|
231
277
|
readonly prefixes: Readonly<Record<string, string>>;
|
|
278
|
+
/** The other stories' lookups, for a filter that names a noun. */
|
|
279
|
+
readonly nouns?: NounLookups;
|
|
232
280
|
/** The noun's declared tier hierarchy, when its entities are tiered. */
|
|
233
281
|
readonly tierScope?: PackTierScope;
|
|
234
282
|
}
|
|
@@ -246,6 +294,7 @@ function compileListVerb(shape: PackList, meta: ListVerbMeta): VerbSpec {
|
|
|
246
294
|
path: [meta.noun, meta.verb],
|
|
247
295
|
summary: meta.summary,
|
|
248
296
|
...(meta.doc ? { doc: meta.doc } : {}),
|
|
297
|
+
...guidanceOf(meta),
|
|
249
298
|
params,
|
|
250
299
|
output: {
|
|
251
300
|
formatters: listFormatters(shape, {
|
|
@@ -272,6 +321,8 @@ function compileListVerb(shape: PackList, meta: ListVerbMeta): VerbSpec {
|
|
|
272
321
|
runBodies().then((m) =>
|
|
273
322
|
m.makeListRun(shape, {
|
|
274
323
|
source: meta.source,
|
|
324
|
+
prefixes: meta.prefixes,
|
|
325
|
+
...(meta.nouns ? { nouns: meta.nouns } : {}),
|
|
275
326
|
...(meta.tierScope ? { tierScope: meta.tierScope } : {}),
|
|
276
327
|
})(params, rt),
|
|
277
328
|
),
|
|
@@ -285,6 +336,7 @@ function compileLookupVerb(
|
|
|
285
336
|
noun: string,
|
|
286
337
|
source: StorySource,
|
|
287
338
|
prefixes: Readonly<Record<string, string>>,
|
|
339
|
+
hasList: boolean,
|
|
288
340
|
tierScope?: PackTierScope,
|
|
289
341
|
): VerbSpec {
|
|
290
342
|
// Derive-by-default: every lookup completes its `<name>` from the pack index
|
|
@@ -319,6 +371,7 @@ function compileLookupVerb(
|
|
|
319
371
|
summary:
|
|
320
372
|
lookup.description ?? `Look up ${noun} details by name, IRI, or glob.`,
|
|
321
373
|
...(lookup.toolDescription ? { doc: lookup.toolDescription } : {}),
|
|
374
|
+
...guidanceOf(lookup),
|
|
322
375
|
params: [nameParam, ...tierParams(tierScope)],
|
|
323
376
|
output: { formatters: lookupFormatters(lookup, prefixes) },
|
|
324
377
|
examples: [
|
|
@@ -332,13 +385,18 @@ function compileLookupVerb(
|
|
|
332
385
|
]
|
|
333
386
|
: []),
|
|
334
387
|
],
|
|
335
|
-
|
|
336
|
-
? { disclosure: disclosureSpec(lookup.disclosure) }
|
|
337
|
-
: {}),
|
|
388
|
+
disclosure: disclosureSpec(lookup.disclosure),
|
|
338
389
|
capability: READ_CAPABILITY,
|
|
339
390
|
run: (params: Record<string, unknown>, rt: PragmaRuntime) =>
|
|
340
391
|
runBodies().then((m) =>
|
|
341
|
-
m.makeLookupRun(
|
|
392
|
+
m.makeLookupRun(
|
|
393
|
+
lookup,
|
|
394
|
+
noun,
|
|
395
|
+
source,
|
|
396
|
+
prefixes,
|
|
397
|
+
hasList,
|
|
398
|
+
tierScope,
|
|
399
|
+
)(params, rt),
|
|
342
400
|
),
|
|
343
401
|
};
|
|
344
402
|
return asVerb(verb);
|
|
@@ -374,6 +432,7 @@ function compileSampleVerb(
|
|
|
374
432
|
noun: string,
|
|
375
433
|
source: StorySource,
|
|
376
434
|
prefixes: Readonly<Record<string, string>>,
|
|
435
|
+
hasList: boolean,
|
|
377
436
|
): VerbSpec {
|
|
378
437
|
const defaultCount = sampleDefaultCount(lookup);
|
|
379
438
|
const config = lookup.sample === true ? undefined : lookup.sample;
|
|
@@ -396,6 +455,7 @@ function compileSampleVerb(
|
|
|
396
455
|
config?.description ??
|
|
397
456
|
`Return randomly selected complete ${noun} entries as exemplars.`,
|
|
398
457
|
...(config?.toolDescription ? { doc: config.toolDescription } : {}),
|
|
458
|
+
...guidanceOf(config ?? {}),
|
|
399
459
|
params: countParam,
|
|
400
460
|
output: { formatters: sampleFormatters(lookup, noun, prefixes) },
|
|
401
461
|
examples: [
|
|
@@ -411,12 +471,41 @@ function compileSampleVerb(
|
|
|
411
471
|
source,
|
|
412
472
|
prefixes,
|
|
413
473
|
defaultCount,
|
|
474
|
+
hasList,
|
|
414
475
|
)(params, rt),
|
|
415
476
|
),
|
|
416
477
|
};
|
|
417
478
|
return asVerb(verb);
|
|
418
479
|
}
|
|
419
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Give a lookup that declares no disclosure the canonical ladder: default
|
|
483
|
+
* `detailed` (so its default answer is unchanged) and untagged expands from
|
|
484
|
+
* `standard` (so `summary` is the fields alone, and `standard` equals
|
|
485
|
+
* `detailed`). A declared disclosure is returned as written.
|
|
486
|
+
*/
|
|
487
|
+
function withDisclosure(lookup: PackLookup): PackLookup {
|
|
488
|
+
if (lookup.disclosure) return lookup;
|
|
489
|
+
return {
|
|
490
|
+
...lookup,
|
|
491
|
+
disclosure: { levels: [...DETAIL_LEVELS], default: IMPUTED_DEFAULT_LEVEL },
|
|
492
|
+
...(lookup.expand
|
|
493
|
+
? {
|
|
494
|
+
expand: lookup.expand.map((expand) => ({
|
|
495
|
+
...expand,
|
|
496
|
+
level: expand.level ?? IMPUTED_EXPAND_LEVEL,
|
|
497
|
+
})),
|
|
498
|
+
}
|
|
499
|
+
: {}),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** The level an imputed disclosure answers at when none is asked for: all of it. */
|
|
504
|
+
const IMPUTED_DEFAULT_LEVEL = "detailed";
|
|
505
|
+
|
|
506
|
+
/** The level from which an imputed disclosure shows an untagged expand. */
|
|
507
|
+
const IMPUTED_EXPAND_LEVEL = "standard";
|
|
508
|
+
|
|
420
509
|
/** Normalize a pack disclosure into a {@link DisclosureSpec} (default → base). */
|
|
421
510
|
function disclosureSpec(disclosure: PackLookup["disclosure"]): DisclosureSpec {
|
|
422
511
|
const levels = disclosure?.levels ?? [];
|