@canonical/pragma-cli 0.36.0 → 0.38.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 -2
- package/bundled-skills/adoption-a1-styles/SKILL.md +24 -0
- package/bundled-skills/adoption-a2-components/SKILL.md +22 -6
- package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +1397 -327
- package/bundled-skills/anatomy-author/SKILL.md +840 -137
- package/bundled-skills/design-auditor/SKILL.md +133 -9
- package/bundled-skills/implement-component/SKILL.md +192 -23
- package/bundled-skills/specify-component/SKILL.md +124 -12
- package/bundled-skills/specify-pattern/SKILL.md +47 -8
- package/dist/package.json +23 -20
- package/dist/pragma.conf.js +963 -40
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/capabilities/capabilities/catalog.js +14 -5
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -1
- package/dist/src/capabilities/capabilities/hints.js +33 -5
- package/dist/src/capabilities/capabilities/hints.js.map +1 -1
- package/dist/src/capabilities/config/show.render.js +30 -2
- package/dist/src/capabilities/config/show.render.js.map +1 -1
- package/dist/src/capabilities/create/create.verb.js +2 -1
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/create/createSurface.generated.js +23 -1
- package/dist/src/capabilities/create/createSurface.generated.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +11 -6
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js +38 -0
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/targetHealth.js +104 -14
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
- package/dist/src/capabilities/graph/connect.render.js +101 -0
- package/dist/src/capabilities/graph/connect.render.js.map +1 -0
- package/dist/src/capabilities/graph/connect.types.js +21 -0
- package/dist/src/capabilities/graph/connect.types.js.map +1 -0
- package/dist/src/capabilities/graph/connect.verb.js +147 -0
- package/dist/src/capabilities/graph/connect.verb.js.map +1 -0
- package/dist/src/capabilities/graph/index.js +5 -3
- package/dist/src/capabilities/graph/index.js.map +1 -1
- package/dist/src/capabilities/graph/queryText.js +206 -0
- package/dist/src/capabilities/graph/queryText.js.map +1 -0
- package/dist/src/capabilities/graph/relationIndex.js +302 -0
- package/dist/src/capabilities/graph/relationIndex.js.map +1 -0
- package/dist/src/capabilities/graph/runConnect.js +456 -0
- package/dist/src/capabilities/graph/runConnect.js.map +1 -0
- package/dist/src/capabilities/graph/runQuery.js +21 -4
- package/dist/src/capabilities/graph/runQuery.js.map +1 -1
- package/dist/src/capabilities/setup/buildPlan.js +6 -2
- package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
- package/dist/src/capabilities/setup/operations/index.js +7 -2
- package/dist/src/capabilities/setup/operations/index.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupCompletions.js +6 -2
- package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
- package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupGenerator.js +72 -14
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupLsp.js +372 -62
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupMcp.js +150 -5
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupSkills.js +4 -2
- package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
- package/dist/src/capabilities/setup/operations/writability.js +114 -0
- package/dist/src/capabilities/setup/operations/writability.js.map +1 -0
- package/dist/src/capabilities/setup/plan.js.map +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +80 -31
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/setup/targets.js +124 -42
- package/dist/src/capabilities/setup/targets.js.map +1 -1
- package/dist/src/capabilities/shared/index.js +1 -1
- package/dist/src/capabilities/shared/index.js.map +1 -1
- package/dist/src/constants.js +7 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/error/renderError.js +3 -2
- package/dist/src/kernel/error/renderError.js.map +1 -1
- package/dist/src/kernel/error/validOptions.js +41 -0
- package/dist/src/kernel/error/validOptions.js.map +1 -0
- package/dist/src/kernel/packs/compile.js +90 -6
- package/dist/src/kernel/packs/compile.js.map +1 -1
- package/dist/src/kernel/packs/cursor.js +135 -0
- package/dist/src/kernel/packs/cursor.js.map +1 -0
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js +9 -2
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -1
- package/dist/src/kernel/packs/paging.js +108 -0
- package/dist/src/kernel/packs/paging.js.map +1 -0
- package/dist/src/kernel/packs/renderPack.js +154 -5
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +118 -19
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +156 -18
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +160 -12
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/authorQuery.js +227 -0
- package/dist/src/kernel/packs/sparql/authorQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js +251 -0
- package/dist/src/kernel/packs/sparql/buildListQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +125 -22
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/sparql/filterValues.js +145 -0
- package/dist/src/kernel/packs/sparql/filterValues.js.map +1 -0
- package/dist/src/kernel/packs/sparql/index.js +24 -14
- package/dist/src/kernel/packs/sparql/index.js.map +1 -1
- package/dist/src/kernel/packs/sparql/runSelect.js +10 -4
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -1
- package/dist/src/kernel/packs/sparql/searchTerm.js +25 -0
- package/dist/src/kernel/packs/sparql/searchTerm.js.map +1 -0
- package/dist/src/kernel/packs/storyRules.js +151 -0
- package/dist/src/kernel/packs/storyRules.js.map +1 -0
- package/dist/src/kernel/packs/tierScope.js +310 -0
- package/dist/src/kernel/packs/tierScope.js.map +1 -0
- package/dist/src/kernel/packs/types.js +80 -0
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +10 -1
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +104 -3
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/rootHelp.js +8 -5
- package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
- package/dist/src/kernel/project/cli/suggestNames.js +31 -7
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +5 -1
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +34 -2
- package/dist/src/kernel/render/renderers.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +2 -3
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
- package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +17 -10
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +3 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/probe.js +1 -1
- package/dist/src/kernel/runtime/probe.js.map +1 -1
- package/dist/src/kernel/runtime/readEntity.js +19 -4
- package/dist/src/kernel/runtime/readEntity.js.map +1 -1
- package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
- package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
- package/dist/src/kernel/runtime/refs/resolve.js +38 -5
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
- package/dist/src/kernel/spec/emitReference.js +1 -1
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/package.json +23 -20
- package/pragma.conf.ts +983 -40
- package/src/capabilities/block.parity.test.ts +207 -27
- package/src/capabilities/block.shipped.exec.test.ts +156 -14
- package/src/capabilities/block.tierRank.exec.test.ts +46 -9
- package/src/capabilities/capabilities/catalog.ts +14 -5
- package/src/capabilities/capabilities/hints.ts +40 -5
- package/src/capabilities/config/collectConfigShow.test.ts +1 -0
- package/src/capabilities/config/set.test.ts +24 -25
- package/src/capabilities/config/show.render.test.ts +9 -4
- package/src/capabilities/config/show.render.ts +30 -2
- package/src/capabilities/create/byteEquality.test.ts +28 -1
- package/src/capabilities/create/create.test.ts +1 -0
- package/src/capabilities/create/create.verb.ts +2 -1
- package/src/capabilities/create/createGrammar.test.ts +4 -1
- package/src/capabilities/create/createSurface.generated.ts +23 -1
- package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
- package/src/capabilities/distribution.parity.test.ts +12 -11
- package/src/capabilities/distribution.test.ts +77 -7
- package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
- package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
- package/src/capabilities/doctor/checks/harnessInventory.test.ts +13 -6
- package/src/capabilities/doctor/checks/harnessInventory.ts +8 -4
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.test.ts +111 -0
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
- package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
- package/src/capabilities/doctor/checks/targetHealth.ts +114 -13
- package/src/capabilities/doctor/doctor.test.ts +327 -36
- package/src/capabilities/emptyRecovery.test.ts +84 -28
- package/src/capabilities/graph/connect.render.ts +141 -0
- package/src/capabilities/graph/connect.shipped.exec.test.ts +370 -0
- package/src/capabilities/graph/connect.test.ts +361 -0
- package/src/capabilities/graph/connect.types.ts +136 -0
- package/src/capabilities/graph/connect.verb.ts +165 -0
- package/src/capabilities/graph/index.ts +5 -3
- package/src/capabilities/graph/query.shipped.exec.test.ts +66 -0
- package/src/capabilities/graph/query.test.ts +17 -0
- package/src/capabilities/graph/queryText.test.ts +121 -0
- package/src/capabilities/graph/queryText.ts +240 -0
- package/src/capabilities/graph/relationIndex.ts +372 -0
- package/src/capabilities/graph/runConnect.ts +577 -0
- package/src/capabilities/graph/runQuery.ts +21 -6
- package/src/capabilities/lazy.test.ts +32 -2
- package/src/capabilities/listBudget.shipped.exec.test.ts +239 -0
- package/src/capabilities/listLookup.shipped.exec.test.ts +387 -0
- package/src/capabilities/listQuery.shipped.exec.test.ts +400 -0
- package/src/capabilities/resources/resources.test.ts +38 -2
- package/src/capabilities/setup/buildPlan.ts +7 -1
- package/src/capabilities/setup/operations/index.ts +14 -0
- package/src/capabilities/setup/operations/setupCompletions.ts +9 -2
- package/src/capabilities/setup/operations/setupConfig.ts +7 -2
- package/src/capabilities/setup/operations/setupGenerator.ts +93 -15
- package/src/capabilities/setup/operations/setupLsp.ts +544 -85
- package/src/capabilities/setup/operations/setupMcp.ts +212 -4
- package/src/capabilities/setup/operations/setupSkills.ts +7 -2
- package/src/capabilities/setup/operations/writability.test.ts +151 -0
- package/src/capabilities/setup/operations/writability.ts +135 -0
- package/src/capabilities/setup/plan.ts +11 -0
- package/src/capabilities/setup/setup.test.ts +992 -16
- package/src/capabilities/setup/setup.verb.ts +84 -36
- package/src/capabilities/setup/targets.ts +152 -48
- package/src/capabilities/setup/types.ts +41 -5
- package/src/capabilities/shared/index.ts +1 -0
- package/src/capabilities/sources/sources.test.ts +55 -0
- package/src/capabilities/surface.test.ts +59 -11
- package/src/capabilities/tier.parity.test.ts +2 -2
- package/src/capabilities/token.parity.test.ts +784 -0
- package/src/capabilities/tokenGraph.cli.test.ts +279 -0
- package/src/capabilities/tokenGraph.shipped.exec.test.ts +653 -0
- package/src/capabilities/variable.parity.test.ts +448 -0
- package/src/constants.ts +8 -0
- package/src/kernel/completion/shellDrive.test.ts +32 -30
- package/src/kernel/config/defaults.test.ts +21 -2
- package/src/kernel/config/readConfig.test.ts +1 -1
- package/src/kernel/error/renderError.ts +3 -2
- package/src/kernel/error/validOptions.test.ts +57 -0
- package/src/kernel/error/validOptions.ts +45 -0
- package/src/kernel/packs/collect.test.ts +2 -0
- package/src/kernel/packs/compile.test.ts +188 -15
- package/src/kernel/packs/compile.ts +109 -14
- package/src/kernel/packs/cursor.ts +135 -0
- package/src/kernel/packs/filteredEmpty.test.ts +213 -0
- package/src/kernel/packs/graphql/buildLookupDocument.ts +16 -9
- package/src/kernel/packs/graphqlSource.test.ts +152 -0
- package/src/kernel/packs/listNotice.test.ts +156 -0
- package/src/kernel/packs/paging.ts +110 -0
- package/src/kernel/packs/renderPack.ts +186 -13
- package/src/kernel/packs/resolveEntity.test.ts +62 -3
- package/src/kernel/packs/resolveEntity.ts +186 -26
- package/src/kernel/packs/runBodies.ts +196 -26
- package/src/kernel/packs/schema.ts +180 -13
- package/src/kernel/packs/sparql/authorQuery.test.ts +179 -0
- package/src/kernel/packs/sparql/authorQuery.ts +257 -0
- package/src/kernel/packs/sparql/buildListQuery.test.ts +344 -0
- package/src/kernel/packs/sparql/buildListQuery.ts +344 -0
- package/src/kernel/packs/sparql/buildLookupQuery.test.ts +138 -0
- package/src/kernel/packs/sparql/buildLookupQuery.ts +140 -20
- package/src/kernel/packs/sparql/filterValues.test.ts +86 -0
- package/src/kernel/packs/sparql/filterValues.ts +182 -0
- package/src/kernel/packs/sparql/index.ts +30 -14
- package/src/kernel/packs/sparql/runSelect.test.ts +63 -0
- package/src/kernel/packs/sparql/runSelect.ts +42 -2
- package/src/kernel/packs/sparql/searchTerm.ts +29 -0
- package/src/kernel/packs/storyRules.ts +180 -0
- package/src/kernel/packs/tierScope.test.ts +487 -0
- package/src/kernel/packs/tierScope.ts +409 -0
- package/src/kernel/packs/toolDescription.test.ts +13 -10
- package/src/kernel/packs/types.ts +311 -9
- package/src/kernel/project/cli/buildProgram.ts +17 -1
- package/src/kernel/project/cli/dispatch.test.ts +87 -0
- package/src/kernel/project/cli/dispatch.ts +114 -4
- package/src/kernel/project/cli/rootHelp.ts +8 -5
- package/src/kernel/project/cli/suggest.test.ts +35 -0
- package/src/kernel/project/cli/suggestNames.ts +34 -7
- package/src/kernel/project/mcp/registerVerb.ts +5 -1
- package/src/kernel/render/contracts.ts +2 -0
- package/src/kernel/render/prefixes.test.ts +2 -0
- package/src/kernel/render/renderers.test.ts +43 -0
- package/src/kernel/render/renderers.ts +34 -1
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +2 -3
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
- package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +14 -6
- package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
- package/src/kernel/runtime/graphpack/read.ts +17 -13
- package/src/kernel/runtime/loadSession.ts +3 -1
- package/src/kernel/runtime/probe.ts +1 -1
- package/src/kernel/runtime/readEntity.ts +19 -4
- package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
- package/src/kernel/runtime/refs/parseRef.ts +25 -1
- package/src/kernel/runtime/refs/resolve.ts +39 -5
- package/src/kernel/runtime/types.ts +30 -0
- package/src/kernel/spec/emitReference.ts +1 -1
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/types.ts +17 -0
- package/src/testing/PARITY_GAPS.ts +4 -4
- package/src/testing/behavioral/agentSession.mcp.test.ts +43 -39
- package/src/testing/behavioral/completion.test.ts +7 -6
- package/src/testing/behavioral/disclosure.test.ts +39 -37
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +82 -64
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +11 -10
- package/src/testing/behavioral/journeys.cli.test.ts +71 -32
- package/src/testing/behavioral/journeys.defaultPack.test.ts +6 -4
- package/src/testing/behavioral/journeys.firstInstall.test.ts +70 -5
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +4 -3
- package/src/testing/behavioral/journeys.packageStories.test.ts +2 -1
- package/src/testing/behavioral/mcpSurface.test.ts +28 -25
- package/src/testing/behavioral/parity.test.ts +25 -23
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +20 -0
- package/src/testing/eval/cases/effectful.ts +7 -1
- package/src/testing/eval/cases/readNouns.ts +100 -11
- package/src/testing/fixtures/blockGraph.ts +89 -5
- package/src/testing/fixtures/connectGraph.ts +159 -0
- package/src/testing/fixtures/graph/canonical.ts +128 -32
- package/src/testing/helpers/fsProbe.ts +88 -0
- package/src/testing/helpers/runCli.test.ts +44 -0
- package/src/testing/helpers/runCli.ts +27 -3
- package/src/testing/perf/budgets.test.ts +3 -1
- package/src/testing/perf/budgets.ts +138 -54
- package/dist/src/kernel/packs/sparql/applyFilters.js +0 -167
- package/dist/src/kernel/packs/sparql/applyFilters.js.map +0 -1
- package/dist/src/kernel/packs/sparql/applySearch.js +0 -25
- package/dist/src/kernel/packs/sparql/applySearch.js.map +0 -1
- package/src/kernel/packs/sparql/applyFilters.ts +0 -203
- package/src/kernel/packs/sparql/applySearch.ts +0 -33
|
@@ -83,6 +83,14 @@ function buildKernelGroups(programName: string): readonly HelpGroup[] {
|
|
|
83
83
|
},
|
|
84
84
|
{ noun: "info", summary: "Show version, config, and update status" },
|
|
85
85
|
{ noun: "version", summary: "Print the CLI version" },
|
|
86
|
+
// A colophon is the note at the back of a book: the typeface, the
|
|
87
|
+
// press, the paper. Nothing depends on it, which is the point — so
|
|
88
|
+
// this line does not argue for it. Every other summary in this column
|
|
89
|
+
// promises work done; this one just invites you to look. It sits with
|
|
90
|
+
// the other commands that describe the distribution rather than act on
|
|
91
|
+
// it; "For AI agents" is for surfaces an agent drives, and credits are
|
|
92
|
+
// for a person reading.
|
|
93
|
+
{ noun: "colophon", summary: "Read the credits" },
|
|
86
94
|
{
|
|
87
95
|
noun: "upgrade",
|
|
88
96
|
summary: `Upgrade the ${programName} CLI to the latest version`,
|
|
@@ -96,11 +104,6 @@ function buildKernelGroups(programName: string): readonly HelpGroup[] {
|
|
|
96
104
|
noun: "capabilities",
|
|
97
105
|
summary: "Discover conventions, tools, and the discovery sequence",
|
|
98
106
|
},
|
|
99
|
-
// A colophon is the note at the back of a book: the typeface, the
|
|
100
|
-
// press, the paper. Nothing depends on it, which is the point — so
|
|
101
|
-
// this line does not argue for it. Every other summary in this column
|
|
102
|
-
// promises work done; this one just invites you to look.
|
|
103
|
-
{ noun: "colophon", summary: "Read the credits" },
|
|
104
107
|
{ noun: "skill", summary: "Browse agent skills from the active packs" },
|
|
105
108
|
{ noun: "prompt", summary: "Browse reusable prompt templates" },
|
|
106
109
|
// Curated for PLACEMENT, not for existence: `mcp serve` is an
|
|
@@ -83,4 +83,39 @@ describe("suggestNames", () => {
|
|
|
83
83
|
it("returns nothing for an empty query", () => {
|
|
84
84
|
expect(suggestNames("", ["config"])).toEqual([]);
|
|
85
85
|
});
|
|
86
|
+
|
|
87
|
+
it("returns nothing for a query that is only whitespace", () => {
|
|
88
|
+
expect(suggestNames(" ", ["config"])).toEqual([]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("never offers a candidate that IS the query once padding is ignored", () => {
|
|
92
|
+
// The reported defect, in the unit that produced the sentence:
|
|
93
|
+
// `block lookup Timeline` printed `Did you mean? - Timeline ` because 66
|
|
94
|
+
// shipped `ds:name` literals carry the source document's trailing space, and
|
|
95
|
+
// the exclusion compared the raw strings. A suggestion that differs from the
|
|
96
|
+
// query by a character no surface prints reads as the CLI refusing the word
|
|
97
|
+
// it just echoed — and if a candidate really is the query, the miss is the
|
|
98
|
+
// bug, so restating it would only hide the bug.
|
|
99
|
+
//
|
|
100
|
+
// The near-miss beside it is what proves the exclusion is the only thing
|
|
101
|
+
// dropped — an empty list would pass whether the rule worked or the
|
|
102
|
+
// threshold had simply swallowed both.
|
|
103
|
+
expect(suggestNames("Timeline", ["Timeline ", "Timelines"])).toEqual([
|
|
104
|
+
"Timelines",
|
|
105
|
+
]);
|
|
106
|
+
// Both directions, and leading padding too: the query is the padded one
|
|
107
|
+
// here, and case is folded alongside.
|
|
108
|
+
expect(suggestNames(" timeline\t", ["Timeline", "Timelines"])).toEqual([
|
|
109
|
+
"Timelines",
|
|
110
|
+
]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("suggests a padded candidate by its LITERAL value on a genuine typo", () => {
|
|
114
|
+
// Padding costs a candidate no edit distance, and the value handed back is
|
|
115
|
+
// the one the graph holds — the suggester matches loosely and quotes
|
|
116
|
+
// exactly, because a suggestion names something a reader can look up.
|
|
117
|
+
expect(suggestNames("Timelime", ["Timeline ", "block"])).toEqual([
|
|
118
|
+
"Timeline ",
|
|
119
|
+
]);
|
|
120
|
+
});
|
|
86
121
|
});
|
|
@@ -10,30 +10,43 @@
|
|
|
10
10
|
* Return up to {@link maxResults} candidates most similar to `query`.
|
|
11
11
|
*
|
|
12
12
|
* Exact matches are excluded — a match means the caller should have resolved it
|
|
13
|
-
* and never reached here.
|
|
13
|
+
* and never reached here. "Exact" is judged on the TRIMMED, case-folded token,
|
|
14
|
+
* which is the same equality the resolver's own name FILTER applies, so the two
|
|
15
|
+
* cannot disagree about whether a candidate is a match. They did:
|
|
16
|
+
* `block lookup Timeline` missed an entity whose `ds:name` ends in a space and
|
|
17
|
+
* then suggested "Timeline " back, which reads as the CLI declining to accept
|
|
18
|
+
* the word it just printed. Restating the query is never a useful suggestion —
|
|
19
|
+
* if a candidate really is the query, the miss is the bug and the suggestion
|
|
20
|
+
* would only hide it.
|
|
21
|
+
*
|
|
22
|
+
* Scoring reads the same trimmed forms, so padding costs a candidate no edit
|
|
23
|
+
* distance either; what is RETURNED is the candidate verbatim, padding and
|
|
24
|
+
* casing intact, because a suggestion names a value the graph holds.
|
|
14
25
|
*
|
|
15
26
|
* @param query - The token that failed to resolve.
|
|
16
27
|
* @param candidates - All known names to rank against.
|
|
17
28
|
* @param opts.maxResults - Max suggestions to return (default 5).
|
|
18
29
|
* @param opts.threshold - Max normalized edit distance (default 0.4).
|
|
19
|
-
* @returns Ranked suggestions, original
|
|
30
|
+
* @returns Ranked suggestions, original spelling preserved.
|
|
20
31
|
*/
|
|
21
32
|
export function suggestNames(
|
|
22
33
|
query: string,
|
|
23
34
|
candidates: readonly string[],
|
|
24
35
|
opts?: { maxResults?: number; threshold?: number },
|
|
25
36
|
): string[] {
|
|
26
|
-
if (query === "") return [];
|
|
27
|
-
|
|
28
37
|
const maxResults = opts?.maxResults ?? 5;
|
|
29
38
|
const threshold = opts?.threshold ?? 0.4;
|
|
30
|
-
const queryLower = query.toLowerCase();
|
|
39
|
+
const queryLower = query.trim().toLowerCase();
|
|
40
|
+
|
|
41
|
+
// A token that is nothing but whitespace has no word to rank against, the
|
|
42
|
+
// same as the empty one.
|
|
43
|
+
if (queryLower === "") return [];
|
|
31
44
|
|
|
32
45
|
type Scored = { name: string; score: number };
|
|
33
46
|
const scored: Scored[] = [];
|
|
34
47
|
|
|
35
48
|
for (const candidate of candidates) {
|
|
36
|
-
const candidateLower = candidate.toLowerCase();
|
|
49
|
+
const candidateLower = candidate.trim().toLowerCase();
|
|
37
50
|
|
|
38
51
|
if (candidateLower === queryLower) continue;
|
|
39
52
|
|
|
@@ -42,8 +55,22 @@ export function suggestNames(
|
|
|
42
55
|
continue;
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
const distance = damerauLevenshtein(queryLower, candidateLower);
|
|
46
58
|
const maxLen = Math.max(queryLower.length, candidateLower.length);
|
|
59
|
+
// Skip on LENGTH before building a matrix. An edit distance is at least the
|
|
60
|
+
// difference in length, so a candidate whose length alone already exceeds
|
|
61
|
+
// the threshold cannot pass it — and the full Damerau-Levenshtein for it
|
|
62
|
+
// costs an O(n·m) matrix allocation. This changes no result, only the cost
|
|
63
|
+
// of reaching it: ranking one mistyped name against the shipped pack's
|
|
64
|
+
// 4,380 entities took 1.2 SECONDS, which is a long time to wait to be told
|
|
65
|
+
// about a typo.
|
|
66
|
+
if (
|
|
67
|
+
Math.abs(queryLower.length - candidateLower.length) >
|
|
68
|
+
threshold * maxLen
|
|
69
|
+
) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const distance = damerauLevenshtein(queryLower, candidateLower);
|
|
47
74
|
const normalized = maxLen === 0 ? 0 : distance / maxLen;
|
|
48
75
|
|
|
49
76
|
if (normalized <= threshold) {
|
|
@@ -156,7 +156,11 @@ function withDetail(
|
|
|
156
156
|
*/
|
|
157
157
|
function noticeMeta(verb: VerbSpec, data: unknown): Record<string, unknown> {
|
|
158
158
|
const notice = verb.output.formatters.notice?.(data as never);
|
|
159
|
-
|
|
159
|
+
// The seam's machine half, merged here so an agent gets the tier scope as
|
|
160
|
+
// DATA (`meta.scope`) and not only as the sentence `notice` carries. The CLI
|
|
161
|
+
// merges the same seam into the same keys (`cli/dispatch.ts#renderData`).
|
|
162
|
+
const extra = verb.output.formatters.meta?.(data as never);
|
|
163
|
+
return { ...(extra ?? {}), ...(notice ? { notice } : {}) };
|
|
160
164
|
}
|
|
161
165
|
|
|
162
166
|
/** The tool handler for a read verb: run, project, envelope. */
|
|
@@ -51,6 +51,8 @@ export interface SectionDef<T> {
|
|
|
51
51
|
readonly heading: string;
|
|
52
52
|
readonly kind: SectionKind;
|
|
53
53
|
readonly showWhenEmpty?: boolean;
|
|
54
|
+
/** One sentence on how to READ the body, rendered under the heading. */
|
|
55
|
+
readonly note?: string;
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
/** A single inline field rendered in a lookup heading block. */
|
|
@@ -13,6 +13,8 @@ describe("DEFAULT_PREFIX_MAP", () => {
|
|
|
13
13
|
skos: "http://www.w3.org/2004/02/skos/core#",
|
|
14
14
|
ds: "https://ds.canonical.com/",
|
|
15
15
|
cs: "http://pragma.canonical.com/codestandards#",
|
|
16
|
+
dt: "https://dt.canonical.com/",
|
|
17
|
+
"w3c-tokens": "https://dt.canonical.com/w3c-tokens/",
|
|
16
18
|
});
|
|
17
19
|
});
|
|
18
20
|
|
|
@@ -440,3 +440,46 @@ describe("section-body nesting follows CommonMark, not a near-enough reading", (
|
|
|
440
440
|
expect(out).toMatch(/^### also inside$/m);
|
|
441
441
|
});
|
|
442
442
|
});
|
|
443
|
+
|
|
444
|
+
describe("a section can say how to read its body", () => {
|
|
445
|
+
const entity = { anatomy: "background.color: [a, b]" };
|
|
446
|
+
const options = {
|
|
447
|
+
title: () => "Button",
|
|
448
|
+
fields: [],
|
|
449
|
+
sections: [
|
|
450
|
+
{
|
|
451
|
+
key: "anatomy" as const,
|
|
452
|
+
heading: "Anatomy (DSL)",
|
|
453
|
+
kind: "code" as const,
|
|
454
|
+
note: "A list value is the fallback chain, first wins.",
|
|
455
|
+
},
|
|
456
|
+
],
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
it("puts the note between the heading and the body, once", () => {
|
|
460
|
+
const llm = renderLookupLlm(entity, options);
|
|
461
|
+
expect(llm).toContain(
|
|
462
|
+
"### Anatomy (DSL)\nA list value is the fallback chain, first wins.",
|
|
463
|
+
);
|
|
464
|
+
expect(llm.split("first wins")).toHaveLength(2);
|
|
465
|
+
|
|
466
|
+
const plain = renderLookupPlain(entity, options, styleFor(false));
|
|
467
|
+
expect(plain).toContain(
|
|
468
|
+
"Anatomy (DSL):\n A list value is the fallback chain, first wins.",
|
|
469
|
+
);
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it("renders nothing extra for a section that declares none", () => {
|
|
473
|
+
const bare = {
|
|
474
|
+
...options,
|
|
475
|
+
sections: [
|
|
476
|
+
{
|
|
477
|
+
key: "anatomy" as const,
|
|
478
|
+
heading: "Anatomy (DSL)",
|
|
479
|
+
kind: "code" as const,
|
|
480
|
+
},
|
|
481
|
+
],
|
|
482
|
+
};
|
|
483
|
+
expect(renderLookupLlm(entity, bare)).not.toContain("fallback chain");
|
|
484
|
+
});
|
|
485
|
+
});
|
|
@@ -189,12 +189,40 @@ function renderHeaderRow<T>(
|
|
|
189
189
|
return style.enabled ? style.bold(line) : line;
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Render a list as condensed Markdown.
|
|
194
|
+
*
|
|
195
|
+
* The heading COUNTS what the reader is looking at and — when the caller says
|
|
196
|
+
* so — admits that the count is not the population: `## Token (300, more
|
|
197
|
+
* exist)` rather than a bare `## Token (300)` that reads as a complete answer.
|
|
198
|
+
* The total is not named because it is not known: a page is cut with one extra
|
|
199
|
+
* row (`packs/runBodies.ts`), never with a second COUNT over the whole filtered
|
|
200
|
+
* population, so "more exist" is the strongest honest claim.
|
|
201
|
+
*
|
|
202
|
+
* The SCOPE is in the heading for the same reason, and it is the more serious
|
|
203
|
+
* of the two omissions: a truncated page at least ends where it ends, while a
|
|
204
|
+
* scoped read looks exactly like a complete one. `## Block (175, tier scope:
|
|
205
|
+
* global, apps, documentation, sites, stores)` says which part of the design
|
|
206
|
+
* system the 175 are, in the words `--tier` accepts.
|
|
207
|
+
*
|
|
208
|
+
* @param items - The rows on this page.
|
|
209
|
+
* @param options - Columns and empty-state copy.
|
|
210
|
+
* @param page - What the page knows about itself (`more`: further rows exist;
|
|
211
|
+
* `scope`: the tiers it answered from, when it answered from some of them).
|
|
212
|
+
* @returns The formatted Markdown list.
|
|
213
|
+
*/
|
|
192
214
|
export function renderListLlm<T>(
|
|
193
215
|
items: readonly T[],
|
|
194
216
|
options: RenderListOptions<T>,
|
|
217
|
+
page: { readonly more?: boolean; readonly scope?: string } = {},
|
|
195
218
|
): string {
|
|
196
219
|
const prefixes = options.prefixes ?? DEFAULT_PREFIX_MAP;
|
|
197
|
-
const
|
|
220
|
+
const count = [
|
|
221
|
+
`${items.length}`,
|
|
222
|
+
...(page.more === true ? ["more exist"] : []),
|
|
223
|
+
...(page.scope === undefined ? [] : [`tier scope: ${page.scope}`]),
|
|
224
|
+
].join(", ");
|
|
225
|
+
const lines = [`## ${options.heading} (${count})`, ""];
|
|
198
226
|
|
|
199
227
|
if (items.length === 0) {
|
|
200
228
|
const body = emptyBody(options);
|
|
@@ -326,6 +354,11 @@ function renderLookupSections<T>(
|
|
|
326
354
|
? `${"#".repeat(SECTION_HEADING_LEVEL)} ${section.heading}`
|
|
327
355
|
: `${section.heading}:`,
|
|
328
356
|
);
|
|
357
|
+
// How to read what follows goes between the heading and the body — a
|
|
358
|
+
// notation's key is no use anywhere else.
|
|
359
|
+
if (section.note) {
|
|
360
|
+
sections.push(mode === "llm" ? section.note : indentBlock(section.note));
|
|
361
|
+
}
|
|
329
362
|
sections.push(body);
|
|
330
363
|
}
|
|
331
364
|
|