@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
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { tmpdir } from "node:os";
|
|
18
18
|
import { join } from "node:path";
|
|
19
|
-
import { describe, expect, it } from "vitest";
|
|
19
|
+
import { describe, expect, it, vi } from "vitest";
|
|
20
20
|
import { storyModules } from "../../capabilities/distribution.js";
|
|
21
21
|
import { checkPackageRefs } from "../../capabilities/doctor/checks/checkPackageRefs.js";
|
|
22
22
|
import { promptListVerb } from "../../capabilities/prompt/verbs.js";
|
|
@@ -27,6 +27,14 @@ import { bootRuntime } from "../../kernel/runtime/boot.js";
|
|
|
27
27
|
import type { GlobalFlags } from "../../kernel/runtime/types.js";
|
|
28
28
|
import type { CapabilityModule, VerbSpec } from "../../kernel/spec/types.js";
|
|
29
29
|
|
|
30
|
+
// Every case here boots its own runtime — a fresh install is what is under test —
|
|
31
|
+
// and the first read in the process parses the embedded pack cold: 65,000 triples,
|
|
32
|
+
// three seconds on an idle machine and more when every package's suite runs at
|
|
33
|
+
// once, which is how the release workflow runs them. The budget is a fact about
|
|
34
|
+
// the pack's size, not about any assertion, and it belongs to the file because
|
|
35
|
+
// whichever case runs first is the one that pays it.
|
|
36
|
+
vi.setConfig({ testTimeout: 60_000 });
|
|
37
|
+
|
|
30
38
|
const JSON_FLAGS: GlobalFlags = {
|
|
31
39
|
llm: false,
|
|
32
40
|
autoLlm: false,
|
|
@@ -113,10 +121,67 @@ describe("first install — an empty cwd answers real reads offline", () => {
|
|
|
113
121
|
});
|
|
114
122
|
|
|
115
123
|
describe("first install — empty results are honest, not papered over", () => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
// `token list` used to be this describe's first case, asserting no rows
|
|
125
|
+
// "because the graph carries no ds:Token". That is no longer true and the
|
|
126
|
+
// change is the point: the noun addressed a class no shipped graph asserted,
|
|
127
|
+
// it now addresses the token symbols, and the embedded pack carries them with
|
|
128
|
+
// the name literal the story keys on — so a first install ANSWERS. The case
|
|
129
|
+
// moved rather than being deleted, and it moved in both directions.
|
|
130
|
+
// ONE case and ONE store boot for the whole token noun, deliberately. Each
|
|
131
|
+
// `readData` here boots its own runtime — which is the point of this file,
|
|
132
|
+
// since a fresh install is what is under test — and the embedded pack is the
|
|
133
|
+
// expensive part of that. Three separate cases meant three boots of a
|
|
134
|
+
// 53,467-triple store for three claims about the same install, which is a
|
|
135
|
+
// cost this file pays under every parallel run for no extra coverage.
|
|
136
|
+
it("the token noun answers a first install: rows, a named symbol, and honest emptiness", async () => {
|
|
137
|
+
const cwd = emptyCwd();
|
|
138
|
+
const runtime = bootRuntime(JSON_FLAGS, cwd);
|
|
139
|
+
|
|
140
|
+
const read = async (
|
|
141
|
+
verb: VerbSpec,
|
|
142
|
+
params: Record<string, unknown> = {},
|
|
143
|
+
): Promise<unknown> => {
|
|
144
|
+
const outcome = await executeVerb(verb, params, NO_MUTATION, runtime);
|
|
145
|
+
return (JSON.parse(outcome.stdout as string) as { data: unknown }).data;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// The symbols resolve offline, from the embedded pack, with no build.
|
|
149
|
+
const rows = (await read(verbOf(tokenModule, "token list"))) as {
|
|
150
|
+
name: string;
|
|
151
|
+
}[];
|
|
152
|
+
expect(rows.length).toBeGreaterThan(0);
|
|
153
|
+
for (const row of rows) expect(row.name).toBeTruthy();
|
|
154
|
+
|
|
155
|
+
// Membership, never a count — but asserted through a FILTER rather than
|
|
156
|
+
// through the unfiltered page, because this is the first population large
|
|
157
|
+
// enough for the page to matter: 436 symbols sort before `color.text`, so
|
|
158
|
+
// it is not on the first page and an unfiltered `toContain` would be
|
|
159
|
+
// testing the alphabet. A filter compiles INTO the query, so it answers
|
|
160
|
+
// from the whole population however the rows happen to page.
|
|
161
|
+
const matched = (await read(verbOf(tokenModule, "token list"), {
|
|
162
|
+
search: "color.text",
|
|
163
|
+
})) as { name: string }[];
|
|
164
|
+
expect(matched.map((row) => row.name)).toContain("color.text");
|
|
165
|
+
|
|
166
|
+
// The bindings between blocks and symbols now ride the pack too — they
|
|
167
|
+
// are derived from the component anatomies the embedded snapshot carries —
|
|
168
|
+
// so this verb ANSWERS on a first install where it used to be the honest
|
|
169
|
+
// emptiness this describe was written around. The claim moved rather than
|
|
170
|
+
// being deleted: what a first install owes the reader is a usable answer,
|
|
171
|
+
// and the columns that make a row usable are asserted here.
|
|
172
|
+
const consumers = (await read(verbOf(tokenModule, "token consumers"))) as {
|
|
173
|
+
block: string;
|
|
174
|
+
via?: string;
|
|
175
|
+
symbol: string;
|
|
176
|
+
}[];
|
|
177
|
+
expect(consumers.length).toBeGreaterThan(0);
|
|
178
|
+
for (const row of consumers) {
|
|
179
|
+
// The CONSUMING block, which is the fact the verb exists for, and the
|
|
180
|
+
// via only where the binding came from another block's tree.
|
|
181
|
+
expect(row.block).toBeTruthy();
|
|
182
|
+
expect(row.symbol).toBeTruthy();
|
|
183
|
+
if (row.via) expect(row.via).not.toBe(row.block);
|
|
184
|
+
}
|
|
120
185
|
});
|
|
121
186
|
|
|
122
187
|
it("prompt list exits calmly with no prompts (the graph carries no ds:Prompt)", async () => {
|
|
@@ -104,9 +104,10 @@ describe("MCP lifecycle — cold store recovers after sources_update (E2, C1)",
|
|
|
104
104
|
const names = (warm.data as { name: string }[])
|
|
105
105
|
.map((row) => row.name)
|
|
106
106
|
.sort();
|
|
107
|
-
// The whole pack
|
|
108
|
-
//
|
|
109
|
-
//
|
|
107
|
+
// The whole pack: no channel hides Beta Badge, no tier join hides the
|
|
108
|
+
// untiered Orphan Widget, and the tier scope admits the rest because every
|
|
109
|
+
// tier this fixture declares is top-level. Add a nested one upstream and
|
|
110
|
+
// this set becomes the default scope's, not the pack's.
|
|
110
111
|
expect(names).toEqual(["Beta Badge", "Button", "Card", "Orphan Widget"]);
|
|
111
112
|
});
|
|
112
113
|
});
|
|
@@ -22,6 +22,7 @@ import { runChecks } from "../../capabilities/doctor/runChecks.js";
|
|
|
22
22
|
import { capabilities } from "../../capabilities/index.js";
|
|
23
23
|
import { buildUpdateTask } from "../../capabilities/sources/runUpdate.js";
|
|
24
24
|
import { loadEffectiveModules } from "../../kernel/packs/collect.js";
|
|
25
|
+
import type { PackPage } from "../../kernel/packs/types.js";
|
|
25
26
|
import { packDir, readActivePack } from "../../kernel/runtime/paths.js";
|
|
26
27
|
import type { VerbSpec } from "../../kernel/spec/types.js";
|
|
27
28
|
import {
|
|
@@ -103,7 +104,7 @@ describe("a package-declared noun answers reads (in-process)", () => {
|
|
|
103
104
|
const list = recipe?.verbs.find(
|
|
104
105
|
(verb) => verb.path.join(" ") === "recipe list",
|
|
105
106
|
) as VerbSpec;
|
|
106
|
-
const rows = (await list.run({}, graph.runtime)) as
|
|
107
|
+
const { rows } = (await list.run({}, graph.runtime)) as PackPage;
|
|
107
108
|
expect(rows.map((row) => row.name)).toEqual(["Soup", "Stew"]);
|
|
108
109
|
});
|
|
109
110
|
|
|
@@ -114,31 +114,34 @@ describe("every MCP tool is callable and returns a well-formed envelope (B4)", (
|
|
|
114
114
|
expect(everyExposedVerb.length).toBeGreaterThan(0);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
it.each(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
it.each(everyExposedVerb)(
|
|
118
|
+
"$tool: callable, well-formed envelope, annotations match capability.mutates",
|
|
119
|
+
async (v) => {
|
|
120
|
+
const tool = v.tool as string;
|
|
121
|
+
const args = representativeArgs(v);
|
|
122
|
+
const result = await mcp.callTool(tool, args);
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
expect(typeof result.ok).toBe("boolean");
|
|
125
|
+
if (result.ok) {
|
|
126
|
+
expect("data" in result).toBe(true);
|
|
127
|
+
expect(typeof result.meta).toBe("object");
|
|
128
|
+
} else {
|
|
129
|
+
const error = result.error as { code?: unknown; message?: unknown };
|
|
130
|
+
expect(typeof error.code).toBe("string");
|
|
131
|
+
expect(typeof error.message).toBe("string");
|
|
132
|
+
}
|
|
133
133
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
134
|
+
const registered = registeredTools.find((t) => t.name === tool);
|
|
135
|
+
expect(registered).toBeDefined();
|
|
136
|
+
const annotations = registered?.annotations as
|
|
137
|
+
| { readOnlyHint?: boolean; destructiveHint?: boolean }
|
|
138
|
+
| undefined;
|
|
139
|
+
expect(annotations?.readOnlyHint).toBe(!v.mutates);
|
|
140
|
+
if (v.spec.capability.destructive !== undefined) {
|
|
141
|
+
expect(annotations?.destructiveHint).toBe(
|
|
142
|
+
v.spec.capability.destructive,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
);
|
|
144
147
|
});
|
|
@@ -197,28 +197,30 @@ describe("read-noun parity — every list/lookup/extra verb (B5)", () => {
|
|
|
197
197
|
});
|
|
198
198
|
});
|
|
199
199
|
|
|
200
|
-
it.each(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
200
|
+
it.each(lookupVerbs)(
|
|
201
|
+
"$noun lookup: CLI --format json == MCP, for a known name",
|
|
202
|
+
async (v) => {
|
|
203
|
+
const name = firstNameByNoun.get(v.noun);
|
|
204
|
+
if (!name) return;
|
|
205
|
+
await assertCliMcpParity({
|
|
206
|
+
modules: capabilities,
|
|
207
|
+
verb: v.spec,
|
|
208
|
+
tool: v.tool as string,
|
|
209
|
+
cwd: fixture.cwd,
|
|
210
|
+
params: { name: [name] },
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
);
|
|
213
214
|
|
|
214
|
-
it.each(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
215
|
+
it.each(extraListShapedVerbs)(
|
|
216
|
+
"$noun $verb: CLI --format json == MCP",
|
|
217
|
+
async (v) => {
|
|
218
|
+
await assertCliMcpParity({
|
|
219
|
+
modules: capabilities,
|
|
220
|
+
verb: v.spec,
|
|
221
|
+
tool: v.tool as string,
|
|
222
|
+
cwd: fixture.cwd,
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
);
|
|
224
226
|
});
|
|
@@ -202,11 +202,21 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
202
202
|
"kind": "tool",
|
|
203
203
|
"passed": true,
|
|
204
204
|
},
|
|
205
|
+
{
|
|
206
|
+
"id": "tool-token-consumers-answers-or-recovers",
|
|
207
|
+
"kind": "tool",
|
|
208
|
+
"passed": true,
|
|
209
|
+
},
|
|
205
210
|
{
|
|
206
211
|
"id": "tool-token-lookup-addresses-only-what-list-publishes",
|
|
207
212
|
"kind": "tool",
|
|
208
213
|
"passed": true,
|
|
209
214
|
},
|
|
215
|
+
{
|
|
216
|
+
"id": "tool-token-lookup-dotted-name-resolves-with-its-definitions",
|
|
217
|
+
"kind": "tool",
|
|
218
|
+
"passed": true,
|
|
219
|
+
},
|
|
210
220
|
{
|
|
211
221
|
"id": "tool-token-noun-is-read-only",
|
|
212
222
|
"kind": "tool",
|
|
@@ -217,10 +227,20 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
217
227
|
"kind": "tool",
|
|
218
228
|
"passed": true,
|
|
219
229
|
},
|
|
230
|
+
{
|
|
231
|
+
"id": "tool-token-values-narrows-to-one-symbol",
|
|
232
|
+
"kind": "tool",
|
|
233
|
+
"passed": true,
|
|
234
|
+
},
|
|
220
235
|
{
|
|
221
236
|
"id": "tool-upgrade-is-plan-first",
|
|
222
237
|
"kind": "tool",
|
|
223
238
|
"passed": true,
|
|
224
239
|
},
|
|
240
|
+
{
|
|
241
|
+
"id": "tool-variable-lookup-resolves-without-the-leading-dashes",
|
|
242
|
+
"kind": "tool",
|
|
243
|
+
"passed": true,
|
|
244
|
+
},
|
|
225
245
|
]
|
|
226
246
|
`;
|
|
@@ -186,7 +186,13 @@ export const effectfulEvalCases: readonly EvalCase[] = [
|
|
|
186
186
|
assert.ok(!tools.includes("token_add-config"));
|
|
187
187
|
assert.deepEqual(
|
|
188
188
|
tools.filter((name) => name.startsWith("token")).sort(),
|
|
189
|
-
[
|
|
189
|
+
[
|
|
190
|
+
"token_consumers",
|
|
191
|
+
"token_list",
|
|
192
|
+
"token_lookup",
|
|
193
|
+
"token_sample",
|
|
194
|
+
"token_values",
|
|
195
|
+
],
|
|
190
196
|
);
|
|
191
197
|
});
|
|
192
198
|
},
|
|
@@ -165,7 +165,7 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
165
165
|
id: "tool-token-lookup-addresses-only-what-list-publishes",
|
|
166
166
|
kind: "tool",
|
|
167
167
|
input:
|
|
168
|
-
"a
|
|
168
|
+
"a dt:TokenSymbol carrying no rdfs:label appears in no token_list row, resolves through no token_lookup name, and is drawn by no token_sample.",
|
|
169
169
|
async expect() {
|
|
170
170
|
await withCanonicalFixture(ALL_VISIBLE_CONFIG, async (mcp) => {
|
|
171
171
|
const list = await mcp.callTool("token_list");
|
|
@@ -175,11 +175,11 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
175
175
|
);
|
|
176
176
|
assert.ok(published.size > 0, "expected token_list to publish rows");
|
|
177
177
|
// The IRI-derived spellings the fallback would have minted for
|
|
178
|
-
// `
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
]) {
|
|
178
|
+
// `dt:legacy.borderRadius` — the local name, and the same local name
|
|
179
|
+
// with its dots published as slashes, which is what the kernel's
|
|
180
|
+
// derivation actually does and the reason the token noun declares no
|
|
181
|
+
// fallback at all.
|
|
182
|
+
for (const derived of ["legacy.borderRadius", "legacy/borderRadius"]) {
|
|
183
183
|
assert.ok(
|
|
184
184
|
!published.has(derived),
|
|
185
185
|
`token_list must not publish ${derived}`,
|
|
@@ -265,15 +265,19 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
265
265
|
id: "content-canonical-graph-has-4-components",
|
|
266
266
|
kind: "content",
|
|
267
267
|
input:
|
|
268
|
-
|
|
268
|
+
'the canonical fixture graph carries 4 ds:Component individuals (Button, Modal, LXD Panel, Beta Widget); block_list {tier:"all"} also surfaces the untiered Button Icon subcomponent (A2).',
|
|
269
269
|
async expect() {
|
|
270
270
|
await withCanonicalFixture(ALL_VISIBLE_CONFIG, async (mcp) => {
|
|
271
|
-
|
|
271
|
+
// `tier: "all"` because the claim is about the POPULATION, and the
|
|
272
|
+
// default tier scope answers from the top-level tiers alone — LXD Panel
|
|
273
|
+
// is two levels down. The scope's own narrowing is asserted where that
|
|
274
|
+
// is the claim (`behavioral/journeys.cli.test.ts`).
|
|
275
|
+
const result = await mcp.callTool("block_list", { tier: "all" });
|
|
272
276
|
const names = (result.data as { name: string }[])
|
|
273
277
|
.map((r) => r.name)
|
|
274
278
|
.sort();
|
|
275
|
-
//
|
|
276
|
-
//
|
|
279
|
+
// Every tier, and nothing else filtered: the 4 tiered components plus
|
|
280
|
+
// the untiered Button Icon subcomponent (A2).
|
|
277
281
|
assert.deepEqual(names, [
|
|
278
282
|
"Beta Widget",
|
|
279
283
|
"Button",
|
|
@@ -422,7 +426,10 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
422
426
|
const normal = await namesUnder(CANONICAL_CONFIG);
|
|
423
427
|
const prerelease = await namesUnder(ALL_VISIBLE_CONFIG);
|
|
424
428
|
// The signed-off consequence: an experimental block is visible to
|
|
425
|
-
// everyone, on every channel
|
|
429
|
+
// everyone, on every channel. The TIER scope narrows these reads (both
|
|
430
|
+
// configs set no tier, so both answer from the top-level tiers) and the
|
|
431
|
+
// channel narrows neither — which is exactly the asymmetry this case
|
|
432
|
+
// holds: the two answers are equal, and the beta block is in both.
|
|
426
433
|
assert.ok(normal.includes("Beta Widget"));
|
|
427
434
|
assert.deepEqual(normal, prerelease);
|
|
428
435
|
},
|
|
@@ -456,6 +463,88 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
456
463
|
});
|
|
457
464
|
},
|
|
458
465
|
},
|
|
466
|
+
// The token-graph nouns run against the SHARED env rather than a fixture:
|
|
467
|
+
// the canonical fixture carries no token strata, and what these cases are
|
|
468
|
+
// for is that the SHIPPED pack answers them — the name literals both nouns
|
|
469
|
+
// key on ship with the pack, so a fixture would prove nothing about that.
|
|
470
|
+
{
|
|
471
|
+
id: "tool-token-lookup-dotted-name-resolves-with-its-definitions",
|
|
472
|
+
kind: "tool",
|
|
473
|
+
input:
|
|
474
|
+
"token_lookup {name:[color.text]} resolves the dotted name and carries definitions, coverage and values.",
|
|
475
|
+
async expect({ mcp }) {
|
|
476
|
+
const result = await mcp.callTool("token_lookup", {
|
|
477
|
+
name: ["color.text"],
|
|
478
|
+
});
|
|
479
|
+
assert.equal(result.ok, true);
|
|
480
|
+
const entity = (result.data as { results: Record<string, unknown>[] })
|
|
481
|
+
.results[0];
|
|
482
|
+
assert.equal(entity?.name, "color.text");
|
|
483
|
+
for (const section of ["definitions", "coverage", "values"]) {
|
|
484
|
+
assert.ok(
|
|
485
|
+
Array.isArray(entity?.[section]) &&
|
|
486
|
+
(entity[section] as unknown[]).length > 0,
|
|
487
|
+
`expected a non-empty ${section} array`,
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
id: "tool-variable-lookup-resolves-without-the-leading-dashes",
|
|
494
|
+
kind: "tool",
|
|
495
|
+
input:
|
|
496
|
+
"variable_lookup {name:[color-text]} resolves the dash-stripped CSS name and names the symbol it stands for.",
|
|
497
|
+
async expect({ mcp }) {
|
|
498
|
+
const result = await mcp.callTool("variable_lookup", {
|
|
499
|
+
name: ["color-text"],
|
|
500
|
+
});
|
|
501
|
+
assert.equal(result.ok, true);
|
|
502
|
+
const entity = (result.data as { results: Record<string, unknown>[] })
|
|
503
|
+
.results[0];
|
|
504
|
+
assert.equal(entity?.name, "color-text");
|
|
505
|
+
assert.equal(entity?.symbol, "color.text");
|
|
506
|
+
assert.ok(
|
|
507
|
+
Array.isArray(entity?.declarations) &&
|
|
508
|
+
(entity.declarations as unknown[]).length > 0,
|
|
509
|
+
"expected a non-empty declarations array",
|
|
510
|
+
);
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
id: "tool-token-values-narrows-to-one-symbol",
|
|
515
|
+
kind: "tool",
|
|
516
|
+
input:
|
|
517
|
+
"token_values {symbol:color.text} returns only that symbol's materialised positions, each with a value or a derivation.",
|
|
518
|
+
async expect({ mcp }) {
|
|
519
|
+
const result = await mcp.callTool("token_values", {
|
|
520
|
+
symbol: "color.text",
|
|
521
|
+
});
|
|
522
|
+
assert.equal(result.ok, true);
|
|
523
|
+
const rows = result.data as Record<string, string>[];
|
|
524
|
+
assert.ok(rows.length > 0, "expected at least one resolved value");
|
|
525
|
+
for (const row of rows) {
|
|
526
|
+
assert.equal(row.symbol, "color.text");
|
|
527
|
+
assert.ok(
|
|
528
|
+
row.value !== undefined || row.derivedFrom !== undefined,
|
|
529
|
+
"every row carries a value or a derivation",
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
id: "tool-token-consumers-answers-or-recovers",
|
|
536
|
+
kind: "tool",
|
|
537
|
+
input:
|
|
538
|
+
"token_consumers {} either returns binding rows or reports a recoverable empty result — never an error.",
|
|
539
|
+
async expect({ mcp }) {
|
|
540
|
+
// Deliberately not asserting emptiness: the design-system packs will
|
|
541
|
+
// record bindings, and a case pinning the empty answer would fail on
|
|
542
|
+
// that correct change. What must hold either way is that the call
|
|
543
|
+
// SUCCEEDS.
|
|
544
|
+
const result = await mcp.callTool("token_consumers", {});
|
|
545
|
+
assert.equal(result.ok, true);
|
|
546
|
+
},
|
|
547
|
+
},
|
|
459
548
|
{
|
|
460
549
|
id: "prompt-block-question-maps-to-block-lookup",
|
|
461
550
|
kind: "prompt",
|
|
@@ -32,6 +32,12 @@ export const BLOCK_PREFIXES: Readonly<Record<string, string>> = {
|
|
|
32
32
|
owl: "http://www.w3.org/2002/07/owl#",
|
|
33
33
|
rdfs: "http://www.w3.org/2000/01/rdf-schema#",
|
|
34
34
|
xsd: "http://www.w3.org/2001/XMLSchema#",
|
|
35
|
+
// The token-binding record spans three vocabularies exactly as the live
|
|
36
|
+
// graph does: the design system owns the record and its edges, the token
|
|
37
|
+
// ontology the symbol it consumes, and the anatomy DSL the style key and
|
|
38
|
+
// state it applies at.
|
|
39
|
+
anatomy: "https://anatomy.canonical.com/",
|
|
40
|
+
dt: "https://dt.canonical.com/",
|
|
35
41
|
};
|
|
36
42
|
|
|
37
43
|
/**
|
|
@@ -52,6 +58,8 @@ export const BLOCK_TTL = `
|
|
|
52
58
|
@prefix owl: <http://www.w3.org/2002/07/owl#> .
|
|
53
59
|
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
|
|
54
60
|
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
61
|
+
@prefix anatomy: <https://anatomy.canonical.com/> .
|
|
62
|
+
@prefix dt: <https://dt.canonical.com/> .
|
|
55
63
|
|
|
56
64
|
# ---- Ontology (TBox) ----
|
|
57
65
|
ds:UIBlock a owl:Class .
|
|
@@ -87,6 +95,29 @@ ds:optional a owl:DatatypeProperty ; rdfs:domain ds:BlockProperty ; rdfs:range x
|
|
|
87
95
|
# Domain is ds:Component (not ds:UIBlock) — reached via subtype scoping.
|
|
88
96
|
ds:hasSubcomponent a owl:ObjectProperty ; rdfs:domain ds:Component ; rdfs:range ds:Subcomponent .
|
|
89
97
|
|
|
98
|
+
# The token-binding record, modelled with the live graph's split ownership —
|
|
99
|
+
# which is what makes the block lookup's \`tokens\` expand a SPARQL-lane one.
|
|
100
|
+
#
|
|
101
|
+
# The five ds: edges carry a domain and a range, so ke-graphql derives a field
|
|
102
|
+
# for each and a document could read them. \`anatomy:styleKey\` and
|
|
103
|
+
# \`anatomy:styleState\` carry NO rdfs:domain, because they belong to the anatomy
|
|
104
|
+
# vocabulary and apply to every styled thing rather than to this record — so no
|
|
105
|
+
# field is derived for either, and a generated document drops them in SILENCE.
|
|
106
|
+
# They are two of the six columns that IDENTIFY a binding, so dropping them
|
|
107
|
+
# leaves rows a reader cannot tell apart. Preserved here deliberately: change
|
|
108
|
+
# the fixture to declare a domain and the suite stops testing the condition the
|
|
109
|
+
# lane exists for.
|
|
110
|
+
ds:TokenBinding a owl:Class .
|
|
111
|
+
ds:hasTokenBinding a owl:ObjectProperty ; rdfs:domain ds:UIBlock ; rdfs:range ds:TokenBinding .
|
|
112
|
+
ds:consumesSymbol a owl:ObjectProperty, owl:FunctionalProperty ;
|
|
113
|
+
rdfs:domain ds:TokenBinding ; rdfs:range dt:TokenSymbol .
|
|
114
|
+
ds:viaBlock a owl:ObjectProperty ; rdfs:domain ds:TokenBinding ; rdfs:range ds:UIBlock .
|
|
115
|
+
ds:rank a owl:DatatypeProperty ; rdfs:domain ds:TokenBinding ; rdfs:range xsd:integer .
|
|
116
|
+
ds:node a owl:DatatypeProperty ; rdfs:domain ds:TokenBinding ; rdfs:range xsd:string .
|
|
117
|
+
dt:TokenSymbol a owl:Class .
|
|
118
|
+
anatomy:styleKey a owl:DatatypeProperty ; rdfs:range xsd:string .
|
|
119
|
+
anatomy:styleState a owl:DatatypeProperty ; rdfs:range xsd:string .
|
|
120
|
+
|
|
90
121
|
# ---- Individuals (ABox) ----
|
|
91
122
|
ds:global a ds:Tier ; ds:name "global" .
|
|
92
123
|
|
|
@@ -101,7 +132,9 @@ ds:button a ds:Component ;
|
|
|
101
132
|
ds:figmaLink "https://figma.com/design/example/Button" ;
|
|
102
133
|
ds:hasModifierFamily ds:family.importance, ds:family.density ;
|
|
103
134
|
ds:hasProperty ds:button.prop.disabled ;
|
|
104
|
-
ds:hasSubcomponent ds:button.icon
|
|
135
|
+
ds:hasSubcomponent ds:button.icon ;
|
|
136
|
+
ds:hasTokenBinding ds:binding.button.bg1, ds:binding.button.bg2,
|
|
137
|
+
ds:binding.button.text, ds:binding.button.icon .
|
|
105
138
|
|
|
106
139
|
ds:modal a ds:Component ;
|
|
107
140
|
ds:name "Modal" ;
|
|
@@ -111,10 +144,49 @@ ds:modal a ds:Component ;
|
|
|
111
144
|
ds:guidelines "Always provide an explicit close affordance." ;
|
|
112
145
|
ds:anatomyDsl "root: dialog; children: header, body, footer" ;
|
|
113
146
|
ds:hasModifierFamily ds:family.size ;
|
|
114
|
-
ds:hasProperty ds:modal.prop.open
|
|
147
|
+
ds:hasProperty ds:modal.prop.open ;
|
|
148
|
+
ds:hasTokenBinding ds:binding.modal.button .
|
|
115
149
|
|
|
116
150
|
ds:button.icon a ds:Subcomponent ; ds:name "Button Icon" .
|
|
117
151
|
|
|
152
|
+
# The symbols the bindings consume, addressed by the dotted name the token
|
|
153
|
+
# noun publishes — which is what the expand's \`ds:consumesSymbol/rdfs:label\`
|
|
154
|
+
# path reads, so a row here is an address \`token lookup\` takes.
|
|
155
|
+
dt:color.background a dt:TokenSymbol ; rdfs:label "color.background" .
|
|
156
|
+
dt:color.background.hover a dt:TokenSymbol ; rdfs:label "color.background.hover" .
|
|
157
|
+
dt:color.text a dt:TokenSymbol ; rdfs:label "color.text" .
|
|
158
|
+
dt:color.icon a dt:TokenSymbol ; rdfs:label "color.icon" .
|
|
159
|
+
|
|
160
|
+
# Button's own tree. Two records share a node and a key and differ ONLY in
|
|
161
|
+
# state and rank — the pair that proves the two columns the GraphQL lane cannot
|
|
162
|
+
# see are the ones that tell the rows apart. The declaration order here is
|
|
163
|
+
# deliberately NOT the reading order (node, then key, then rank), so the
|
|
164
|
+
# expand's own ORDER BY is what puts them right.
|
|
165
|
+
ds:binding.button.bg2 a ds:TokenBinding ;
|
|
166
|
+
ds:consumesSymbol dt:color.background.hover ;
|
|
167
|
+
anatomy:styleKey "appearance.background" ; anatomy:styleState "hover" ;
|
|
168
|
+
ds:rank 2 ; ds:viaBlock ds:button ; ds:node "$root" .
|
|
169
|
+
ds:binding.button.bg1 a ds:TokenBinding ;
|
|
170
|
+
ds:consumesSymbol dt:color.background ;
|
|
171
|
+
anatomy:styleKey "appearance.background" ; anatomy:styleState "default" ;
|
|
172
|
+
ds:rank 1 ; ds:viaBlock ds:button ; ds:node "$root" .
|
|
173
|
+
ds:binding.button.text a ds:TokenBinding ;
|
|
174
|
+
ds:consumesSymbol dt:color.text ;
|
|
175
|
+
anatomy:styleKey "typography.color" ; anatomy:styleState "default" ;
|
|
176
|
+
ds:rank 1 ; ds:viaBlock ds:button ; ds:node "$root" .
|
|
177
|
+
# Reached through the subcomponent Button's anatomy embeds, so its via DIFFERS
|
|
178
|
+
# from the block and must print.
|
|
179
|
+
ds:binding.button.icon a ds:TokenBinding ;
|
|
180
|
+
ds:consumesSymbol dt:color.icon ;
|
|
181
|
+
anatomy:styleKey "appearance.background" ; anatomy:styleState "default" ;
|
|
182
|
+
ds:rank 1 ; ds:viaBlock ds:button.icon ; ds:node "$root/icon" .
|
|
183
|
+
# Modal consumes nothing of its own: its one record is Button's, reached
|
|
184
|
+
# through the Button its anatomy embeds.
|
|
185
|
+
ds:binding.modal.button a ds:TokenBinding ;
|
|
186
|
+
ds:consumesSymbol dt:color.background ;
|
|
187
|
+
anatomy:styleKey "appearance.background" ; anatomy:styleState "default" ;
|
|
188
|
+
ds:rank 1 ; ds:viaBlock ds:button ; ds:node "$root/footer" .
|
|
189
|
+
|
|
118
190
|
ds:button.prop.disabled a ds:BlockProperty ;
|
|
119
191
|
ds:name "disabled" ; ds:propertyType "boolean" ; ds:optional true .
|
|
120
192
|
ds:modal.prop.open a ds:BlockProperty ;
|
|
@@ -176,10 +248,17 @@ ${ROSTER_MEMBERS}
|
|
|
176
248
|
* parity, ontology and GraphQL-engine suites assert over the base graph and
|
|
177
249
|
* must keep seeing exactly two components.
|
|
178
250
|
*
|
|
179
|
-
* It models the
|
|
251
|
+
* It models the four shapes the addressing path gets wrong: two components
|
|
180
252
|
* sharing one `ds:name` (declared zeta-first so the store's enumeration order
|
|
181
|
-
* and IRI order DISAGREE),
|
|
182
|
-
*
|
|
253
|
+
* and IRI order DISAGREE), a component carrying no `ds:name` at all (reachable
|
|
254
|
+
* only by IRI, the way 131 of the 144 live code standards are), and a component
|
|
255
|
+
* whose `ds:name` is PADDED with a trailing space.
|
|
256
|
+
*
|
|
257
|
+
* That last one is copied from the live graph, not invented: 66 shipped names
|
|
258
|
+
* end in a space, carried across by the transform that reads them out of the
|
|
259
|
+
* source document, and `block lookup Timeline` used to answer
|
|
260
|
+
* ENTITY_NOT_FOUND while suggesting "Timeline " back. It is spelled with the
|
|
261
|
+
* live name so the fixture reads as the report it came from.
|
|
183
262
|
*
|
|
184
263
|
* The shared name is a SHAPE probe, not the live ambiguity: neither chip's tier
|
|
185
264
|
* outranks the other, so this fixture can only prove that both are returned in a
|
|
@@ -203,4 +282,9 @@ ds:alpha.chip a ds:Component ;
|
|
|
203
282
|
ds:nameless.widget a ds:Component ;
|
|
204
283
|
ds:tier ds:global ;
|
|
205
284
|
ds:summary "Carries no ds:name; addressable only by IRI." .
|
|
285
|
+
|
|
286
|
+
ds:padded.timeline a ds:Component ;
|
|
287
|
+
ds:name "Timeline " ;
|
|
288
|
+
ds:tier ds:global ;
|
|
289
|
+
ds:summary "Its ds:name carries the source document's trailing space." .
|
|
206
290
|
`;
|