@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
|
@@ -55,48 +55,52 @@ afterAll(async () => {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
describe("agent session — list, pick, lookup (B1)", () => {
|
|
58
|
-
it.each(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
it.each(browsableNouns)(
|
|
59
|
+
"%s: list -> pick first -> lookup resolves it",
|
|
60
|
+
async (noun) => {
|
|
61
|
+
const list = await mcp.callTool(`${noun}_list`);
|
|
62
|
+
expect(list.ok).toBe(true);
|
|
63
|
+
const rows = list.data as { name: string }[];
|
|
64
|
+
expect(rows.length).toBeGreaterThan(0);
|
|
65
|
+
const first = rows[0] as { name: string };
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
const lookup = await mcp.callTool(`${noun}_lookup`, {
|
|
68
|
+
name: [first.name],
|
|
69
|
+
});
|
|
70
|
+
expect(lookup.ok).toBe(true);
|
|
71
|
+
const data = lookup.data as {
|
|
72
|
+
results: { name: string }[];
|
|
73
|
+
errors: unknown[];
|
|
74
|
+
};
|
|
75
|
+
expect(data.errors).toEqual([]);
|
|
76
|
+
expect(data.results[0]?.name).toBe(first.name);
|
|
77
|
+
},
|
|
78
|
+
);
|
|
76
79
|
|
|
77
|
-
it.each(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
it.each(browsableNouns)(
|
|
81
|
+
"%s: a BATCH lookup with one hit reports the miss without failing the call",
|
|
82
|
+
async (noun) => {
|
|
83
|
+
// `makeLookupRun` (kernel/packs/runBodies.ts) throws on a TOTAL miss (see
|
|
84
|
+
// the errorMatrix.mcp.test.ts B3 suite) — a partial batch is the "miss
|
|
85
|
+
// reported, call not failed" shape (an ADAPTATION of the plan's B1/B3
|
|
86
|
+
// wording, which described a single-name miss; verified against the
|
|
87
|
+
// live behavior).
|
|
88
|
+
const list = await mcp.callTool(`${noun}_list`);
|
|
89
|
+
const rows = list.data as { name: string }[];
|
|
90
|
+
const known = (rows[0] as { name: string }).name;
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const result = await mcp.callTool(`${noun}_lookup`, {
|
|
93
|
+
name: [known, "zzz-definitely-not-a-real-entity"],
|
|
94
|
+
});
|
|
95
|
+
expect(result.ok).toBe(true);
|
|
96
|
+
const data = result.data as {
|
|
97
|
+
results: { name: string }[];
|
|
98
|
+
errors: { code: string }[];
|
|
99
|
+
};
|
|
100
|
+
expect(data.results[0]?.name).toBe(known);
|
|
101
|
+
expect(data.errors[0]?.code).toBe("ENTITY_NOT_FOUND");
|
|
102
|
+
},
|
|
103
|
+
);
|
|
100
104
|
});
|
|
101
105
|
|
|
102
106
|
describe("agent session — the categories journey, if the live surface declares one (B1)", () => {
|
|
@@ -65,12 +65,13 @@ describe("verb-level candidates: the SET matches the live surface", () => {
|
|
|
65
65
|
expect(multiVerbNouns.length).toBeGreaterThan(0);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it.each(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
it.each(multiVerbNouns)(
|
|
69
|
+
"%s: candidates == its live verb set",
|
|
70
|
+
async (noun, verbs) => {
|
|
71
|
+
const candidates = await runComplete([noun, ""], capabilities);
|
|
72
|
+
expect([...candidates].sort()).toEqual([...verbs].sort());
|
|
73
|
+
},
|
|
74
|
+
);
|
|
74
75
|
});
|
|
75
76
|
|
|
76
77
|
describe("flags are kebab-cased at emission (the live, testable guarantee)", () => {
|
|
@@ -69,47 +69,49 @@ describe("disclosure lookups declare the aligned canonical level set (B4)", () =
|
|
|
69
69
|
// the full `[summary, standard, detailed]`, so a config `detail=standard` named
|
|
70
70
|
// a level block never advertised. Every disclosure lookup now declares the same
|
|
71
71
|
// canonical ladder; per-noun DEFAULTS may still differ (domain-tuned).
|
|
72
|
-
it.each(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
it.each(disclosureLookupVerbs)(
|
|
73
|
+
"$noun: levels === the canonical ladder",
|
|
74
|
+
(v) => {
|
|
75
|
+
expect(v.spec.disclosure?.levels).toEqual([...DETAIL_LEVELS]);
|
|
76
|
+
},
|
|
77
|
+
);
|
|
77
78
|
});
|
|
78
79
|
|
|
79
80
|
describe("detail:summary vs detail:detailed — key-set growth (B6)", () => {
|
|
80
|
-
it.each(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
it.each(disclosureLookupVerbs)(
|
|
82
|
+
"%s_lookup: detailed carries every summary key plus at least one more",
|
|
83
|
+
async (v) => {
|
|
84
|
+
const noun = v.noun;
|
|
85
|
+
const list = await mcp.callTool(`${noun}_list`);
|
|
86
|
+
const rows = list.data as { name: string }[];
|
|
87
|
+
const name = rows[0]?.name;
|
|
88
|
+
expect(name).toBeDefined();
|
|
89
|
+
if (!name) return;
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
91
|
+
const summary = await mcp.callTool(`${noun}_lookup`, {
|
|
92
|
+
name: [name],
|
|
93
|
+
detail: "summary",
|
|
94
|
+
});
|
|
95
|
+
const detailed = await mcp.callTool(`${noun}_lookup`, {
|
|
96
|
+
name: [name],
|
|
97
|
+
detail: "detailed",
|
|
98
|
+
});
|
|
99
|
+
expect(summary.ok).toBe(true);
|
|
100
|
+
expect(detailed.ok).toBe(true);
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
const summaryEntity = (
|
|
103
|
+
summary.data as { results: Record<string, unknown>[] }
|
|
104
|
+
).results[0] as Record<string, unknown>;
|
|
105
|
+
const detailedEntity = (
|
|
106
|
+
detailed.data as { results: Record<string, unknown>[] }
|
|
107
|
+
).results[0] as Record<string, unknown>;
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
const summaryKeys = new Set(Object.keys(summaryEntity));
|
|
110
|
+
const detailedKeys = new Set(Object.keys(detailedEntity));
|
|
111
|
+
for (const key of summaryKeys) {
|
|
112
|
+
expect(detailedKeys.has(key)).toBe(true);
|
|
113
|
+
}
|
|
114
|
+
expect(detailedKeys.size).toBeGreaterThan(summaryKeys.size);
|
|
115
|
+
},
|
|
116
|
+
);
|
|
115
117
|
});
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
27
27
|
import { capabilities } from "../../capabilities/index.js";
|
|
28
|
+
import { RESERVED_STORY_PARAMS } from "../../kernel/packs/types.js";
|
|
28
29
|
import {
|
|
29
30
|
ALL_VISIBLE_CONFIG,
|
|
30
31
|
CANONICAL_TTL,
|
|
@@ -37,16 +38,25 @@ import { projectMcp } from "../helpers/projectMcp.js";
|
|
|
37
38
|
import { listVerbs, lookupVerbs } from "./liveReadSurface.js";
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
|
-
* List verbs with a STRING or ENUM (narrowable, non-boolean) flag
|
|
41
|
-
* `standard_list --category`. Boolean flags are
|
|
42
|
-
* value at the schema layer rather than
|
|
43
|
-
* list --all-tiers` used to be the
|
|
44
|
-
* filtering in L-OPEN-9.)
|
|
41
|
+
* List verbs with a STRING or ENUM (narrowable, non-boolean) flag the STORY
|
|
42
|
+
* itself declares — e.g. `standard_list --category`. Boolean flags are
|
|
43
|
+
* excluded: they reject a string value at the schema layer rather than
|
|
44
|
+
* narrowing to an empty result. (`block list --all-tiers` used to be the
|
|
45
|
+
* example; it retired with the hand-written filtering in L-OPEN-9.)
|
|
46
|
+
*
|
|
47
|
+
* The kernel's own params are excluded by name, from the grammar's own list.
|
|
48
|
+
* Without that, every list verb qualified the day the kernel gave them all an
|
|
49
|
+
* `--after` cursor, and four unfiltered nouns were swept for a narrowing
|
|
50
|
+
* behaviour they do not have — the assertions failed on a param that is not a
|
|
51
|
+
* filter at all.
|
|
45
52
|
*/
|
|
46
53
|
const filteredListVerbs = listVerbs
|
|
47
54
|
.map((v) => {
|
|
48
55
|
const flag = v.spec.params.find(
|
|
49
|
-
(p) =>
|
|
56
|
+
(p) =>
|
|
57
|
+
!p.positional &&
|
|
58
|
+
(p.kind === "string" || p.kind === "enum") &&
|
|
59
|
+
!RESERVED_STORY_PARAMS.includes(p.name),
|
|
50
60
|
);
|
|
51
61
|
return flag
|
|
52
62
|
? { noun: v.noun, tool: v.tool as string, param: flag.name }
|
|
@@ -73,25 +83,27 @@ afterAll(async () => {
|
|
|
73
83
|
});
|
|
74
84
|
|
|
75
85
|
describe("lookup miss — total miss fails the call (B3, adapted)", () => {
|
|
76
|
-
it.each(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
it.each(lookupVerbs.map((v) => v.noun))(
|
|
87
|
+
"%s_lookup: a single unknown name fails with ENTITY_NOT_FOUND",
|
|
88
|
+
async (noun) => {
|
|
89
|
+
const result = await mcp.callTool(`${noun}_lookup`, {
|
|
90
|
+
name: ["zzz-definitely-not-a-real-entity"],
|
|
91
|
+
});
|
|
92
|
+
expect(result.ok).toBe(false);
|
|
93
|
+
expect((result.error as { code: string }).code).toBe("ENTITY_NOT_FOUND");
|
|
94
|
+
},
|
|
95
|
+
);
|
|
85
96
|
|
|
86
|
-
it.each(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
it.each(lookupVerbs.map((v) => v.noun))(
|
|
98
|
+
"%s_lookup: an all-unknown batch ALSO fails (not a partial report)",
|
|
99
|
+
async (noun) => {
|
|
100
|
+
const result = await mcp.callTool(`${noun}_lookup`, {
|
|
101
|
+
name: ["zzz-nope-one", "zzz-nope-two"],
|
|
102
|
+
});
|
|
103
|
+
expect(result.ok).toBe(false);
|
|
104
|
+
expect((result.error as { code: string }).code).toBe("ENTITY_NOT_FOUND");
|
|
105
|
+
},
|
|
106
|
+
);
|
|
95
107
|
});
|
|
96
108
|
|
|
97
109
|
/**
|
|
@@ -116,45 +128,43 @@ describe("list — a filter value the graph does not carry is INVALID_INPUT (B3,
|
|
|
116
128
|
expect(filteredListVerbs.length).toBeGreaterThan(0);
|
|
117
129
|
});
|
|
118
130
|
|
|
119
|
-
it.each(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
[
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
it.each(filteredListVerbs)(
|
|
132
|
+
"$tool: an unobserved filter value is rejected, naming the observed ones",
|
|
133
|
+
async ({ tool, param }) => {
|
|
134
|
+
const result = await mcp.callTool(tool, {
|
|
135
|
+
[param]: "zzz-definitely-not-a-real-value",
|
|
136
|
+
});
|
|
137
|
+
expect(result.ok).toBe(false);
|
|
138
|
+
const error = result.error as { code: string; validOptions?: string[] };
|
|
139
|
+
expect(error.code).toBe("INVALID_INPUT");
|
|
140
|
+
expect(error.validOptions?.length).toBeGreaterThan(0);
|
|
141
|
+
expect(error.validOptions).not.toContain(
|
|
142
|
+
"zzz-definitely-not-a-real-value",
|
|
143
|
+
);
|
|
144
|
+
},
|
|
145
|
+
);
|
|
134
146
|
|
|
135
|
-
it.each(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
expect(
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
expect(populated).toBeGreaterThan(0);
|
|
157
|
-
});
|
|
147
|
+
it.each(filteredListVerbs)(
|
|
148
|
+
"$tool: every value the graph DOES carry narrows to a calm list",
|
|
149
|
+
async ({ tool, param }) => {
|
|
150
|
+
const rejected = await mcp.callTool(tool, { [param]: "zzz-nope" });
|
|
151
|
+
const admissible = (rejected.error as { validOptions: string[] })
|
|
152
|
+
.validOptions;
|
|
153
|
+
expect(admissible.length).toBeGreaterThan(0);
|
|
154
|
+
// EVERY admissible value is accepted, and at least one is populated. Not
|
|
155
|
+
// "the first one returns rows": the vocabulary is the graph's, so it can
|
|
156
|
+
// legitimately contain a value no row carries (a category with zero
|
|
157
|
+
// standards) — that value is a calm empty list, not a rejection, and the
|
|
158
|
+
// sweep would otherwise read a real answer as a failure.
|
|
159
|
+
let populated = 0;
|
|
160
|
+
for (const value of admissible) {
|
|
161
|
+
const result = await mcp.callTool(tool, { [param]: value });
|
|
162
|
+
expect(result.ok).toBe(true);
|
|
163
|
+
if ((result.data as unknown[]).length > 0) populated += 1;
|
|
164
|
+
}
|
|
165
|
+
expect(populated).toBeGreaterThan(0);
|
|
166
|
+
},
|
|
167
|
+
);
|
|
158
168
|
|
|
159
169
|
it("standard_list: a declared category with NO standards is a calm empty list", async () => {
|
|
160
170
|
// The case that separates "the graph is the vocabulary" from "the returned
|
|
@@ -202,14 +212,22 @@ describe("empty ≠ silence on the machine surfaces", () => {
|
|
|
202
212
|
// an agent received `{"ok":true,"data":[],"meta":{}}` and nothing else. The
|
|
203
213
|
// search path is the honest way to reach an empty list without a bad
|
|
204
214
|
// argument.
|
|
215
|
+
//
|
|
216
|
+
// The guidance leads with the question that was actually answered — the
|
|
217
|
+
// SEARCH that matched nothing, in the caller's own spelling — and the
|
|
218
|
+
// story's `emptyRecovery` follows it, as it does on an unfiltered empty
|
|
219
|
+
// answer. Leading with the recovery instead was the defect: `sources
|
|
220
|
+
// update` told a reader with a populated store to rebuild it.
|
|
205
221
|
const result = await mcp.callTool("standard_list", {
|
|
206
222
|
search: "zzz-nothing-matches-this",
|
|
207
223
|
});
|
|
208
224
|
expect(result.ok).toBe(true);
|
|
209
225
|
expect(result.data).toEqual([]);
|
|
210
226
|
const notice = (result.meta as { notice?: string }).notice ?? "";
|
|
211
|
-
expect(notice).toContain(
|
|
212
|
-
|
|
227
|
+
expect(notice).toContain(
|
|
228
|
+
"No standard matches `--search zzz-nothing-matches-this`.",
|
|
229
|
+
);
|
|
230
|
+
expect(notice).toContain("Category slugs come from the graph");
|
|
213
231
|
});
|
|
214
232
|
});
|
|
215
233
|
|
|
@@ -96,16 +96,17 @@ describe("error/recovery matrix — render shapes (A8, storeless)", () => {
|
|
|
96
96
|
}
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
it.each(MATRIX)(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
99
|
+
it.each(MATRIX)(
|
|
100
|
+
"json renders the failure envelope for $label",
|
|
101
|
+
({ error }) => {
|
|
102
|
+
const envelope = JSON.parse(renderErrorJson(error)) as {
|
|
103
|
+
ok: boolean;
|
|
104
|
+
error: { code: string };
|
|
105
|
+
};
|
|
106
|
+
expect(envelope.ok).toBe(false);
|
|
107
|
+
expect(envelope.error.code).toBe(error.code);
|
|
108
|
+
},
|
|
109
|
+
);
|
|
109
110
|
});
|
|
110
111
|
|
|
111
112
|
describe("error/recovery matrix — grounded in a real spawn (A8, e2e)", () => {
|
|
@@ -8,22 +8,29 @@
|
|
|
8
8
|
* against the fixture, rather than spawning. It still exercises the true CLI
|
|
9
9
|
* seam (typed params -> dispatch -> render), just without forking a process.
|
|
10
10
|
*
|
|
11
|
-
* CONTRACT CHANGE
|
|
12
|
-
* answers — one per tier config, one per channel, one for
|
|
13
|
-
* hand-written filtering
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* gives ONE answer, containing every block in the store. `config.tier` and
|
|
17
|
-
* `config.channel` no longer reach the query at all, and the owner-signed
|
|
18
|
-
* consequence — experimental/alpha blocks are visible to everyone — is asserted
|
|
19
|
-
* here rather than left to prose.
|
|
11
|
+
* CONTRACT CHANGE, TWICE, and this journey is where both are legible. It used
|
|
12
|
+
* to enumerate four answers — one per tier config, one per channel, one for
|
|
13
|
+
* `--all-tiers` — from hand-written filtering. That went, and the journey then
|
|
14
|
+
* pinned ONE answer under every config, because neither `config.tier` nor
|
|
15
|
+
* `config.channel` reached the query at all.
|
|
20
16
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
17
|
+
* The TIER SCOPE brings back exactly one of those two, in declared form: the
|
|
18
|
+
* `block` story declares the tier hierarchy, so `config.tier` and a per-call
|
|
19
|
+
* `--tier` decide which tiers the list answers from — unset is the top-level
|
|
20
|
+
* tiers, a tier is its own chain, `all` is the unfiltered list this journey used
|
|
21
|
+
* to pin. `config.channel` still reaches nothing, and the owner-signed
|
|
22
|
+
* consequence of that — experimental/alpha blocks are visible to everyone — is
|
|
23
|
+
* still asserted here rather than left to prose.
|
|
24
|
+
*
|
|
25
|
+
* So there are several answers again, and that is the improvement: each one
|
|
26
|
+
* states the scope it used, and one argument widens it.
|
|
27
|
+
*
|
|
28
|
+
* BOTH HALVES OF THE NOUN AGREE, as they have to: `block lookup` reads the same
|
|
29
|
+
* declared hierarchy, so the tier that decides which blocks this list shows is
|
|
30
|
+
* the tier that decides which Button a bare name means. The lookup's own half
|
|
31
|
+
* of that — it PREFERS the scope and falls back rather than refusing — is
|
|
32
|
+
* asserted in `kernel/packs/tierScope.test.ts` and, on the shipped pack's real
|
|
33
|
+
* tiers, in `capabilities/block.tierRank.exec.test.ts`.
|
|
27
34
|
*/
|
|
28
35
|
|
|
29
36
|
import { afterAll, describe, expect, it } from "vitest";
|
|
@@ -70,6 +77,16 @@ const EVERY_BLOCK = [
|
|
|
70
77
|
"Modal",
|
|
71
78
|
];
|
|
72
79
|
|
|
80
|
+
/**
|
|
81
|
+
* What the DEFAULT tier scope answers with: the top-level tiers (`global` and
|
|
82
|
+
* `apps`), so `LXD Panel` — two levels down, in `apps/lxd` — is out.
|
|
83
|
+
*
|
|
84
|
+
* `Button Icon` is IN, and that is the half worth stating twice: it carries no
|
|
85
|
+
* tier, and an entity the scope cannot PLACE is not an entity the scope hides.
|
|
86
|
+
* The hand-written verb's required tier join is what used to hide it.
|
|
87
|
+
*/
|
|
88
|
+
const TOP_LEVEL_BLOCKS = ["Beta Widget", "Button", "Button Icon", "Modal"];
|
|
89
|
+
|
|
73
90
|
const fixtures: FixtureGraph[] = [];
|
|
74
91
|
afterAll(async () => {
|
|
75
92
|
await Promise.all(fixtures.map((f) => f.dispose()));
|
|
@@ -84,10 +101,13 @@ async function bootWith(
|
|
|
84
101
|
return fixture;
|
|
85
102
|
}
|
|
86
103
|
|
|
87
|
-
async function blockListNames(
|
|
104
|
+
async function blockListNames(
|
|
105
|
+
fixture: FixtureGraph,
|
|
106
|
+
params: Record<string, unknown> = {},
|
|
107
|
+
): Promise<string[]> {
|
|
88
108
|
const out = await executeVerb(
|
|
89
109
|
listVerb,
|
|
90
|
-
|
|
110
|
+
params,
|
|
91
111
|
NO_MUTATION,
|
|
92
112
|
bootRuntime(JSON_FLAGS, fixture.cwd),
|
|
93
113
|
);
|
|
@@ -95,27 +115,43 @@ async function blockListNames(fixture: FixtureGraph): Promise<string[]> {
|
|
|
95
115
|
return rows.map((r) => r.name).sort();
|
|
96
116
|
}
|
|
97
117
|
|
|
98
|
-
describe("block list — the declared,
|
|
99
|
-
it("with no tier configured,
|
|
118
|
+
describe("block list — the declared, tier-scoped list (B9, in-process CLI dispatch)", () => {
|
|
119
|
+
it("with no tier configured, answers from the top-level tiers", async () => {
|
|
100
120
|
expect(await blockListNames(await bootWith(CANONICAL_CONFIG))).toEqual(
|
|
101
|
-
|
|
121
|
+
TOP_LEVEL_BLOCKS,
|
|
102
122
|
);
|
|
103
123
|
});
|
|
104
124
|
|
|
105
|
-
it("a configured tier
|
|
106
|
-
//
|
|
107
|
-
// apps/lxd block
|
|
108
|
-
// subcomponent. Nothing filters now, so the tier config is inert.
|
|
125
|
+
it("a configured tier narrows the list to its own chain", async () => {
|
|
126
|
+
// `global` is the base and has nothing above it, so its chain is itself.
|
|
127
|
+
// The apps/lxd block is out — and the UNTIERED subcomponent is not.
|
|
109
128
|
const fixture = await bootWith({ tier: "global", channel: "normal" });
|
|
110
|
-
expect(await blockListNames(fixture)).toEqual(
|
|
129
|
+
expect(await blockListNames(fixture)).toEqual(TOP_LEVEL_BLOCKS);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("the deepest tier in the chain sees MORE than the shallowest", async () => {
|
|
133
|
+
// Tier-chain inheritance was the point of the hand-written query, and it is
|
|
134
|
+
// the point again: `apps/lxd` -> [global, apps, apps/lxd], so the deepest
|
|
135
|
+
// tier answers with its own block AND everything it inherits. That is why
|
|
136
|
+
// the scope is the chain and not the single tier.
|
|
137
|
+
const names = await blockListNames(await bootWith(FILTERED_CONFIG));
|
|
138
|
+
expect(names).toEqual(EVERY_BLOCK);
|
|
139
|
+
expect(names).toContain("LXD Panel");
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("every tier on request is the unfiltered list this journey used to pin", async () => {
|
|
143
|
+
// The escape, and the proof that the scope removes nothing from the store:
|
|
144
|
+
// one argument, and every tier answers again.
|
|
145
|
+
const fixture = await bootWith(CANONICAL_CONFIG);
|
|
146
|
+
expect(await blockListNames(fixture, { tier: "all" })).toEqual(EVERY_BLOCK);
|
|
111
147
|
});
|
|
112
148
|
|
|
113
|
-
it("
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
expect(await blockListNames(
|
|
118
|
-
|
|
149
|
+
it("a per-call tier replaces the configured one", async () => {
|
|
150
|
+
// Precedence, at the seam a reader meets it: the machine is set to the deep
|
|
151
|
+
// tier, the call asks for the base, and the call wins.
|
|
152
|
+
const fixture = await bootWith(FILTERED_CONFIG);
|
|
153
|
+
expect(await blockListNames(fixture, { tier: "global" })).toEqual(
|
|
154
|
+
TOP_LEVEL_BLOCKS,
|
|
119
155
|
);
|
|
120
156
|
});
|
|
121
157
|
});
|
|
@@ -131,8 +167,11 @@ describe("block list — channel visibility is gone too (B9)", () => {
|
|
|
131
167
|
});
|
|
132
168
|
|
|
133
169
|
it("`prerelease` — once the only config that saw everything — is now unremarkable", async () => {
|
|
170
|
+
// Both configs set no tier, so both answer from the top-level tiers: the
|
|
171
|
+
// channel changes nothing, which is the claim. What narrows these rows is
|
|
172
|
+
// the tier scope, and it narrows them identically.
|
|
134
173
|
expect(await blockListNames(await bootWith(ALL_VISIBLE_CONFIG))).toEqual(
|
|
135
|
-
|
|
174
|
+
TOP_LEVEL_BLOCKS,
|
|
136
175
|
);
|
|
137
176
|
});
|
|
138
177
|
});
|
|
@@ -168,10 +168,12 @@ describe("default-pack journey — sources update, build, boot (E1)", () => {
|
|
|
168
168
|
expect(outcome.exitCode).toBe(0);
|
|
169
169
|
expect(readActivePack(cwd)).toMatch(/^[0-9a-f]{64}$/);
|
|
170
170
|
// A SEPARATE, fresh runtime boots the just-built pack from the pointer and
|
|
171
|
-
// answers a read over it.
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
171
|
+
// answers a read over it. The cold-boot read returns the pack's WHOLE
|
|
172
|
+
// block set — the beta-gated Beta Badge (no channel filters) and the
|
|
173
|
+
// untiered Orphan Widget (no scope hides an entity it cannot place)
|
|
174
|
+
// included, and every tier this fixture declares is top-level, so the
|
|
175
|
+
// tier scope admits the rest. That makes this the strictest form of the
|
|
176
|
+
// assert (an exact set, not a tolerant subset).
|
|
175
177
|
expect(await blockListNames(cwd)).toEqual([
|
|
176
178
|
"Beta Badge",
|
|
177
179
|
"Button",
|