@canonical/pragma-cli 0.32.0 → 0.34.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 +72 -0
- package/dist/pragma +0 -0
- package/package.json +19 -15
- package/pragma.conf.ts +664 -0
- package/src/bin.ts +15 -6
- package/src/capabilities/block.parity.test.ts +250 -0
- package/src/capabilities/capabilities/capabilities.render.ts +3 -2
- package/src/capabilities/capabilities/capabilities.test.ts +10 -1
- package/src/capabilities/capabilities/capabilities.verb.ts +32 -14
- package/src/capabilities/capabilities/catalog.ts +20 -8
- package/src/capabilities/capabilities/hints.ts +21 -36
- package/src/capabilities/capabilities/types.ts +2 -0
- package/src/capabilities/colophon/collectColophon.ts +34 -19
- package/src/capabilities/colophon/colophon.render.test.ts +31 -4
- package/src/capabilities/colophon/colophon.render.ts +13 -4
- package/src/capabilities/colophon/colophon.test.ts +3 -3
- package/src/capabilities/colophon/colophon.verb.ts +11 -4
- package/src/capabilities/colophon/markdownTerminal.ts +33 -14
- package/src/capabilities/colophon/types.ts +16 -7
- package/src/capabilities/config/collectConfigShow.test.ts +57 -0
- package/src/capabilities/config/collectConfigShow.ts +41 -4
- package/src/capabilities/config/fields.ts +10 -108
- package/src/capabilities/config/set.test.ts +6 -6
- package/src/capabilities/config/set.verb.ts +12 -8
- package/src/capabilities/config/show.render.test.ts +137 -0
- package/src/capabilities/config/show.render.ts +57 -16
- package/src/capabilities/config/show.verb.ts +9 -8
- package/src/capabilities/config/types.ts +8 -0
- package/src/capabilities/create/byteEquality.subprocess.test.ts +1 -1
- package/src/capabilities/create/byteEquality.test.ts +82 -101
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +53 -16
- package/src/capabilities/create/constants.ts +75 -0
- package/src/capabilities/create/create.mcp.test.ts +2 -2
- package/src/capabilities/create/create.test.ts +192 -16
- package/src/capabilities/create/create.verb.ts +208 -79
- package/src/capabilities/create/index.ts +2 -10
- package/src/capabilities/create/pickGenerator.ts +34 -28
- package/src/capabilities/create/templates.embedded.generated.ts +4 -29
- package/src/capabilities/create/types.ts +10 -6
- package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
- package/src/capabilities/distribution.test.ts +120 -0
- package/src/capabilities/distribution.ts +59 -0
- package/src/capabilities/doctor/checks/checkConfigFile.ts +6 -5
- package/src/capabilities/doctor/checks/checkKeStore.ts +2 -2
- package/src/capabilities/doctor/checks/checkMcpCommands.ts +6 -0
- package/src/capabilities/doctor/checks/checkMcpConfigured.ts +15 -8
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +79 -45
- package/src/capabilities/doctor/checks/checkPragmaVersion.ts +3 -2
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +61 -11
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -23
- package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +3 -2
- package/src/capabilities/doctor/checks/deriveBand.test.ts +42 -0
- package/src/capabilities/doctor/checks/deriveBand.ts +28 -0
- package/src/capabilities/doctor/doctor.render.test.ts +170 -0
- package/src/capabilities/doctor/doctor.render.ts +117 -34
- package/src/capabilities/doctor/doctor.test.ts +68 -9
- package/src/capabilities/doctor/doctor.verb.ts +6 -2
- package/src/capabilities/doctor/runChecks.ts +33 -9
- package/src/capabilities/doctor/types.ts +16 -1
- package/src/capabilities/emptyRecovery.test.ts +32 -15
- package/src/capabilities/graph/inspect.verb.ts +3 -2
- package/src/capabilities/graph/query.verb.ts +3 -2
- package/src/capabilities/graph/runQuery.ts +8 -5
- package/src/capabilities/index.ts +22 -18
- package/src/capabilities/info/collectInfo.ts +10 -6
- package/src/capabilities/info/info.render.ts +3 -2
- package/src/capabilities/info/info.verb.ts +3 -2
- package/src/capabilities/lazy.test.ts +93 -2
- package/src/capabilities/ontology/index.ts +10 -3
- package/src/capabilities/ontology/ontology.test.ts +157 -5
- package/src/capabilities/ontology/verbs.ts +203 -104
- package/src/capabilities/prompt/prompt.render.test.ts +94 -0
- package/src/capabilities/prompt/prompt.render.ts +23 -6
- package/src/capabilities/prompt/prompt.test.ts +68 -1
- package/src/capabilities/prompt/verbs.ts +24 -11
- package/src/capabilities/reference.test.ts +32 -0
- package/src/capabilities/resources/provider.ts +58 -25
- package/src/capabilities/resources/resources.test.ts +176 -21
- package/src/capabilities/scopeTypeSync.test.ts +37 -0
- package/src/capabilities/setup/index.ts +7 -1
- package/src/capabilities/setup/operations/setupCompletions.ts +49 -16
- package/src/capabilities/setup/operations/setupGenerator.ts +166 -63
- package/src/capabilities/setup/operations/setupLsp.ts +56 -12
- package/src/capabilities/setup/operations/setupMcp.ts +216 -39
- package/src/capabilities/setup/operations/setupSkills.ts +10 -4
- package/src/capabilities/setup/setup.render.test.ts +109 -0
- package/src/capabilities/setup/setup.render.ts +61 -14
- package/src/capabilities/setup/setup.test.ts +352 -1
- package/src/capabilities/setup/setup.verb.ts +68 -9
- package/src/capabilities/setup/shell.ts +29 -3
- package/src/capabilities/setup/types.ts +59 -2
- package/src/capabilities/shared/bands.ts +16 -0
- package/src/capabilities/skill/discover.ts +11 -5
- package/src/capabilities/skill/render.ts +4 -5
- package/src/capabilities/skill/verbs.ts +7 -7
- package/src/capabilities/sources/collectStatus.ts +69 -49
- package/src/capabilities/sources/index.ts +1 -1
- package/src/capabilities/sources/installSkills.ts +2 -2
- package/src/capabilities/sources/runUpdate.ts +146 -98
- package/src/capabilities/sources/sources.test.ts +264 -84
- package/src/capabilities/sources/status.render.test.ts +94 -0
- package/src/capabilities/sources/status.render.ts +55 -33
- package/src/capabilities/sources/status.verb.ts +15 -8
- package/src/capabilities/sources/types.ts +18 -25
- package/src/capabilities/sources/update.render.ts +9 -2
- package/src/capabilities/sources/update.verb.ts +12 -23
- package/src/capabilities/surface.test.ts +65 -17
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
- package/src/constants.test.ts +9 -7
- package/src/constants.ts +49 -23
- package/src/identity.test.ts +333 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +18 -16
- package/src/kernel/completion/complete.test.ts +3 -5
- package/src/kernel/completion/emitScripts.test.ts +1 -1
- package/src/kernel/completion/emitScripts.ts +4 -2
- package/src/kernel/completion/entitySource.test.ts +185 -41
- package/src/kernel/completion/entitySource.ts +131 -113
- package/src/kernel/completion/model.test.ts +3 -3
- package/src/kernel/completion/model.ts +11 -1
- package/src/kernel/completion/parse.test.ts +2 -4
- package/src/kernel/completion/safety.test.ts +82 -36
- package/src/kernel/completion/shellDrive.test.ts +592 -0
- package/src/kernel/completion/templates/fish.ts +28 -6
- package/src/kernel/completion/types.ts +3 -3
- package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +1 -1
- package/src/kernel/config/defaults.test.ts +85 -0
- package/src/kernel/config/defaults.ts +12 -23
- package/src/kernel/config/evaluateProjectConfig.ts +2 -3
- package/src/kernel/config/findProjectConfig.ts +4 -3
- package/src/kernel/config/firstRun.ts +12 -5
- package/src/kernel/config/globalConfig.ts +2 -2
- package/src/kernel/config/index.ts +4 -5
- package/src/kernel/config/paths.ts +17 -17
- package/src/kernel/config/readConfig.test.ts +242 -6
- package/src/kernel/config/readConfig.ts +8 -8
- package/src/kernel/config/schema.test.ts +50 -0
- package/src/kernel/config/schema.ts +97 -10
- package/src/kernel/config/types.ts +73 -19
- package/src/kernel/copy.test.ts +453 -0
- package/src/kernel/error/PragmaError.test.ts +5 -5
- package/src/kernel/error/constants.ts +3 -2
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +22 -45
- package/src/kernel/error/recovery.ts +22 -27
- package/src/kernel/error/renderError.ts +1 -1
- package/src/kernel/error/types.ts +5 -4
- package/src/kernel/packs/collect.test.ts +195 -11
- package/src/kernel/packs/collect.ts +213 -58
- package/src/kernel/packs/compile.test.ts +163 -7
- package/src/kernel/packs/compile.ts +15 -12
- package/src/kernel/packs/disclosure.test.ts +5 -2
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +11 -10
- package/src/kernel/packs/graphqlSource.test.ts +6 -3
- package/src/kernel/packs/iri.ts +5 -7
- package/src/kernel/packs/renderPack.ts +5 -3
- package/src/kernel/packs/resolveEntity.ts +21 -17
- package/src/kernel/packs/runBodies.ts +15 -14
- package/src/kernel/packs/schema.ts +96 -10
- package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
- package/src/kernel/packs/sparql/runSelect.ts +73 -34
- package/src/kernel/packs/toolDescription.test.ts +10 -2
- package/src/kernel/packs/types.ts +39 -4
- package/src/kernel/packs/uniqueness.ts +4 -4
- package/src/kernel/project/cli/buildProgram.test.ts +60 -11
- package/src/kernel/project/cli/buildProgram.ts +11 -0
- package/src/kernel/project/cli/dispatch.test.ts +67 -0
- package/src/kernel/project/cli/dispatch.ts +34 -12
- package/src/kernel/project/cli/globalFlags.test.ts +12 -4
- package/src/kernel/project/cli/globalFlags.ts +14 -14
- package/src/kernel/project/cli/helpFormat.ts +1 -1
- package/src/kernel/project/cli/rootHelp.ts +109 -107
- package/src/kernel/project/mcp/buildServer.ts +11 -6
- package/src/kernel/project/mcp/instructions.ts +12 -7
- package/src/kernel/project/mcp/mcpError.ts +52 -0
- package/src/kernel/project/mcp/parity.test.ts +39 -1
- package/src/kernel/project/mcp/prompts/prompts.test.ts +128 -5
- package/src/kernel/project/mcp/prompts/provider.ts +51 -7
- package/src/kernel/project/mcp/prompts/source.ts +68 -67
- package/src/kernel/project/mcp/registerVerb.ts +25 -6
- package/src/kernel/project/mcp/serve.ts +11 -3
- package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
- package/src/kernel/render/disclosure.ts +4 -2
- package/src/kernel/render/formatters.ts +5 -4
- package/src/kernel/render/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +35 -1
- package/src/kernel/render/renderers.ts +25 -7
- package/src/kernel/render/style.test.ts +31 -0
- package/src/kernel/render/style.ts +74 -0
- package/src/kernel/runtime/graphpack/build.ts +57 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +149 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +173 -50
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -8
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -4
- package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +37 -11
- package/src/kernel/runtime/graphpack/graphpack.test.ts +274 -6
- package/src/kernel/runtime/graphpack/hash.ts +3 -2
- package/src/kernel/runtime/graphpack/index.ts +1 -1
- package/src/kernel/runtime/graphpack/manifest.ts +114 -12
- package/src/kernel/runtime/graphpack/read.ts +32 -22
- package/src/kernel/runtime/graphpack/schemas.ts +74 -0
- package/src/kernel/runtime/graphpack/stories.ts +84 -0
- package/src/kernel/runtime/graphpack/types.ts +72 -45
- package/src/kernel/runtime/loadSession.ts +4 -12
- package/src/kernel/runtime/paths.ts +64 -15
- package/src/kernel/runtime/probe.test.ts +8 -4
- package/src/kernel/runtime/readEntity.ts +6 -5
- package/src/kernel/runtime/refs/gitOps.ts +1 -19
- package/src/kernel/runtime/refs/parseRef.ts +7 -7
- package/src/kernel/runtime/refs/resolve.ts +141 -65
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +62 -0
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/types.ts +1 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +25 -20
- package/src/kernel/spec/emitReference.test.ts +196 -0
- package/src/kernel/spec/emitReference.ts +624 -0
- package/src/kernel/spec/emitSurface.ts +13 -7
- package/src/kernel/spec/index.ts +2 -0
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/surfaceConformance.ts +8 -0
- package/src/kernel/spec/types.ts +29 -9
- package/src/kernel/spec/validate.ts +2 -1
- package/src/kernel/vocabulary.test.ts +164 -0
- package/src/kernel/vocabulary.ts +146 -0
- package/src/testing/PARITY_GAPS.ts +9 -3
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/autoLlm.e2e.test.ts +12 -2
- package/src/testing/behavioral/completion.test.ts +21 -8
- package/src/testing/behavioral/disclosure.test.ts +12 -0
- package/src/testing/behavioral/docExamples.test.ts +283 -0
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +3 -2
- package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
- package/src/testing/behavioral/harness.foundation.test.ts +14 -5
- package/src/testing/behavioral/journeys.cli.test.ts +116 -73
- package/src/testing/behavioral/journeys.defaultPack.test.ts +477 -0
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.interactiveTty.e2e.test.ts +66 -0
- package/src/testing/behavioral/journeys.livePack.e2e.test.ts +129 -0
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +179 -0
- package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
- package/src/testing/behavioral/liveReadSurface.ts +4 -3
- package/src/testing/behavioral/mcpSurface.test.ts +10 -5
- package/src/testing/behavioral/staleCommands.test.ts +86 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +9 -9
- package/src/testing/eval/cases/assembly.ts +16 -9
- package/src/testing/eval/cases/effectful.ts +31 -16
- package/src/testing/eval/cases/readNouns.ts +23 -18
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/fixtureCapability.ts +201 -1
- package/src/testing/fixtures/graph/canonical.ts +6 -3
- package/src/testing/fixtures/graph/defaultPack.ts +179 -0
- package/src/testing/fixtures/graph/owlExport.ts +97 -0
- package/src/testing/helpers/extractSnippets.ts +29 -0
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- package/src/testing/helpers/golden.ts +1 -1
- package/src/testing/helpers/packRuntime.ts +2 -3
- package/src/testing/helpers/projectCli.ts +2 -1
- package/src/testing/helpers/projectMcp.ts +6 -0
- package/src/testing/perf/budgets.test.ts +4 -0
- package/src/testing/perf/budgets.ts +22 -7
- package/src/testing/perf/globalSetup.ts +121 -6
- package/src/types.ts +2 -2
- package/src/capabilities/block/blockList.verb.ts +0 -150
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -155
- package/src/capabilities/block/parity.test.ts +0 -180
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- package/src/capabilities/config/field.test.ts +0 -188
- package/src/capabilities/modifier/index.ts +0 -15
- package/src/capabilities/modifier/pack.ts +0 -64
- package/src/capabilities/standard/index.ts +0 -18
- package/src/capabilities/standard/pack.ts +0 -128
- package/src/capabilities/tier/index.ts +0 -19
- package/src/capabilities/tier/lookup.render.ts +0 -34
- package/src/capabilities/tier/lookup.test.ts +0 -68
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -59
- package/src/capabilities/token/addConfig.render.ts +0 -27
- package/src/capabilities/token/addConfig.test.ts +0 -62
- package/src/capabilities/token/addConfig.verb.ts +0 -40
- package/src/capabilities/token/index.ts +0 -19
- package/src/capabilities/token/pack.ts +0 -58
- package/src/capabilities/token/runAddConfig.ts +0 -95
- package/src/kernel/completion/bashDrive.test.ts +0 -73
- package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
- package/src/kernel/runtime/lock.ts +0 -90
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stale-command gate: the published README and every doc under `docs/` must be
|
|
3
|
+
* free of the retired v1 vocabulary. This is an ENFORCED test, not a lint — a
|
|
4
|
+
* doc that reintroduces a removed command (or the retired `--llm` flag) fails
|
|
5
|
+
* the build. The live `--format llm` form is deliberately NOT banned.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
9
|
+
import { join, relative } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { describe, expect, it } from "vitest";
|
|
12
|
+
|
|
13
|
+
/** The package root (`packages/cli/pragma/`), resolved from this test's URL. */
|
|
14
|
+
const packageRoot = fileURLToPath(new URL("../../../", import.meta.url));
|
|
15
|
+
|
|
16
|
+
/** Recursively collect every `.md` file under a directory. */
|
|
17
|
+
function collectMarkdown(dir: string): string[] {
|
|
18
|
+
const out: string[] = [];
|
|
19
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
20
|
+
const full = join(dir, entry.name);
|
|
21
|
+
if (entry.isDirectory()) out.push(...collectMarkdown(full));
|
|
22
|
+
else if (entry.name.endsWith(".md")) out.push(full);
|
|
23
|
+
}
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** One retired pattern and a human-readable reason for the failure message. */
|
|
28
|
+
interface BannedPattern {
|
|
29
|
+
readonly pattern: RegExp;
|
|
30
|
+
readonly reason: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The retired v1 vocabulary. The live `--format llm` form is intentionally absent. */
|
|
34
|
+
const BANNED: readonly BannedPattern[] = [
|
|
35
|
+
{
|
|
36
|
+
pattern: /\bupdate-refs\b/,
|
|
37
|
+
reason: "retired `update-refs` (now `sources update`)",
|
|
38
|
+
},
|
|
39
|
+
{ pattern: /pragma\s+llm\b/, reason: "retired `llm` tool" },
|
|
40
|
+
{ pattern: /pragma\s+data\b/, reason: "retired `data` noun (now `sources`)" },
|
|
41
|
+
{
|
|
42
|
+
pattern: /pragma\s+tokens\b/,
|
|
43
|
+
reason: "retired plural `tokens` noun (now singular `token`)",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern: /\btokens_(list|lookup|sample|add-config)\b/,
|
|
47
|
+
reason: "retired plural `tokens_*` tools (now `token_*`)",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
pattern: /--llm\b/,
|
|
51
|
+
reason:
|
|
52
|
+
"retired `--llm` flag (now the `--format llm` form, auto-detected when piped)",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
pattern: /--all-tiers\b/,
|
|
56
|
+
reason:
|
|
57
|
+
"retired `--all-tiers` flag (L-OPEN-9: `block list` is the declared, unfiltered story — there is no tier filter to escape)",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pattern: /\btoken[ _]add-config\b/,
|
|
61
|
+
reason:
|
|
62
|
+
"removed `token add-config` command / `token_add-config` tool (L-OPEN-9: a mutation the declared read grammar has no verb for)",
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Every shipped doc must be free of retired vocabulary: the README plus every
|
|
67
|
+
// page under `docs/`. CHANGELOG.md (at the package root, outside `docs/`) is
|
|
68
|
+
// DELIBERATELY exempt — its migration table legitimately cites the retired
|
|
69
|
+
// names (`data`, `update-refs`, plural `tokens`) to tell readers what they
|
|
70
|
+
// became, so scanning it would false-positive on that historical vocabulary.
|
|
71
|
+
const files = [
|
|
72
|
+
join(packageRoot, "README.md"),
|
|
73
|
+
...collectMarkdown(join(packageRoot, "docs")),
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
describe("stale-command gate — docs never mention retired v1 commands", () => {
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const rel = relative(packageRoot, file);
|
|
79
|
+
it(`${rel} is free of retired commands`, () => {
|
|
80
|
+
const content = readFileSync(file, "utf-8");
|
|
81
|
+
for (const { pattern, reason } of BANNED) {
|
|
82
|
+
expect(pattern.test(content), `${rel}: ${reason}`).toBe(false);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`eval harness — seed gate > runs the full seed (stable + read-noun) cases clean 1`] = `
|
|
4
4
|
[
|
|
5
|
+
{
|
|
6
|
+
"id": "content-block-list-is-channel-independent",
|
|
7
|
+
"kind": "content",
|
|
8
|
+
"passed": true,
|
|
9
|
+
},
|
|
5
10
|
{
|
|
6
11
|
"id": "content-canonical-graph-has-4-components",
|
|
7
12
|
"kind": "content",
|
|
@@ -57,11 +62,6 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
57
62
|
"kind": "content",
|
|
58
63
|
"passed": true,
|
|
59
64
|
},
|
|
60
|
-
{
|
|
61
|
-
"id": "content-normal-channel-drops-beta-only-block",
|
|
62
|
-
"kind": "content",
|
|
63
|
-
"passed": true,
|
|
64
|
-
},
|
|
65
65
|
{
|
|
66
66
|
"id": "content-standard-list-length-equals-category-count-sum",
|
|
67
67
|
"kind": "content",
|
|
@@ -103,7 +103,7 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
103
103
|
"passed": true,
|
|
104
104
|
},
|
|
105
105
|
{
|
|
106
|
-
"id": "prompt-set-tier-maps-to-config-
|
|
106
|
+
"id": "prompt-set-tier-maps-to-config-set",
|
|
107
107
|
"kind": "prompt",
|
|
108
108
|
"passed": true,
|
|
109
109
|
},
|
|
@@ -113,7 +113,7 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
113
113
|
"passed": true,
|
|
114
114
|
},
|
|
115
115
|
{
|
|
116
|
-
"id": "prompt-tokens-config-maps-to-
|
|
116
|
+
"id": "prompt-tokens-config-maps-to-nothing",
|
|
117
117
|
"kind": "prompt",
|
|
118
118
|
"passed": true,
|
|
119
119
|
},
|
|
@@ -138,7 +138,7 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
138
138
|
"passed": true,
|
|
139
139
|
},
|
|
140
140
|
{
|
|
141
|
-
"id": "tool-config-
|
|
141
|
+
"id": "tool-config-set-is-plan-first",
|
|
142
142
|
"kind": "tool",
|
|
143
143
|
"passed": true,
|
|
144
144
|
},
|
|
@@ -183,7 +183,7 @@ exports[`eval harness — seed gate > runs the full seed (stable + read-noun) ca
|
|
|
183
183
|
"passed": true,
|
|
184
184
|
},
|
|
185
185
|
{
|
|
186
|
-
"id": "tool-token-
|
|
186
|
+
"id": "tool-token-noun-is-read-only",
|
|
187
187
|
"kind": "tool",
|
|
188
188
|
"passed": true,
|
|
189
189
|
},
|
|
@@ -163,23 +163,30 @@ export const assemblyEvalCases: readonly EvalCase[] = [
|
|
|
163
163
|
},
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
|
-
id: "prompt-set-tier-maps-to-config-
|
|
166
|
+
id: "prompt-set-tier-maps-to-config-set",
|
|
167
167
|
kind: "prompt",
|
|
168
|
-
input: '"Set the active tier" should map to `
|
|
168
|
+
input: '"Set the active tier" should map to `config_set` (B3).',
|
|
169
169
|
async expect({ mcp }) {
|
|
170
|
-
assertIntentTool(await mcp.listTools(), "
|
|
170
|
+
assertIntentTool(await mcp.listTools(), "config_set", /tier/i);
|
|
171
171
|
},
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
|
-
id: "prompt-tokens-config-maps-to-
|
|
174
|
+
id: "prompt-tokens-config-maps-to-nothing",
|
|
175
175
|
kind: "prompt",
|
|
176
176
|
input:
|
|
177
|
-
'"Generate a terrazzo tokens config"
|
|
177
|
+
'"Generate a terrazzo tokens config" maps to NO tool — `token_add-config` was removed in L-OPEN-9, and the token noun is read-only.',
|
|
178
178
|
async expect({ mcp }) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
// The inverse of an intent-mapping case, and the point of the ruling: an
|
|
180
|
+
// agent asked to write a tokens config finds nothing in the catalog that
|
|
181
|
+
// claims to do it, rather than a verb the declared grammar cannot express.
|
|
182
|
+
const tools = await mcp.listTools();
|
|
183
|
+
assert.ok(
|
|
184
|
+
!tools.some(
|
|
185
|
+
(tool) =>
|
|
186
|
+
tool.name === "token_add-config" ||
|
|
187
|
+
/terrazzo|tokens\.config/i.test(String(tool.description ?? "")),
|
|
188
|
+
),
|
|
189
|
+
"no tool may still offer to write a tokens config",
|
|
183
190
|
);
|
|
184
191
|
},
|
|
185
192
|
},
|
|
@@ -70,12 +70,15 @@ export const effectfulEvalCases: readonly EvalCase[] = [
|
|
|
70
70
|
},
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
|
-
id: "tool-config-
|
|
73
|
+
id: "tool-config-set-is-plan-first",
|
|
74
74
|
kind: "tool",
|
|
75
75
|
input:
|
|
76
|
-
"
|
|
76
|
+
"config_set without `confirm` returns a plan (planOnly) and writes nothing — the uniform plan-first mutation contract.",
|
|
77
77
|
async expect({ mcp }) {
|
|
78
|
-
const result = await mcp.callTool("
|
|
78
|
+
const result = await mcp.callTool("config_set", {
|
|
79
|
+
key: "tier",
|
|
80
|
+
value: "apps/lxd",
|
|
81
|
+
});
|
|
79
82
|
assert.equal(result.ok, true);
|
|
80
83
|
const meta = result.meta as { planOnly?: boolean };
|
|
81
84
|
assert.equal(meta.planOnly, true);
|
|
@@ -167,18 +170,23 @@ export const effectfulEvalCases: readonly EvalCase[] = [
|
|
|
167
170
|
},
|
|
168
171
|
},
|
|
169
172
|
{
|
|
170
|
-
id: "tool-token-
|
|
173
|
+
id: "tool-token-noun-is-read-only",
|
|
171
174
|
kind: "tool",
|
|
172
175
|
input:
|
|
173
|
-
"
|
|
176
|
+
"the `token` noun exposes only reads — `token_add-config` (the tokens.config.mjs writer) was REMOVED in L-OPEN-9, not ported.",
|
|
174
177
|
async expect() {
|
|
175
178
|
await withCanonicalFixture(CANONICAL_CONFIG, async (mcp) => {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
179
|
+
// This case used to pin `token_add-config`'s plan-first contract. The
|
|
180
|
+
// verb is gone, so it pins the ruling instead: the read surface is
|
|
181
|
+
// declared content and carries no mutation. (The plan-first MECHANIC is
|
|
182
|
+
// still covered by `tool-config-set-is-plan-first` and
|
|
183
|
+
// `tool-upgrade-is-plan-first`.)
|
|
184
|
+
const tools = (await mcp.listTools()).map((tool) => tool.name);
|
|
185
|
+
assert.ok(!tools.includes("token_add-config"));
|
|
186
|
+
assert.deepEqual(
|
|
187
|
+
tools.filter((name) => name.startsWith("token")).sort(),
|
|
188
|
+
["token_list", "token_lookup", "token_sample"],
|
|
189
|
+
);
|
|
182
190
|
});
|
|
183
191
|
},
|
|
184
192
|
},
|
|
@@ -186,14 +194,21 @@ export const effectfulEvalCases: readonly EvalCase[] = [
|
|
|
186
194
|
id: "tool-tier-lookup-lists-scoped-blocks",
|
|
187
195
|
kind: "tool",
|
|
188
196
|
input:
|
|
189
|
-
"tier_lookup {name:apps/lxd} resolves the tier and
|
|
197
|
+
"tier_lookup {name:[apps/lxd]} resolves the tier and expands the blocks scoped to it (LXD Panel).",
|
|
190
198
|
async expect() {
|
|
191
199
|
await withCanonicalFixture(ALL_VISIBLE_CONFIG, async (mcp) => {
|
|
192
|
-
|
|
200
|
+
// The declared pack lookup (L-OPEN-9): variadic names in, the uniform
|
|
201
|
+
// `{ results, errors }` lookup envelope out, blocks as an expand.
|
|
202
|
+
const result = await mcp.callTool("tier_lookup", {
|
|
203
|
+
name: ["apps/lxd"],
|
|
204
|
+
});
|
|
193
205
|
assert.equal(result.ok, true);
|
|
194
|
-
const data = result.data as {
|
|
195
|
-
|
|
196
|
-
|
|
206
|
+
const data = result.data as {
|
|
207
|
+
results: { name: string; blocks: { name: string }[] }[];
|
|
208
|
+
};
|
|
209
|
+
const tier = data.results[0];
|
|
210
|
+
assert.equal(tier?.name, "apps/lxd");
|
|
211
|
+
assert.ok(tier?.blocks.some((block) => block.name === "LXD Panel"));
|
|
197
212
|
});
|
|
198
213
|
},
|
|
199
214
|
},
|
|
@@ -90,16 +90,19 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
90
90
|
id: "content-canonical-graph-has-4-components",
|
|
91
91
|
kind: "content",
|
|
92
92
|
input:
|
|
93
|
-
"the canonical fixture graph carries
|
|
93
|
+
"the canonical fixture graph carries 4 ds:Component individuals (Button, Modal, LXD Panel, Beta Widget); block_list also surfaces the untiered Button Icon subcomponent (A2).",
|
|
94
94
|
async expect() {
|
|
95
95
|
await withCanonicalFixture(ALL_VISIBLE_CONFIG, async (mcp) => {
|
|
96
|
-
const result = await mcp.callTool("block_list"
|
|
96
|
+
const result = await mcp.callTool("block_list");
|
|
97
97
|
const names = (result.data as { name: string }[])
|
|
98
98
|
.map((r) => r.name)
|
|
99
99
|
.sort();
|
|
100
|
+
// The declared list takes no arguments and filters nothing: the 4 tiered
|
|
101
|
+
// components plus the untiered Button Icon subcomponent (A2).
|
|
100
102
|
assert.deepEqual(names, [
|
|
101
103
|
"Beta Widget",
|
|
102
104
|
"Button",
|
|
105
|
+
"Button Icon",
|
|
103
106
|
"LXD Panel",
|
|
104
107
|
"Modal",
|
|
105
108
|
]);
|
|
@@ -165,25 +168,27 @@ export const readNounEvalCases: readonly EvalCase[] = [
|
|
|
165
168
|
},
|
|
166
169
|
},
|
|
167
170
|
{
|
|
168
|
-
id: "content-
|
|
171
|
+
id: "content-block-list-is-channel-independent",
|
|
169
172
|
kind: "content",
|
|
170
173
|
input:
|
|
171
|
-
"the normal channel (CANONICAL_CONFIG)
|
|
174
|
+
"block_list returns the SAME rows on the normal channel (CANONICAL_CONFIG) and the prerelease one (ALL_VISIBLE_CONFIG) — including the beta-only block, which the normal channel used to hide (L-OPEN-9).",
|
|
172
175
|
async expect() {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
176
|
+
const namesUnder = async (
|
|
177
|
+
config: typeof CANONICAL_CONFIG | typeof ALL_VISIBLE_CONFIG,
|
|
178
|
+
): Promise<string[]> => {
|
|
179
|
+
let names: string[] = [];
|
|
180
|
+
await withCanonicalFixture(config, async (mcp) => {
|
|
181
|
+
const result = await mcp.callTool("block_list");
|
|
182
|
+
names = (result.data as { name: string }[]).map((r) => r.name).sort();
|
|
183
|
+
});
|
|
184
|
+
return names;
|
|
185
|
+
};
|
|
186
|
+
const normal = await namesUnder(CANONICAL_CONFIG);
|
|
187
|
+
const prerelease = await namesUnder(ALL_VISIBLE_CONFIG);
|
|
188
|
+
// The signed-off consequence: an experimental block is visible to
|
|
189
|
+
// everyone, on every channel, until filtering returns in declared form.
|
|
190
|
+
assert.ok(normal.includes("Beta Widget"));
|
|
191
|
+
assert.deepEqual(normal, prerelease);
|
|
187
192
|
},
|
|
188
193
|
},
|
|
189
194
|
{
|
|
@@ -110,7 +110,11 @@ export const stableEvalCases: readonly EvalCase[] = [
|
|
|
110
110
|
try {
|
|
111
111
|
const widgetModule: CapabilityModule = {
|
|
112
112
|
name: "widget",
|
|
113
|
-
verbs: compilePack(
|
|
113
|
+
verbs: compilePack(
|
|
114
|
+
WIDGET_PACK,
|
|
115
|
+
{ label: "test:widget", origin: "package" },
|
|
116
|
+
WIDGET_PREFIXES,
|
|
117
|
+
),
|
|
114
118
|
};
|
|
115
119
|
const mcp = await projectMcp([widgetModule], fixture.cwd);
|
|
116
120
|
try {
|
|
@@ -70,5 +70,11 @@ describe("eval harness — seed gate", () => {
|
|
|
70
70
|
expect(report.cases.length).toBeGreaterThanOrEqual(35);
|
|
71
71
|
expect(report.cases.length).toBeLessThanOrEqual(60);
|
|
72
72
|
expect(normalize(report.cases)).toMatchSnapshot();
|
|
73
|
-
|
|
73
|
+
// Explicit timeout, like the other suite-level gates: this drives every
|
|
74
|
+
// seed case through a real runtime AND a real MCP server, and since a
|
|
75
|
+
// preview now performs its reads for real rather than answering from a
|
|
76
|
+
// mock, the effectful cases pay genuine IO. Measured 3.7s before that
|
|
77
|
+
// change and 5.4s after, so the vitest 5s default fails it on cost the
|
|
78
|
+
// PR intends to pay — not on a defect. 60s leaves room for CI contention.
|
|
79
|
+
}, 60_000);
|
|
74
80
|
});
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
import { join } from "node:path";
|
|
10
|
-
import { $, gen, succeed, writeFile } from "@canonical/task";
|
|
10
|
+
import { $, gen, readFile, succeed, writeFile } from "@canonical/task";
|
|
11
11
|
import type { CapabilityModule } from "../../kernel/spec/types.js";
|
|
12
12
|
|
|
13
13
|
/** A synthetic module: noun `widget`, three verbs (one hidden). */
|
|
@@ -173,3 +173,203 @@ export const fixtureEffectsModule: CapabilityModule = {
|
|
|
173
173
|
},
|
|
174
174
|
],
|
|
175
175
|
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* A synthetic module for the HONEST-preview guards (PR7). `probe graft` READS a
|
|
179
|
+
* file before writing beside it, so a run whose source is missing dies on its
|
|
180
|
+
* first effect. The mock previewer answered that read with a placeholder string
|
|
181
|
+
* and reported a confident plan with exit 0 — the structural false positive
|
|
182
|
+
* PRA-104 indicts. Under `runPreview` the read is real, so `--dry-run` (and the
|
|
183
|
+
* MCP plan-first twin) fail exactly where and how the run would. Test-only (D8)
|
|
184
|
+
* — never listed in `capabilities/index.ts`.
|
|
185
|
+
*/
|
|
186
|
+
export const fixturePreviewModule: CapabilityModule = {
|
|
187
|
+
name: "fixture-preview",
|
|
188
|
+
verbs: [
|
|
189
|
+
{
|
|
190
|
+
path: ["probe", "graft"],
|
|
191
|
+
summary: "Copy a file's content into a sibling.",
|
|
192
|
+
params: [
|
|
193
|
+
{
|
|
194
|
+
kind: "string",
|
|
195
|
+
name: "source",
|
|
196
|
+
doc: "The file to read.",
|
|
197
|
+
positional: true,
|
|
198
|
+
required: true,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
output: { formatters: passthroughFormatters },
|
|
202
|
+
capability: {
|
|
203
|
+
needsStore: false,
|
|
204
|
+
mutates: true,
|
|
205
|
+
mcp: {
|
|
206
|
+
expose: true,
|
|
207
|
+
annotations: { readOnlyHint: false, openWorldHint: false },
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
run: (p) =>
|
|
211
|
+
gen(function* () {
|
|
212
|
+
const { source } = p as { source: string };
|
|
213
|
+
const content = yield* $(readFile(source));
|
|
214
|
+
yield* $(writeFile(`${source}.grafted`, content));
|
|
215
|
+
return { grafted: source };
|
|
216
|
+
}),
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* A synthetic module that exercises every RENDER path of `emitReference` (D8 —
|
|
223
|
+
* never listed in `src/capabilities/index.ts`). Distinct from `fixtureModule`,
|
|
224
|
+
* which only exercises `emitSurface`: this one carries the doc-only shapes the
|
|
225
|
+
* reference generator reads and the machine surface ignores — a rich `doc`,
|
|
226
|
+
* examples with and without notes, a {@link DisclosureSpec}, every param kind
|
|
227
|
+
* as a flag (including a repeatable `string[]` flag), an OPTIONAL variadic
|
|
228
|
+
* positional, a destructive mutation AND a non-destructive one (the two
|
|
229
|
+
* `formatToolAnnotations` mutation branches), a visible MCP-withheld verb, a
|
|
230
|
+
* self-verb, a hidden verb the emitter must drop, and — so `renderNonToolSurface`
|
|
231
|
+
* renders both its optional bullets — an `mcpResources` template surface and an
|
|
232
|
+
* `mcpPrompts` native-prompt surface. The `register` hooks are no-ops: the
|
|
233
|
+
* reference emitter reads only `mcpResources.surface.templates` and the presence
|
|
234
|
+
* of `mcpPrompts`, never invoking either.
|
|
235
|
+
*/
|
|
236
|
+
export const fixtureReferenceModule: CapabilityModule = {
|
|
237
|
+
name: "fixture-reference",
|
|
238
|
+
verbs: [
|
|
239
|
+
{
|
|
240
|
+
path: ["gizmo", "scan"],
|
|
241
|
+
summary: "Scan the gizmos.",
|
|
242
|
+
doc: "Scan every gizmo under the active scope, optionally narrowing to named targets. Reads nothing off disk.",
|
|
243
|
+
params: [
|
|
244
|
+
{
|
|
245
|
+
kind: "string[]",
|
|
246
|
+
name: "targets",
|
|
247
|
+
doc: "Gizmo names to scan (all when omitted).",
|
|
248
|
+
positional: true,
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
kind: "enum",
|
|
252
|
+
name: "mode",
|
|
253
|
+
doc: "Scan mode.",
|
|
254
|
+
values: ["fast", "slow"],
|
|
255
|
+
default: "fast",
|
|
256
|
+
},
|
|
257
|
+
{ kind: "number", name: "limit", doc: "Maximum gizmos to scan." },
|
|
258
|
+
{ kind: "string", name: "label", doc: "Label to stamp on the report." },
|
|
259
|
+
{ kind: "string[]", name: "include", doc: "Extra globs to include." },
|
|
260
|
+
{ kind: "boolean", name: "deep", doc: "Recurse into sub-gizmos." },
|
|
261
|
+
],
|
|
262
|
+
output: { formatters: passthroughFormatters },
|
|
263
|
+
examples: [
|
|
264
|
+
{ cmd: "pragma gizmo scan", note: "scan everything" },
|
|
265
|
+
{ cmd: "pragma gizmo scan alpha --mode slow" },
|
|
266
|
+
],
|
|
267
|
+
disclosure: { levels: ["summary", "detailed"], default: "summary" },
|
|
268
|
+
capability: {
|
|
269
|
+
needsStore: false,
|
|
270
|
+
mutates: false,
|
|
271
|
+
mcp: {
|
|
272
|
+
expose: true,
|
|
273
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
run: async () => ({ scanned: true }),
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
path: ["gizmo", "wipe"],
|
|
280
|
+
summary: "Wipe a gizmo.",
|
|
281
|
+
params: [
|
|
282
|
+
{
|
|
283
|
+
kind: "string",
|
|
284
|
+
name: "path",
|
|
285
|
+
doc: "The gizmo path to wipe.",
|
|
286
|
+
positional: true,
|
|
287
|
+
required: true,
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
output: { formatters: passthroughFormatters },
|
|
291
|
+
capability: {
|
|
292
|
+
needsStore: true,
|
|
293
|
+
mutates: true,
|
|
294
|
+
destructive: true,
|
|
295
|
+
mcp: {
|
|
296
|
+
expose: true,
|
|
297
|
+
annotations: {
|
|
298
|
+
readOnlyHint: false,
|
|
299
|
+
destructiveHint: true,
|
|
300
|
+
openWorldHint: false,
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
run: () => succeed({ wiped: true }),
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
path: ["gizmo", "tidy"],
|
|
308
|
+
summary: "Tidy the gizmo cache.",
|
|
309
|
+
params: [],
|
|
310
|
+
output: { formatters: passthroughFormatters },
|
|
311
|
+
capability: {
|
|
312
|
+
needsStore: false,
|
|
313
|
+
mutates: true,
|
|
314
|
+
destructive: false,
|
|
315
|
+
mcp: {
|
|
316
|
+
expose: true,
|
|
317
|
+
annotations: {
|
|
318
|
+
readOnlyHint: false,
|
|
319
|
+
destructiveHint: false,
|
|
320
|
+
openWorldHint: false,
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
run: () => succeed({ tidied: true }),
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
path: ["gizmo", "local"],
|
|
328
|
+
summary: "A visible gizmo verb withheld from MCP.",
|
|
329
|
+
params: [],
|
|
330
|
+
output: { formatters: passthroughFormatters },
|
|
331
|
+
capability: {
|
|
332
|
+
needsStore: false,
|
|
333
|
+
mutates: false,
|
|
334
|
+
mcp: { expose: false, reason: "CLI-only local helper" },
|
|
335
|
+
},
|
|
336
|
+
run: async () => ({ local: true }),
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
path: ["ping"],
|
|
340
|
+
summary: "Ping the gizmo host.",
|
|
341
|
+
params: [],
|
|
342
|
+
output: { formatters: passthroughFormatters },
|
|
343
|
+
capability: {
|
|
344
|
+
needsStore: false,
|
|
345
|
+
mutates: false,
|
|
346
|
+
mcp: {
|
|
347
|
+
expose: true,
|
|
348
|
+
annotations: { readOnlyHint: true, openWorldHint: false },
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
run: async () => ({ pong: true }),
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
path: ["gizmo", "hidden"],
|
|
355
|
+
summary: "Hidden gizmo probe.",
|
|
356
|
+
hidden: true,
|
|
357
|
+
params: [],
|
|
358
|
+
output: { formatters: passthroughFormatters },
|
|
359
|
+
capability: {
|
|
360
|
+
needsStore: false,
|
|
361
|
+
mutates: false,
|
|
362
|
+
mcp: { expose: false, reason: "internal probe" },
|
|
363
|
+
},
|
|
364
|
+
run: async () => ({ ok: true }),
|
|
365
|
+
},
|
|
366
|
+
],
|
|
367
|
+
// A non-tool MCP surface, so `renderNonToolSurface` emits its Resources bullet.
|
|
368
|
+
// `register` is a no-op — the emitter reads only `surface.templates`.
|
|
369
|
+
mcpResources: {
|
|
370
|
+
surface: { templates: ["gizmo:{+uri}"] },
|
|
371
|
+
register: () => {},
|
|
372
|
+
},
|
|
373
|
+
// A native prompt surface, so `renderNonToolSurface` emits its Prompts bullet.
|
|
374
|
+
mcpPrompts: { register: () => {} },
|
|
375
|
+
};
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
* `block` content-parity + `ontology`/`graph inspect` tests are protected
|
|
7
7
|
* against) byte-for-byte and EXTENDS it with the entities the other bundled
|
|
8
8
|
* read nouns (`standard`, `modifier`, `token`, `tier`) need, plus two more
|
|
9
|
-
* blocks that exercise tier-chain inheritance and channel visibility
|
|
10
|
-
* hand-written `block list`, Risk5).
|
|
11
|
-
*
|
|
9
|
+
* blocks that used to exercise tier-chain inheritance and channel visibility
|
|
10
|
+
* (PR3's hand-written `block list`, Risk5). Those two now serve the opposite
|
|
11
|
+
* purpose: L-OPEN-9 removed the filtering, so a tier-scoped and a
|
|
12
|
+
* channel-gated block are what prove the declared list hides NEITHER. Because
|
|
13
|
+
* `BLOCK_TTL` is reused verbatim, Button/Modal content can never drift between
|
|
14
|
+
* PR3's fixture and this one.
|
|
12
15
|
*
|
|
13
16
|
* Composed as one Turtle document, so ONE store answers every read noun:
|
|
14
17
|
* `block`/`ontology`/`graph inspect` were already provable on `BLOCK_TTL`
|