@canonical/pragma-cli 0.33.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 +7 -7
- package/dist/pragma +0 -0
- package/package.json +18 -15
- package/pragma.conf.ts +664 -0
- package/src/bin.ts +13 -4
- package/src/capabilities/block.parity.test.ts +250 -0
- package/src/capabilities/capabilities/capabilities.render.ts +3 -2
- package/src/capabilities/capabilities/capabilities.verb.ts +31 -13
- package/src/capabilities/capabilities/catalog.ts +18 -10
- package/src/capabilities/capabilities/hints.ts +13 -19
- package/src/capabilities/colophon/collectColophon.ts +34 -19
- package/src/capabilities/colophon/colophon.verb.ts +8 -4
- 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 +0 -27
- package/src/capabilities/config/set.verb.ts +7 -3
- package/src/capabilities/config/show.render.test.ts +77 -5
- package/src/capabilities/config/show.render.ts +7 -12
- package/src/capabilities/config/show.verb.ts +4 -3
- package/src/capabilities/config/types.ts +8 -0
- package/src/capabilities/create/byteEquality.test.ts +78 -100
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +52 -15
- 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 +162 -15
- package/src/capabilities/create/create.verb.ts +140 -69
- 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/checkMcpConfigured.ts +7 -6
- 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/doctor.render.test.ts +6 -6
- package/src/capabilities/doctor/doctor.render.ts +2 -1
- package/src/capabilities/doctor/doctor.test.ts +37 -8
- package/src/capabilities/doctor/doctor.verb.ts +6 -2
- package/src/capabilities/doctor/runChecks.ts +5 -5
- package/src/capabilities/doctor/types.ts +1 -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/verbs.ts +21 -21
- package/src/capabilities/prompt/prompt.test.ts +12 -6
- package/src/capabilities/prompt/verbs.ts +24 -11
- package/src/capabilities/resources/provider.ts +30 -11
- package/src/capabilities/resources/resources.test.ts +85 -29
- package/src/capabilities/setup/operations/setupGenerator.ts +16 -9
- package/src/capabilities/setup/operations/setupMcp.ts +2 -2
- package/src/capabilities/setup/operations/setupSkills.ts +3 -3
- package/src/capabilities/setup/setup.verb.ts +12 -5
- package/src/capabilities/setup/shell.ts +29 -3
- 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 +55 -50
- package/src/capabilities/sources/index.ts +1 -1
- package/src/capabilities/sources/installSkills.ts +2 -2
- package/src/capabilities/sources/runUpdate.ts +113 -122
- package/src/capabilities/sources/sources.test.ts +111 -117
- package/src/capabilities/sources/status.render.test.ts +53 -24
- package/src/capabilities/sources/status.render.ts +24 -29
- 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 +33 -10
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
- package/src/constants.test.ts +8 -6
- package/src/constants.ts +47 -21
- package/src/identity.test.ts +333 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +5 -2
- 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 +117 -107
- package/src/kernel/completion/model.test.ts +1 -1
- package/src/kernel/completion/model.ts +11 -0
- 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 +1 -1
- 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/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 +9 -4
- package/src/kernel/project/cli/dispatch.test.ts +67 -0
- package/src/kernel/project/cli/dispatch.ts +34 -12
- package/src/kernel/project/cli/helpFormat.ts +1 -1
- package/src/kernel/project/cli/rootHelp.ts +105 -105
- package/src/kernel/project/mcp/buildServer.ts +11 -6
- package/src/kernel/project/mcp/instructions.ts +11 -6
- package/src/kernel/project/mcp/parity.test.ts +39 -1
- package/src/kernel/project/mcp/prompts/prompts.test.ts +120 -5
- package/src/kernel/project/mcp/prompts/provider.ts +22 -8
- 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/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +1 -1
- package/src/kernel/runtime/graphpack/build.ts +29 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +46 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +52 -17
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -5
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -3
- 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 +205 -5
- 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 +4 -9
- 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 +61 -48
- 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 +78 -62
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +9 -8
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +22 -19
- package/src/kernel/spec/emitReference.test.ts +3 -3
- package/src/kernel/spec/emitReference.ts +144 -11
- package/src/kernel/spec/emitSurface.ts +9 -5
- 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 +8 -2
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/completion.test.ts +19 -6
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +1 -1
- 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 -75
- package/src/testing/behavioral/journeys.defaultPack.test.ts +82 -176
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +9 -6
- 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 +9 -4
- package/src/testing/behavioral/staleCommands.test.ts +10 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +7 -7
- package/src/testing/eval/cases/assembly.ts +13 -6
- package/src/testing/eval/cases/effectful.ts +25 -13
- package/src/testing/eval/cases/readNouns.ts +22 -20
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/fixtureCapability.ts +45 -1
- package/src/testing/fixtures/graph/canonical.ts +6 -3
- package/src/testing/fixtures/graph/defaultPack.ts +6 -5
- package/src/testing/fixtures/graph/owlExport.ts +7 -5
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- 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.test.ts +0 -79
- package/src/capabilities/block/blockList.verb.ts +0 -163
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -166
- package/src/capabilities/block/parity.test.ts +0 -187
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- 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.test.ts +0 -72
- package/src/capabilities/tier/lookup.render.ts +0 -59
- package/src/capabilities/tier/lookup.test.ts +0 -83
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -87
- 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
|
@@ -14,7 +14,7 @@ export type CheckStatus = "pass" | "fail" | "skip";
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* A structured sub-item under a check — e.g. one resolved package under
|
|
17
|
-
* `
|
|
17
|
+
* `pack refs`, or one unresolvable server under `MCP commands`. Lets the
|
|
18
18
|
* formatter render an indented, aligned breakdown instead of cramming
|
|
19
19
|
* everything into a single `detail` string.
|
|
20
20
|
*/
|
|
@@ -3,24 +3,34 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Listing zero rows is a calm SUCCESS, not an error. The run body returns `[]`
|
|
5
5
|
* (no throw), dispatch renders a non-blank message and exits 0, and JSON stays
|
|
6
|
-
* `[]`. A
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* `[]`. A story's declared `emptyRecovery` becomes that message's HINT — but as
|
|
7
|
+
* guidance on the success path, never a thrown EMPTY_RESULTS (which maps to
|
|
8
|
+
* exit 1 and would break the uniform `ok:true` list contract).
|
|
9
|
+
*
|
|
10
|
+
* The story declares the command WITHOUT a binary name (`sources update`); the
|
|
11
|
+
* renderer prepends the CONSUMING distribution's. The hints asserted below are
|
|
12
|
+
* therefore the JOINED string, which is what a user reads — a story that named
|
|
13
|
+
* a binary itself would render it twice, and the grammar now refuses one.
|
|
10
14
|
*/
|
|
11
15
|
|
|
12
16
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
13
17
|
import { compilePack } from "../kernel/packs/compile.js";
|
|
14
18
|
import type { PackDefinition } from "../kernel/packs/types.js";
|
|
19
|
+
import { distributionSource } from "../kernel/packs/types.js";
|
|
15
20
|
import { verbKey } from "../kernel/packs/uniqueness.js";
|
|
16
21
|
import { executeVerb } from "../kernel/project/cli/dispatch.js";
|
|
17
22
|
import { DEFAULT_PREFIX_MAP } from "../kernel/render/prefixes.js";
|
|
18
23
|
import type { PragmaRuntime } from "../kernel/runtime/types.js";
|
|
19
24
|
import type { VerbSpec } from "../kernel/spec/types.js";
|
|
20
25
|
import { buildFixtureRuntime } from "../testing/helpers/packRuntime.js";
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
import { declaredStories } from "./distribution.js";
|
|
27
|
+
|
|
28
|
+
/** A story `pragma.conf.ts` declares — absent means it was renamed or dropped. */
|
|
29
|
+
function storyFor(noun: string): PackDefinition {
|
|
30
|
+
const story = declaredStories.get(noun);
|
|
31
|
+
if (!story) throw new Error(`pragma.conf.ts declares no story for "${noun}"`);
|
|
32
|
+
return story;
|
|
33
|
+
}
|
|
24
34
|
|
|
25
35
|
const PREFIXES = {
|
|
26
36
|
ds: "https://ds.canonical.com/",
|
|
@@ -61,19 +71,21 @@ afterAll(async () => {
|
|
|
61
71
|
});
|
|
62
72
|
|
|
63
73
|
const listVerb = (pack: PackDefinition): VerbSpec =>
|
|
64
|
-
compilePack(
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
compilePack(
|
|
75
|
+
pack,
|
|
76
|
+
distributionSource("pragma.conf.ts"),
|
|
77
|
+
DEFAULT_PREFIX_MAP,
|
|
78
|
+
).find((v) => verbKey(v.path) === `${pack.noun} list`) as VerbSpec;
|
|
67
79
|
|
|
68
80
|
/**
|
|
69
|
-
* Every
|
|
81
|
+
* Every declared story's list verb, with the hint expected in its empty message:
|
|
70
82
|
* an authored `emptyRecovery` surfaces `pragma sources update`; the others fall
|
|
71
83
|
* back to the generic build/broaden hint.
|
|
72
84
|
*/
|
|
73
85
|
const PACK_LISTS: readonly { pack: PackDefinition; hint: RegExp }[] = [
|
|
74
|
-
{ pack:
|
|
75
|
-
{ pack:
|
|
76
|
-
{ pack:
|
|
86
|
+
{ pack: storyFor("modifier"), hint: /pragma sources update/ },
|
|
87
|
+
{ pack: storyFor("token"), hint: /pragma sources update/ },
|
|
88
|
+
{ pack: storyFor("standard"), hint: /broaden your filter/ },
|
|
77
89
|
];
|
|
78
90
|
|
|
79
91
|
const REAL = { dryRun: false, undo: false, yes: false };
|
|
@@ -104,7 +116,12 @@ describe("pack list empty-state (U5, PROTECTED)", () => {
|
|
|
104
116
|
});
|
|
105
117
|
|
|
106
118
|
it("dispatch prints the empty message on stdout and exits 0 (end-to-end)", async () => {
|
|
107
|
-
const outcome = await executeVerb(
|
|
119
|
+
const outcome = await executeVerb(
|
|
120
|
+
listVerb(storyFor("modifier")),
|
|
121
|
+
{},
|
|
122
|
+
REAL,
|
|
123
|
+
rt,
|
|
124
|
+
);
|
|
108
125
|
expect(outcome.exitCode).toBe(0);
|
|
109
126
|
expect(outcome.stdout).toContain("No modifier entries found.");
|
|
110
127
|
expect(outcome.stdout).toContain("pragma sources update");
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* name or absolute IRI addresses the subject exactly.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import { BIN_NAME } from "../../constants.js";
|
|
11
12
|
import type { InspectResult } from "../../kernel/runtime/readEntity.js";
|
|
12
13
|
import { readEntity } from "../../kernel/runtime/readEntity.js";
|
|
13
14
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
@@ -32,8 +33,8 @@ const inspectVerb: VerbSpec<Record<string, unknown>, InspectResult> = {
|
|
|
32
33
|
],
|
|
33
34
|
output: { formatters: inspectFormatters },
|
|
34
35
|
examples: [
|
|
35
|
-
{ cmd:
|
|
36
|
-
{ cmd:
|
|
36
|
+
{ cmd: `${BIN_NAME} graph inspect ds:button` },
|
|
37
|
+
{ cmd: `${BIN_NAME} graph inspect https://ds.canonical.com/button` },
|
|
37
38
|
],
|
|
38
39
|
capability: {
|
|
39
40
|
needsStore: true,
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* query surfaces as INVALID_INPUT with a recovery pointer to `ontology list`.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { BIN_NAME } from "../../constants.js";
|
|
12
13
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
13
14
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
14
15
|
import type { VerbSpec } from "../../kernel/spec/types.js";
|
|
@@ -35,11 +36,11 @@ const queryVerb: VerbSpec<Record<string, unknown>, QueryResult> = {
|
|
|
35
36
|
output: { formatters: queryFormatters },
|
|
36
37
|
examples: [
|
|
37
38
|
{
|
|
38
|
-
cmd:
|
|
39
|
+
cmd: `${BIN_NAME} graph query "SELECT ?s WHERE { ?s a ds:Component }"`,
|
|
39
40
|
note: "list every component subject",
|
|
40
41
|
},
|
|
41
42
|
{
|
|
42
|
-
cmd:
|
|
43
|
+
cmd: `${BIN_NAME} graph query "ASK { ds:button a ds:Component }" --format json`,
|
|
43
44
|
},
|
|
44
45
|
],
|
|
45
46
|
capability: {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import type { QueryResult } from "@canonical/ke";
|
|
13
13
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
14
|
+
import { cliRecovery } from "../../kernel/error/recovery.js";
|
|
14
15
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -39,11 +40,13 @@ export async function runQuery(
|
|
|
39
40
|
message: detail
|
|
40
41
|
? `Invalid SPARQL query: ${detail}`
|
|
41
42
|
: "Invalid SPARQL query.",
|
|
42
|
-
recovery:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
recovery: cliRecovery(
|
|
44
|
+
"ontology list",
|
|
45
|
+
"Check your SPARQL syntax and the loaded namespaces.",
|
|
46
|
+
{
|
|
47
|
+
tool: "ontology_list",
|
|
48
|
+
},
|
|
49
|
+
),
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -1,46 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The capability registry:
|
|
3
|
-
*
|
|
2
|
+
* The capability registry: every capability module the projectors consume
|
|
3
|
+
* (D8 — test-only fixtures are never listed here).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Two sources, in this order: the literal array of AUTHORED modules (in
|
|
6
|
+
* authoring order; projectors sort where they need to), then every story
|
|
7
|
+
* `pragma.conf.ts` declares that no authored module already claims. Since
|
|
8
|
+
* L-OPEN-9 no DATA noun is authored — the authored array is the kernel's own
|
|
9
|
+
* nouns and nothing else, and every design-system noun appears only in the
|
|
10
|
+
* config. No noun literal is written here: the second half is derived.
|
|
11
|
+
*
|
|
12
|
+
* Importing this barrel pulls only spec + formatter modules — every run body is
|
|
13
|
+
* behind a lazy dynamic import, and `distribution.ts` is zod-free — so the
|
|
9
14
|
* `--help`/`__complete` fast paths stay free of the config reader and zod.
|
|
10
15
|
*/
|
|
11
16
|
|
|
12
17
|
import type { CapabilityModule } from "../kernel/spec/types.js";
|
|
13
|
-
import { blockModule } from "./block/index.js";
|
|
14
18
|
import { capabilitiesModule } from "./capabilities/index.js";
|
|
15
19
|
import { colophonModule } from "./colophon/index.js";
|
|
16
20
|
import { configModule } from "./config/index.js";
|
|
17
21
|
import { createModule } from "./create/index.js";
|
|
22
|
+
import { storyModules } from "./distribution.js";
|
|
18
23
|
import { doctorModule } from "./doctor/index.js";
|
|
19
24
|
import { graphModule } from "./graph/index.js";
|
|
20
25
|
import { infoModule } from "./info/index.js";
|
|
21
26
|
import { metaModule } from "./meta/index.js";
|
|
22
|
-
import { modifierModule } from "./modifier/index.js";
|
|
23
27
|
import { ontologyModule } from "./ontology/index.js";
|
|
24
28
|
import { promptModule } from "./prompt/index.js";
|
|
25
29
|
import { setupModule } from "./setup/index.js";
|
|
26
30
|
import { skillModule } from "./skill/index.js";
|
|
27
31
|
import { sourcesModule } from "./sources/index.js";
|
|
28
|
-
import { standardModule } from "./standard/index.js";
|
|
29
|
-
import { tierModule } from "./tier/index.js";
|
|
30
|
-
import { tokenModule } from "./token/index.js";
|
|
31
32
|
import { upgradeModule } from "./upgrade/index.js";
|
|
32
33
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
34
|
+
/** The modules with hand-written code, in authoring order. */
|
|
35
|
+
const authored: readonly CapabilityModule[] = [
|
|
35
36
|
infoModule,
|
|
36
37
|
configModule,
|
|
37
38
|
createModule,
|
|
38
39
|
sourcesModule,
|
|
39
|
-
standardModule,
|
|
40
|
-
tierModule,
|
|
41
|
-
modifierModule,
|
|
42
|
-
tokenModule,
|
|
43
|
-
blockModule,
|
|
44
40
|
ontologyModule,
|
|
45
41
|
skillModule,
|
|
46
42
|
graphModule,
|
|
@@ -52,3 +48,11 @@ export const capabilities: readonly CapabilityModule[] = [
|
|
|
52
48
|
colophonModule,
|
|
53
49
|
metaModule,
|
|
54
50
|
];
|
|
51
|
+
|
|
52
|
+
const claimed = new Set(authored.map((module) => module.name));
|
|
53
|
+
|
|
54
|
+
/** Every capability module: the authored ones, then the unclaimed declared stories. */
|
|
55
|
+
export const capabilities: readonly CapabilityModule[] = [
|
|
56
|
+
...authored,
|
|
57
|
+
...[...storyModules.values()].filter((module) => !claimed.has(module.name)),
|
|
58
|
+
];
|
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
* the npm registry — this deliberately REVERSES PR1's networkless-D11 stance for
|
|
7
7
|
* `info` (the reversal IS the enrichment), unconditional because the covenant
|
|
8
8
|
* `info` verb carries no flag, 3s timeout, silent-fail — and (b) a storeless
|
|
9
|
-
* entity total from the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* entity total, read from the index of whichever pack the boot decision names
|
|
10
|
+
* (`resolveSources` → `readPackIndex`, the same predicate `sources status` and
|
|
11
|
+
* `doctor` switch on) so `info` never counts a graph this project's reads
|
|
12
|
+
* refuse. Neither enrichment boots the store, so the storeless-guarantee spy
|
|
13
|
+
* still sees `store.booted === false`. Kept out of the spec module so building
|
|
14
|
+
* the command tree never pulls it onto the `--help` fast path.
|
|
13
15
|
*/
|
|
14
16
|
|
|
15
17
|
import {
|
|
@@ -17,6 +19,7 @@ import {
|
|
|
17
19
|
readPackIndex,
|
|
18
20
|
} from "../../kernel/completion/entitySource.js";
|
|
19
21
|
import { readConfig } from "../../kernel/config/readConfig.js";
|
|
22
|
+
import { resolveSources } from "../../kernel/runtime/resolveSources.js";
|
|
20
23
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
21
24
|
import {
|
|
22
25
|
detectInstallSource,
|
|
@@ -50,8 +53,9 @@ export async function collectInfo(runtime: PragmaRuntime): Promise<InfoData> {
|
|
|
50
53
|
: undefined;
|
|
51
54
|
const updateSkipped = registry === undefined;
|
|
52
55
|
|
|
53
|
-
// Entity total: storeless
|
|
54
|
-
|
|
56
|
+
// Entity total: storeless, over the pack the boot decision names — so a
|
|
57
|
+
// configured-but-unbuilt project reports no total rather than the snapshot's.
|
|
58
|
+
const index = readPackIndex(resolveSources(layers, runtime.cwd));
|
|
55
59
|
const entities = index ? entityTotal(index) : undefined;
|
|
56
60
|
|
|
57
61
|
return {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Formatters for `pragma info` — plain, llm, json (no ink).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { BIN_NAME } from "../../constants.js";
|
|
5
6
|
import type { ConfigOrigin } from "../../kernel/config/types.js";
|
|
6
7
|
import type { Formatters } from "../../kernel/spec/types.js";
|
|
7
8
|
import type { InfoData } from "./types.js";
|
|
@@ -15,7 +16,7 @@ export const infoFormatters: Formatters<InfoData> = {
|
|
|
15
16
|
plain(data) {
|
|
16
17
|
const { config } = data;
|
|
17
18
|
const lines = [
|
|
18
|
-
|
|
19
|
+
`${BIN_NAME} v${data.version}`,
|
|
19
20
|
` Installed via: ${data.installSource}`,
|
|
20
21
|
` tier: ${config.tier ?? "(none)"}${originMarker(config.origins.tier)}`,
|
|
21
22
|
` channel: ${config.channel}${originMarker(config.origins.channel)}`,
|
|
@@ -45,7 +46,7 @@ export const infoFormatters: Formatters<InfoData> = {
|
|
|
45
46
|
llm(data) {
|
|
46
47
|
const { config } = data;
|
|
47
48
|
const lines = [
|
|
48
|
-
`#
|
|
49
|
+
`# ${BIN_NAME} v${data.version}`,
|
|
49
50
|
`- Installed via: ${data.installSource}`,
|
|
50
51
|
`- Tier: ${config.tier ?? "(none)"}${originMarker(config.origins.tier)}`,
|
|
51
52
|
`- Channel: ${config.channel}${originMarker(config.origins.channel)}`,
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* the config reader or zod onto the fast path.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { BIN_NAME } from "../../constants.js";
|
|
9
10
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
10
11
|
import type { CapabilityModule, VerbSpec } from "../../kernel/spec/types.js";
|
|
11
12
|
import { infoFormatters } from "./info.render.js";
|
|
@@ -18,9 +19,9 @@ const infoVerb: VerbSpec<Record<string, unknown>, InfoData> = {
|
|
|
18
19
|
params: [],
|
|
19
20
|
output: { formatters: infoFormatters },
|
|
20
21
|
examples: [
|
|
21
|
-
{ cmd:
|
|
22
|
+
{ cmd: `${BIN_NAME} info`, note: "human-readable summary" },
|
|
22
23
|
{
|
|
23
|
-
cmd:
|
|
24
|
+
cmd: `${BIN_NAME} info --format json`,
|
|
24
25
|
note: "the full {ok,data,meta} envelope",
|
|
25
26
|
},
|
|
26
27
|
],
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import { dirname, resolve } from "node:path";
|
|
2
|
+
import { dirname, relative, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { describe, expect, it } from "vitest";
|
|
5
5
|
|
|
@@ -45,10 +45,63 @@ describe("lazy dispatch — module-graph probe (PROTECTED)", () => {
|
|
|
45
45
|
expect(has(graph, "info/info.render.ts")).toBe(true);
|
|
46
46
|
expect(has(graph, "config/show.render.ts")).toBe(true);
|
|
47
47
|
|
|
48
|
-
// ...but run bodies and the config
|
|
48
|
+
// ...but run bodies and the config LAYER stay behind the dynamic boundary:
|
|
49
|
+
// no reader, no defaults layer, no zod schema. The distribution config
|
|
50
|
+
// itself IS on the graph — `constants.ts` projects the program's identity
|
|
51
|
+
// from it, `render/prefixes.ts` its domain namespaces and
|
|
52
|
+
// `kernel/vocabulary.ts` its domain terms — which is safe only because it
|
|
53
|
+
// is inert data (pinned below).
|
|
49
54
|
expect(has(graph, "info/collectInfo.ts")).toBe(false);
|
|
50
55
|
expect(has(graph, "config/collectConfigShow.ts")).toBe(false);
|
|
51
56
|
expect(has(graph, "kernel/config/readConfig.ts")).toBe(false);
|
|
57
|
+
expect(has(graph, "kernel/config/defaults.ts")).toBe(false);
|
|
58
|
+
expect(has(graph, "kernel/config/schema.ts")).toBe(false);
|
|
59
|
+
expect(has(graph, "pragma.conf.ts")).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("the distribution config is inert data — it imports nothing that runs", () => {
|
|
63
|
+
const conf = resolve(here, "../../pragma.conf.ts");
|
|
64
|
+
const pkgRoot = resolve(here, "../..");
|
|
65
|
+
// The graph walker follows `from "…"` textually and cannot tell an
|
|
66
|
+
// `import type` from a value import, so the type-only `config/types.ts`
|
|
67
|
+
// and `packs/types.ts` show up here even though nothing of either survives
|
|
68
|
+
// compilation. Assert that NO file on the graph has a value import — not
|
|
69
|
+
// just the conf. That is the claim in the title, and it is what keeps
|
|
70
|
+
// `--help`/`__complete`/`--version` free of module-init work when another
|
|
71
|
+
// lane or a fork edits any of these three (`packs/types.ts` in particular
|
|
72
|
+
// is the grammar that type-checks the declared stories, and its own
|
|
73
|
+
// docblock promises it stays zod-free BECAUSE it lands here).
|
|
74
|
+
const graph = [...staticImportGraph(conf)];
|
|
75
|
+
for (const file of graph) {
|
|
76
|
+
expect(readFileSync(file, "utf-8"), file).not.toMatch(
|
|
77
|
+
/^import (?!type\b)/m,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
// The enumeration is exact, not a subset: a type import from a module that
|
|
81
|
+
// itself imports something grows this list and fails here.
|
|
82
|
+
expect(graph.map((f) => relative(pkgRoot, f)).sort()).toEqual([
|
|
83
|
+
"pragma.conf.ts",
|
|
84
|
+
"src/kernel/config/types.ts",
|
|
85
|
+
"src/kernel/packs/types.ts",
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("the dispatch path never reaches the embedded n-quads module (PROTECTED)", () => {
|
|
90
|
+
// `activeStories` reads the pack's carried stories from their OWN generated
|
|
91
|
+
// module rather than through `graphpack/embedded.ts`, which statically
|
|
92
|
+
// imports the ~1.9 MB `pack.generated.ts`. Restoring that edge costs a
|
|
93
|
+
// measured +23 ms on EVERY dispatched command, and the whole test suite
|
|
94
|
+
// passes with it restored — the split is prose in three docblocks and
|
|
95
|
+
// nothing else. This is the constraint those docblocks describe.
|
|
96
|
+
for (const entry of [
|
|
97
|
+
"../kernel/packs/collect.ts",
|
|
98
|
+
"../kernel/runtime/graphpack/stories.ts",
|
|
99
|
+
"../kernel/runtime/resolveSources.ts",
|
|
100
|
+
]) {
|
|
101
|
+
const graph = staticImportGraph(resolve(here, entry));
|
|
102
|
+
expect(has(graph, "embedded/pack.generated.ts"), entry).toBe(false);
|
|
103
|
+
expect(has(graph, "graphpack/embedded.ts"), entry).toBe(false);
|
|
104
|
+
}
|
|
52
105
|
});
|
|
53
106
|
|
|
54
107
|
it("the help path (buildProgram) imports no zod schema module", () => {
|
|
@@ -86,4 +139,42 @@ describe("lazy dispatch — module-graph probe (PROTECTED)", () => {
|
|
|
86
139
|
}
|
|
87
140
|
}
|
|
88
141
|
});
|
|
142
|
+
|
|
143
|
+
it("NO module on that graph statically imports zod (PROTECTED)", () => {
|
|
144
|
+
// This used to pin an exact set of one — `graphpack/types.ts`, reached via
|
|
145
|
+
// `resolveSources` → `packIsComplete` → `readManifest` → `manifestSchema
|
|
146
|
+
// .parse` — as the one genuine zod value import on the storeless graph,
|
|
147
|
+
// measured at ~3–4 ms of a ~30 ms budget. Its own comment said an exact set
|
|
148
|
+
// was what would make the day it got fixed impossible to miss. That day is
|
|
149
|
+
// this commit: the schemas moved to `graphpack/schemas.ts`, imported only by
|
|
150
|
+
// the two readers already off the fast path, and `readManifest` validates
|
|
151
|
+
// structurally instead.
|
|
152
|
+
//
|
|
153
|
+
// The set is now EMPTY, which is strictly stronger than the pin it replaces:
|
|
154
|
+
// it no longer tolerates one named module, so a brand-new module value-
|
|
155
|
+
// importing zod fails here too — the gap the previous form left open.
|
|
156
|
+
const graph = staticImportGraph(resolve(here, "index.ts"));
|
|
157
|
+
const pkgRoot = resolve(here, "..", "..");
|
|
158
|
+
const zodImporters = [...graph]
|
|
159
|
+
.filter((file) => /from\s*["']zod["']/.test(readFileSync(file, "utf-8")))
|
|
160
|
+
.map((file) => relative(pkgRoot, file))
|
|
161
|
+
.sort();
|
|
162
|
+
expect(zodImporters).toEqual([]);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("the help path (buildProgram) imports zod from nowhere (PROTECTED)", () => {
|
|
166
|
+
// The named-module check above (`kernel/config/schema.ts`,
|
|
167
|
+
// `kernel/spec/validate.ts`) could only catch the two modules it names — a
|
|
168
|
+
// third zod importer reaching the help path would have passed it silently.
|
|
169
|
+
// Generalized (ruling R4) to the property those names were standing in for.
|
|
170
|
+
const graph = staticImportGraph(
|
|
171
|
+
resolve(here, "../kernel/project/cli/buildProgram.ts"),
|
|
172
|
+
);
|
|
173
|
+
const pkgRoot = resolve(here, "..", "..");
|
|
174
|
+
const zodImporters = [...graph]
|
|
175
|
+
.filter((file) => /from\s*["']zod["']/.test(readFileSync(file, "utf-8")))
|
|
176
|
+
.map((file) => relative(pkgRoot, file))
|
|
177
|
+
.sort();
|
|
178
|
+
expect(zodImporters).toEqual([]);
|
|
179
|
+
});
|
|
89
180
|
});
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
* any level), so the covenant is untouched.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
+
import { BIN_NAME } from "../../constants.js";
|
|
25
26
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
27
|
+
import { cliRecovery } from "../../kernel/error/recovery.js";
|
|
26
28
|
import { resolvePackDetail } from "../../kernel/packs/disclosure.js";
|
|
27
29
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
28
30
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
@@ -51,22 +53,22 @@ function resolvePrefix(
|
|
|
51
53
|
if (entry) return { prefix: entry[0], namespace: entry[1] };
|
|
52
54
|
throw PragmaError.invalidInput("namespace", input, {
|
|
53
55
|
validOptions: Object.values(prefixes),
|
|
54
|
-
recovery:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
recovery: cliRecovery(
|
|
57
|
+
"ontology list",
|
|
58
|
+
"List loaded ontology namespaces.",
|
|
59
|
+
{
|
|
60
|
+
tool: "ontology_list",
|
|
61
|
+
},
|
|
62
|
+
),
|
|
59
63
|
});
|
|
60
64
|
}
|
|
61
65
|
const namespace = prefixes[input];
|
|
62
66
|
if (namespace === undefined) {
|
|
63
67
|
throw PragmaError.invalidInput("prefix", input, {
|
|
64
68
|
validOptions: Object.keys(prefixes),
|
|
65
|
-
recovery: {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
mcp: { tool: "ontology_list" },
|
|
69
|
-
},
|
|
69
|
+
recovery: cliRecovery("ontology list", "List loaded ontologies.", {
|
|
70
|
+
tool: "ontology_list",
|
|
71
|
+
}),
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
return { prefix: input, namespace };
|
|
@@ -77,7 +79,7 @@ const listVerb: VerbSpec<Record<string, unknown>, OntologySummary[]> = {
|
|
|
77
79
|
summary: "List loaded ontology namespaces with class and property counts.",
|
|
78
80
|
params: [],
|
|
79
81
|
output: { formatters: ontologyListFormatters },
|
|
80
|
-
examples: [{ cmd:
|
|
82
|
+
examples: [{ cmd: `${BIN_NAME} ontology list` }],
|
|
81
83
|
capability: {
|
|
82
84
|
needsStore: true,
|
|
83
85
|
mutates: false,
|
|
@@ -193,11 +195,9 @@ async function runByName(
|
|
|
193
195
|
|
|
194
196
|
if (classes.length === 0 && properties.length === 0) {
|
|
195
197
|
throw PragmaError.notFound("ontology", String(params.prefix), {
|
|
196
|
-
recovery: {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
mcp: { tool: "ontology_list" },
|
|
200
|
-
},
|
|
198
|
+
recovery: cliRecovery("ontology list", "List loaded ontologies.", {
|
|
199
|
+
tool: "ontology_list",
|
|
200
|
+
}),
|
|
201
201
|
});
|
|
202
202
|
}
|
|
203
203
|
|
|
@@ -244,9 +244,9 @@ export const ontologyLookupVerb = asVerb(
|
|
|
244
244
|
"lookup",
|
|
245
245
|
"Look up a namespace's classes (hierarchy + counts) and properties.",
|
|
246
246
|
[
|
|
247
|
-
{ cmd:
|
|
248
|
-
{ cmd:
|
|
249
|
-
{ cmd:
|
|
247
|
+
{ cmd: `${BIN_NAME} ontology lookup ds` },
|
|
248
|
+
{ cmd: `${BIN_NAME} ontology lookup ds --properties` },
|
|
249
|
+
{ cmd: `${BIN_NAME} ontology lookup ds --class Component` },
|
|
250
250
|
],
|
|
251
251
|
),
|
|
252
252
|
);
|
|
@@ -261,8 +261,8 @@ export const ontologyShowVerb = asVerb(
|
|
|
261
261
|
"show",
|
|
262
262
|
"(deprecated: use `ontology lookup`) Show a namespace's classes (hierarchy + counts) and properties.",
|
|
263
263
|
[
|
|
264
|
-
{ cmd:
|
|
265
|
-
{ cmd:
|
|
264
|
+
{ cmd: `${BIN_NAME} ontology lookup ds`, note: "prefer `lookup`" },
|
|
265
|
+
{ cmd: `${BIN_NAME} ontology show ds`, note: "deprecated alias" },
|
|
266
266
|
],
|
|
267
267
|
"Deprecated alias of `ontology lookup` — retained for compatibility. Prefer `ontology lookup <prefix>`.",
|
|
268
268
|
),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { mkdtempSync } from "node:fs";
|
|
1
|
+
import { mkdtempSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { afterAll, beforeAll, describe, expect, it } from "vitest";
|
|
5
5
|
import { listPromptSummaries } from "../../kernel/project/mcp/prompts/source.js";
|
|
6
6
|
import { bootRuntime } from "../../kernel/runtime/boot.js";
|
|
7
|
-
import {
|
|
7
|
+
import { resolveSources } from "../../kernel/runtime/resolveSources.js";
|
|
8
8
|
import type { GlobalFlags } from "../../kernel/spec/types.js";
|
|
9
9
|
import { CANONICAL_TTL } from "../../testing/fixtures/graph/canonical.js";
|
|
10
10
|
import {
|
|
@@ -116,7 +116,9 @@ describe("prompt — native MCP prompts surface (PROTECTED)", () => {
|
|
|
116
116
|
describe("prompt — storeless native listing (PROTECTED)", () => {
|
|
117
117
|
it("listing the prompts does NOT boot the store", async () => {
|
|
118
118
|
const runtime = bootRuntime(FLAGS, fixture.cwd);
|
|
119
|
-
const summaries = listPromptSummaries(
|
|
119
|
+
const summaries = listPromptSummaries(
|
|
120
|
+
resolveSources(await runtime.loadConfig(), runtime.cwd),
|
|
121
|
+
);
|
|
120
122
|
expect(summaries.map((s) => s.name).sort()).toEqual(EXPECTED);
|
|
121
123
|
expect(runtime.store.booted).toBe(false);
|
|
122
124
|
});
|
|
@@ -127,15 +129,19 @@ describe("prompt — storeless native listing (PROTECTED)", () => {
|
|
|
127
129
|
* (`needsStore`), so a cold store throws STORE_UNAVAILABLE through its pre-check;
|
|
128
130
|
* native `prompts/list`/`prompts/get` must present the SAME diagnostic rather
|
|
129
131
|
* than silently listing a stale index (D1) or reporting a bogus "not found"
|
|
130
|
-
* (D4). A
|
|
131
|
-
* store
|
|
132
|
+
* (D4). A project that declares its own packs and has never built them is the
|
|
133
|
+
* cold "configured but unbuilt" store — the row of the boot decision table
|
|
134
|
+
* that must never be served the distribution's embedded graph.
|
|
132
135
|
*/
|
|
133
136
|
describe("prompt — cold-store convergence, tool + native agree (D1/D4)", () => {
|
|
134
137
|
let cold: McpHarness;
|
|
135
138
|
|
|
136
139
|
beforeAll(async () => {
|
|
137
140
|
const cwd = mkdtempSync(join(tmpdir(), "pragma-prompt-cold-"));
|
|
138
|
-
|
|
141
|
+
writeFileSync(
|
|
142
|
+
join(cwd, "pragma.config.ts"),
|
|
143
|
+
`export default { packs: [{ name: "unbuilt", source: "file:///pragma-never-built" }] };\n`,
|
|
144
|
+
);
|
|
139
145
|
cold = await projectMcp(capabilities, cwd);
|
|
140
146
|
});
|
|
141
147
|
afterAll(async () => {
|