@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
|
@@ -2,28 +2,37 @@
|
|
|
2
2
|
* Data shapes for `pragma colophon`.
|
|
3
3
|
*
|
|
4
4
|
* A colophon (the printer's end-note on how a book is made) for the toolchain:
|
|
5
|
-
* one section narrating how
|
|
6
|
-
*
|
|
5
|
+
* one section narrating how the distribution itself is built — declared in its
|
|
6
|
+
* config, not authored in code — followed by one section per active pack/domain
|
|
7
|
+
* that declares a `colophon`. Storeless and read-only.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
|
-
/** One colophon section —
|
|
10
|
+
/** One colophon section — the distribution's own, or an active pack's story. */
|
|
10
11
|
export interface ColophonSection {
|
|
11
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* Whether this is the distribution's declared section or an active pack's.
|
|
14
|
+
* `"pragma"` is a FROZEN JSON-visible discriminant (wire compatibility, like
|
|
15
|
+
* the `pragma:` resource scheme) — it does not track the distribution's
|
|
16
|
+
* name; a fork's own section still carries `kind: "pragma"`.
|
|
17
|
+
*/
|
|
12
18
|
readonly kind: "pragma" | "pack";
|
|
13
|
-
/** Section heading —
|
|
19
|
+
/** Section heading — the distribution's name, or the pack's noun/name. */
|
|
14
20
|
readonly title: string;
|
|
15
21
|
/**
|
|
16
22
|
* The authored Markdown BODY (no leading H1 — the renderer supplies the
|
|
17
23
|
* heading from {@link title}, so a section is never double-titled).
|
|
18
24
|
*/
|
|
19
25
|
readonly markdown: string;
|
|
20
|
-
/** Optional condensed body for `--format llm` (
|
|
26
|
+
/** Optional condensed body for `--format llm` (the declaration's `summary`). */
|
|
21
27
|
readonly summary?: string;
|
|
22
28
|
/** Provenance: `"built-in"`, or `"pack:<name>"`. */
|
|
23
29
|
readonly source?: string;
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* The full `colophon` payload: the distribution's declared section first (when
|
|
34
|
+
* its config declares one), then active packs'.
|
|
35
|
+
*/
|
|
27
36
|
export interface ColophonData {
|
|
28
37
|
readonly sections: readonly ColophonSection[];
|
|
29
38
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `config show` payload projection — declared story BODIES never ship.
|
|
3
|
+
*
|
|
4
|
+
* MCP returns the JSON formatter's output verbatim, so anything in this payload
|
|
5
|
+
* is tokens in every `config_show` tool call. The distribution declares five
|
|
6
|
+
* read stories on its packs, whose bodies are SPARQL; carried through, they take
|
|
7
|
+
* the payload from ~1.3 KB to ~11 KB — larger than `capabilities`, the discovery
|
|
8
|
+
* tool, for the least useful content in the surface.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { mkdtempSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { describe, expect, it } from "vitest";
|
|
15
|
+
import { bootRuntime } from "../../kernel/runtime/boot.js";
|
|
16
|
+
import type { GlobalFlags } from "../../kernel/runtime/types.js";
|
|
17
|
+
import { collectConfigShow } from "./collectConfigShow.js";
|
|
18
|
+
|
|
19
|
+
const FLAGS: GlobalFlags = {
|
|
20
|
+
llm: false,
|
|
21
|
+
autoLlm: false,
|
|
22
|
+
format: "json",
|
|
23
|
+
verbose: false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
describe("config show payload", () => {
|
|
27
|
+
it("names the declared packs but carries no story bodies", async () => {
|
|
28
|
+
const cwd = mkdtempSync(join(tmpdir(), "pragma-config-show-"));
|
|
29
|
+
const data = await collectConfigShow(bootRuntime(FLAGS, cwd));
|
|
30
|
+
|
|
31
|
+
// The pack declarations themselves are still fully reported…
|
|
32
|
+
expect(
|
|
33
|
+
data.config.packs?.map((pack) =>
|
|
34
|
+
typeof pack === "string" ? pack : pack.name,
|
|
35
|
+
),
|
|
36
|
+
).toEqual([
|
|
37
|
+
"@canonical/design-system",
|
|
38
|
+
"@canonical/anatomy-dsl",
|
|
39
|
+
"@canonical/code-standards",
|
|
40
|
+
]);
|
|
41
|
+
for (const pack of data.config.packs ?? []) {
|
|
42
|
+
expect(
|
|
43
|
+
typeof pack === "string" ? undefined : pack.stories,
|
|
44
|
+
).toBeUndefined();
|
|
45
|
+
}
|
|
46
|
+
expect(data.config.stories).toBeUndefined();
|
|
47
|
+
|
|
48
|
+
// …and provenance stays honest: the payload still says where they came from.
|
|
49
|
+
expect(data.origins.packs).toBe("default");
|
|
50
|
+
expect(data.origins.stories).toBe("default");
|
|
51
|
+
|
|
52
|
+
// The sharp end: no query text reaches the agent surface.
|
|
53
|
+
const payload = JSON.stringify(data);
|
|
54
|
+
expect(payload).not.toContain("SELECT ?");
|
|
55
|
+
expect(payload.length).toBeLessThan(3000);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -1,15 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Collect the `config show` payload — the verb's run body (lazily imported).
|
|
3
3
|
*
|
|
4
|
-
* Storeless: read the layered config and pass it through with its provenance
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Storeless: read the layered config and pass it through with its provenance,
|
|
5
|
+
* minus the declared story BODIES (see {@link withoutStoryBodies}). Dynamic-
|
|
6
|
+
* imported by the spec so building the tree never pulls the config reader (or
|
|
7
|
+
* zod) onto the fast path.
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
import { readConfig } from "../../kernel/config/readConfig.js";
|
|
11
|
+
import type {
|
|
12
|
+
PackDeclaration,
|
|
13
|
+
PragmaConfig,
|
|
14
|
+
} from "../../kernel/config/types.js";
|
|
10
15
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
11
16
|
import type { ConfigShowData } from "./types.js";
|
|
12
17
|
|
|
18
|
+
/** A pack declaration with any declared story bodies dropped. */
|
|
19
|
+
function nameAndSourceOnly(pack: PackDeclaration): PackDeclaration {
|
|
20
|
+
if (typeof pack === "string") return pack;
|
|
21
|
+
return {
|
|
22
|
+
name: pack.name,
|
|
23
|
+
...(pack.source === undefined ? {} : { source: pack.source }),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The effective config with declared story BODIES dropped — `packs` entries keep
|
|
29
|
+
* `{ name, source }`, and the top-level `stories` array is omitted.
|
|
30
|
+
*
|
|
31
|
+
* A PROJECTION of the payload, not a hiding of config: `origins` still reports
|
|
32
|
+
* where `packs` and `stories` came from, the plain and llm renders already print
|
|
33
|
+
* pack NAMES only, and `pragma capabilities` lists the verbs the stories
|
|
34
|
+
* produce. It exists because the bodies are SPARQL — the distribution's own five
|
|
35
|
+
* stories take `config show --format json` from 1.3 KB to 11 KB, and MCP returns
|
|
36
|
+
* the JSON formatter's output, so every `config_show` tool call would carry
|
|
37
|
+
* ~2.7k tokens of query text: the largest payload in the surface, for its least
|
|
38
|
+
* useful content.
|
|
39
|
+
*/
|
|
40
|
+
function withoutStoryBodies(config: PragmaConfig): PragmaConfig {
|
|
41
|
+
const { stories, ...rest } = config;
|
|
42
|
+
return {
|
|
43
|
+
...rest,
|
|
44
|
+
...(config.packs === undefined
|
|
45
|
+
? {}
|
|
46
|
+
: { packs: config.packs.map(nameAndSourceOnly) }),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
13
50
|
/**
|
|
14
51
|
* Assemble the resolved config with provenance for the current runtime.
|
|
15
52
|
*
|
|
@@ -22,7 +59,7 @@ export async function collectConfigShow(
|
|
|
22
59
|
): Promise<ConfigShowData> {
|
|
23
60
|
const layers = await readConfig(runtime.cwd);
|
|
24
61
|
return {
|
|
25
|
-
config: layers.config,
|
|
62
|
+
config: withoutStoryBodies(layers.config),
|
|
26
63
|
origins: layers.origins,
|
|
27
64
|
...(layers.project.path ? { projectConfigPath: layers.project.path } : {}),
|
|
28
65
|
globalConfigPath: layers.global.path,
|
|
@@ -21,14 +21,8 @@ export interface ConfigFieldSpec {
|
|
|
21
21
|
readonly kind: "string" | "enum";
|
|
22
22
|
/** The allowed values for an enum field. */
|
|
23
23
|
readonly values?: readonly string[];
|
|
24
|
-
/** One-line field summary. */
|
|
25
|
-
readonly summary: string;
|
|
26
|
-
/** Extended help doc. */
|
|
27
|
-
readonly doc: string;
|
|
28
24
|
/** Reserved values that REMOVE the field instead of setting it. */
|
|
29
25
|
readonly resetSentinel?: readonly string[];
|
|
30
|
-
/** Field help examples. */
|
|
31
|
-
readonly examples: readonly { cmd: string; note?: string }[];
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
/**
|
|
@@ -44,38 +38,17 @@ export const CONFIG_FIELDS: readonly ConfigFieldSpec[] = [
|
|
|
44
38
|
positional: "path",
|
|
45
39
|
kind: "string",
|
|
46
40
|
resetSentinel: ["none", "default", "-"],
|
|
47
|
-
summary: "Set the active design-system tier.",
|
|
48
|
-
doc: "Writes the `tier` field to the global config. Pass `none`, `default`, or `-` to clear it. Written to the global layer only — project configs are authored by hand.",
|
|
49
|
-
examples: [
|
|
50
|
-
{
|
|
51
|
-
cmd: "pragma config set tier apps/lxd",
|
|
52
|
-
note: "scope reads to a tier",
|
|
53
|
-
},
|
|
54
|
-
{ cmd: "pragma config set tier none", note: "clear the tier" },
|
|
55
|
-
],
|
|
56
41
|
},
|
|
57
42
|
{
|
|
58
43
|
field: "channel",
|
|
59
44
|
positional: "name",
|
|
60
45
|
kind: "enum",
|
|
61
46
|
values: CHANNELS,
|
|
62
|
-
summary: "Set the release channel controlling component visibility.",
|
|
63
|
-
doc: "Writes the `channel` field to the global config. Reset by setting the default, `normal`.",
|
|
64
|
-
examples: [
|
|
65
|
-
{ cmd: "pragma config set channel experimental" },
|
|
66
|
-
{ cmd: "pragma config set channel normal", note: "back to the default" },
|
|
67
|
-
],
|
|
68
47
|
},
|
|
69
48
|
{
|
|
70
49
|
field: "detail",
|
|
71
50
|
positional: "level",
|
|
72
51
|
kind: "enum",
|
|
73
52
|
values: DETAIL_LEVELS,
|
|
74
|
-
summary: "Set the default progressive-disclosure level.",
|
|
75
|
-
doc: "Writes the `detail` field to the global config. Reset by setting the default, `standard`.",
|
|
76
|
-
examples: [
|
|
77
|
-
{ cmd: "pragma config set detail detailed" },
|
|
78
|
-
{ cmd: "pragma config set detail standard", note: "back to the default" },
|
|
79
|
-
],
|
|
80
53
|
},
|
|
81
54
|
];
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import type { Task } from "@canonical/task";
|
|
17
|
+
import { BIN_NAME } from "../../constants.js";
|
|
17
18
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
18
19
|
import type { VerbSpec } from "../../kernel/spec/types.js";
|
|
19
20
|
import { configFieldFormatters } from "./field.render.js";
|
|
@@ -46,9 +47,12 @@ const setVerb: VerbSpec<Record<string, unknown>, ConfigFieldResult> = {
|
|
|
46
47
|
],
|
|
47
48
|
output: { formatters: configFieldFormatters },
|
|
48
49
|
examples: [
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
{
|
|
51
|
+
cmd: `${BIN_NAME} config set tier apps/lxd`,
|
|
52
|
+
note: "scope reads to a tier",
|
|
53
|
+
},
|
|
54
|
+
{ cmd: `${BIN_NAME} config set channel experimental` },
|
|
55
|
+
{ cmd: `${BIN_NAME} config set tier none`, note: "clear the tier" },
|
|
52
56
|
],
|
|
53
57
|
capability: {
|
|
54
58
|
needsStore: false,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import { type RenderStyle, styleFor } from "../../kernel/render/style.js";
|
|
3
|
-
import {
|
|
3
|
+
import { emitReference } from "../../kernel/spec/emitReference.js";
|
|
4
|
+
import { capabilities } from "../index.js";
|
|
5
|
+
import { configShowFormatters, renderConfigShowPlain } from "./show.render.js";
|
|
4
6
|
import type { ConfigShowData } from "./types.js";
|
|
5
7
|
|
|
6
8
|
const DATA: ConfigShowData = {
|
|
@@ -8,16 +10,15 @@ const DATA: ConfigShowData = {
|
|
|
8
10
|
tier: "apps/lxd",
|
|
9
11
|
channel: "normal",
|
|
10
12
|
detail: "standard",
|
|
11
|
-
|
|
13
|
+
packs: ["@canonical/ds"],
|
|
12
14
|
},
|
|
13
15
|
origins: {
|
|
14
16
|
tier: "project",
|
|
15
17
|
channel: "default",
|
|
16
18
|
detail: "default",
|
|
17
|
-
|
|
19
|
+
packs: "global",
|
|
18
20
|
stories: "default",
|
|
19
21
|
prefixes: "default",
|
|
20
|
-
prompts: "default",
|
|
21
22
|
},
|
|
22
23
|
globalConfigPath: "/home/u/.config/pragma/config.json",
|
|
23
24
|
projectConfigPath: "/repo/pragma.config.ts",
|
|
@@ -42,7 +43,7 @@ describe("renderConfigShowPlain", () => {
|
|
|
42
43
|
"tier: apps/lxd [project]",
|
|
43
44
|
"channel: normal",
|
|
44
45
|
"detail: standard",
|
|
45
|
-
"
|
|
46
|
+
"packs: @canonical/ds [global]",
|
|
46
47
|
"global config: /home/u/.config/pragma/config.json",
|
|
47
48
|
"project config: /repo/pragma.config.ts",
|
|
48
49
|
].join("\n"),
|
|
@@ -62,4 +63,75 @@ describe("renderConfigShowPlain", () => {
|
|
|
62
63
|
);
|
|
63
64
|
expect(out).not.toContain("<d> [default]</d>");
|
|
64
65
|
});
|
|
66
|
+
|
|
67
|
+
it("renders absent optional fields as (none)", () => {
|
|
68
|
+
const bare: ConfigShowData = {
|
|
69
|
+
config: { channel: "normal" },
|
|
70
|
+
origins: {
|
|
71
|
+
tier: "default",
|
|
72
|
+
channel: "default",
|
|
73
|
+
detail: "default",
|
|
74
|
+
packs: "default",
|
|
75
|
+
stories: "default",
|
|
76
|
+
prefixes: "default",
|
|
77
|
+
},
|
|
78
|
+
globalConfigPath: "/home/u/.config/pragma/config.json",
|
|
79
|
+
projectExists: false,
|
|
80
|
+
globalExists: false,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const out = renderConfigShowPlain(bare, styleFor(false));
|
|
84
|
+
|
|
85
|
+
expect(out).toContain("tier: (none)");
|
|
86
|
+
expect(out).toContain("packs: (none)");
|
|
87
|
+
expect(out).toContain("project config: (not found)");
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("configShowFormatters.llm", () => {
|
|
92
|
+
it("renders the layered rows with origin markers", () => {
|
|
93
|
+
const out = configShowFormatters.llm(DATA);
|
|
94
|
+
|
|
95
|
+
expect(out).toContain("- **Tier:** apps/lxd [project]");
|
|
96
|
+
expect(out).toContain("- **Packs:** @canonical/ds [global]");
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("reports no identity row, in either form", () => {
|
|
100
|
+
// Identity is read statically from `pragma.conf.ts`; reporting a layer for
|
|
101
|
+
// it was reporting a provenance the kernel does not honour. Both renderers
|
|
102
|
+
// are asserted, because they list their rows independently.
|
|
103
|
+
for (const out of [
|
|
104
|
+
renderConfigShowPlain(DATA, styleFor(false)),
|
|
105
|
+
configShowFormatters.llm(DATA),
|
|
106
|
+
]) {
|
|
107
|
+
for (const field of ["name", "help", "colophon", "issues"]) {
|
|
108
|
+
expect(out.toLowerCase()).not.toContain(`${field}:`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("the generated configuration reference", () => {
|
|
115
|
+
it("names exactly the fields this renderer reports with a layer", () => {
|
|
116
|
+
// The page and the renderer are written independently — the page is kernel
|
|
117
|
+
// prose, the renderer a capability — and the page's account of the renderer
|
|
118
|
+
// was wrong in both directions: it claimed every field but `completion`
|
|
119
|
+
// carried a printed provenance, while `prefixes`, `stories` and the four
|
|
120
|
+
// distribution-only fields do not, and it claimed `completion` was not
|
|
121
|
+
// printed, while `--format json` carries it.
|
|
122
|
+
//
|
|
123
|
+
// DERIVED from the real formatter: the field rows are the ones before the
|
|
124
|
+
// two PATH rows, which are not fields at all. Adding a row here without
|
|
125
|
+
// saying so on the page, or naming a field there this renderer drops, fails.
|
|
126
|
+
const printed = renderConfigShowPlain(DATA, styleFor(false))
|
|
127
|
+
.split("\n")
|
|
128
|
+
.map((line) => line.slice(0, line.indexOf(":")));
|
|
129
|
+
const fields = printed.slice(0, printed.indexOf("global config"));
|
|
130
|
+
expect(fields.length).toBeGreaterThan(0);
|
|
131
|
+
|
|
132
|
+
const page = emitReference(capabilities).get("config.md") ?? "";
|
|
133
|
+
expect(page).toContain(
|
|
134
|
+
`${fields.map((field) => `\`${field}\``).join(", ")} — those and only those —`,
|
|
135
|
+
);
|
|
136
|
+
});
|
|
65
137
|
});
|
|
@@ -16,10 +16,9 @@ function originMarker(origin: ConfigOrigin): string {
|
|
|
16
16
|
return origin === "default" ? "" : ` [${origin}]`;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/** Summarize
|
|
20
|
-
function
|
|
21
|
-
const
|
|
22
|
-
const names = packages.map((entry) =>
|
|
19
|
+
/** Summarize a list of named entries as a comma-separated set of names. */
|
|
20
|
+
function entryNames(entries: readonly (string | { name: string })[]): string {
|
|
21
|
+
const names = entries.map((entry) =>
|
|
23
22
|
typeof entry === "string" ? entry : entry.name,
|
|
24
23
|
);
|
|
25
24
|
return names.length > 0 ? names.join(", ") : "(none)";
|
|
@@ -32,14 +31,10 @@ type ConfigRow = readonly [label: string, value: string, marker: string];
|
|
|
32
31
|
function configRows(data: ConfigShowData): readonly ConfigRow[] {
|
|
33
32
|
const { config, origins } = data;
|
|
34
33
|
return [
|
|
35
|
-
[
|
|
36
|
-
"tier",
|
|
37
|
-
config.tier ?? "(none — all tiers visible)",
|
|
38
|
-
originMarker(origins.tier),
|
|
39
|
-
],
|
|
34
|
+
["tier", config.tier ?? "(none)", originMarker(origins.tier)],
|
|
40
35
|
["channel", config.channel, originMarker(origins.channel)],
|
|
41
36
|
["detail", config.detail ?? "standard", originMarker(origins.detail)],
|
|
42
|
-
["
|
|
37
|
+
["packs", entryNames(config.packs ?? []), originMarker(origins.packs)],
|
|
43
38
|
[
|
|
44
39
|
"global config",
|
|
45
40
|
`${data.globalConfigPath}${data.globalExists ? "" : " (not found)"}`,
|
|
@@ -89,10 +84,10 @@ export const configShowFormatters: Formatters<ConfigShowData> = {
|
|
|
89
84
|
const lines = [
|
|
90
85
|
"## Configuration",
|
|
91
86
|
"",
|
|
92
|
-
`- **Tier:** ${config.tier ?? "none
|
|
87
|
+
`- **Tier:** ${config.tier ?? "none"}${originMarker(origins.tier)}`,
|
|
93
88
|
`- **Channel:** ${config.channel}${originMarker(origins.channel)}`,
|
|
94
89
|
`- **Detail:** ${config.detail ?? "standard"}${originMarker(origins.detail)}`,
|
|
95
|
-
`- **
|
|
90
|
+
`- **Packs:** ${entryNames(config.packs ?? [])}${originMarker(origins.packs)}`,
|
|
96
91
|
`- **Global config:** \`${data.globalConfigPath}\``,
|
|
97
92
|
];
|
|
98
93
|
if (data.projectConfigPath) {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* later PR — this ships only the reader.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { BIN_NAME, PROJECT_CONFIG_FILENAME } from "../../constants.js";
|
|
8
9
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
9
10
|
import type { CapabilityModule, VerbSpec } from "../../kernel/spec/types.js";
|
|
10
11
|
import { configSetVerb } from "./set.verb.js";
|
|
@@ -14,12 +15,12 @@ import type { ConfigShowData } from "./types.js";
|
|
|
14
15
|
const showVerb: VerbSpec<Record<string, unknown>, ConfigShowData> = {
|
|
15
16
|
path: ["config", "show"],
|
|
16
17
|
summary: "Show the resolved config and per-field provenance.",
|
|
17
|
-
doc:
|
|
18
|
+
doc: `Merges built-in defaults, the global XDG config, and the nearest ${PROJECT_CONFIG_FILENAME}, marking which layer supplied each value.`,
|
|
18
19
|
params: [],
|
|
19
20
|
output: { formatters: configShowFormatters },
|
|
20
21
|
examples: [
|
|
21
|
-
{ cmd:
|
|
22
|
-
{ cmd:
|
|
22
|
+
{ cmd: `${BIN_NAME} config show` },
|
|
23
|
+
{ cmd: `${BIN_NAME} config show --format json` },
|
|
23
24
|
],
|
|
24
25
|
capability: {
|
|
25
26
|
needsStore: false,
|
|
@@ -6,6 +6,14 @@ import type { ConfigOrigins, PragmaConfig } from "../../kernel/config/types.js";
|
|
|
6
6
|
|
|
7
7
|
/** The resolved configuration plus per-field provenance and layer locations. */
|
|
8
8
|
export interface ConfigShowData {
|
|
9
|
+
/**
|
|
10
|
+
* The effective config, MINUS declared story bodies: `packs` entries carry
|
|
11
|
+
* `{ name, source }` only and the top-level `stories` array is omitted. The
|
|
12
|
+
* bodies are SPARQL, and MCP returns the JSON formatter's output verbatim, so
|
|
13
|
+
* carrying them would put ~2.7k tokens of query text in every `config_show`
|
|
14
|
+
* call. `origins` still reports where `packs`/`stories` came from, and
|
|
15
|
+
* `pragma capabilities` lists the verbs those stories produce.
|
|
16
|
+
*/
|
|
9
17
|
readonly config: PragmaConfig;
|
|
10
18
|
readonly origins: ConfigOrigins;
|
|
11
19
|
readonly projectConfigPath?: string;
|