@canonical/pragma-cli 0.27.0 → 0.29.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.
Files changed (169) hide show
  1. package/dist/pragma +0 -0
  2. package/package.json +19 -17
  3. package/src/config/readConfig.ts +38 -2
  4. package/src/config/types.ts +12 -1
  5. package/src/config/writeConfig.ts +12 -0
  6. package/src/constants.ts +12 -1
  7. package/src/domains/block/commands/index.ts +2 -1
  8. package/src/domains/block/commands/sample.ts +55 -0
  9. package/src/domains/block/formatters/index.ts +2 -1
  10. package/src/domains/block/formatters/sample.ts +21 -0
  11. package/src/domains/block/index.ts +3 -3
  12. package/src/domains/block/mcp/specs.ts +48 -0
  13. package/src/domains/block/operations/index.ts +2 -1
  14. package/src/domains/block/operations/lookup.ts +9 -0
  15. package/src/domains/block/operations/sample.ts +41 -0
  16. package/src/domains/block/orchestration/blockEmptyError.test.ts +26 -0
  17. package/src/domains/block/orchestration/resolveBlockLookup.ts +10 -3
  18. package/src/domains/config/commands/framework.test.ts +88 -0
  19. package/src/domains/config/commands/framework.ts +85 -0
  20. package/src/domains/config/commands/index.ts +2 -0
  21. package/src/domains/config/commands/trace.test.ts +148 -0
  22. package/src/domains/config/commands/trace.ts +80 -0
  23. package/src/domains/config/formatters/framework.ts +34 -0
  24. package/src/domains/config/formatters/index.ts +2 -0
  25. package/src/domains/config/formatters/trace.ts +28 -0
  26. package/src/domains/config/index.ts +15 -2
  27. package/src/domains/config/operations/index.ts +1 -0
  28. package/src/domains/config/operations/validateFramework.ts +24 -0
  29. package/src/domains/config/tasks/index.ts +2 -0
  30. package/src/domains/config/tasks/setChannel.ts +7 -1
  31. package/src/domains/config/tasks/setFramework.ts +40 -0
  32. package/src/domains/config/tasks/setTier.ts +7 -1
  33. package/src/domains/config/tasks/setTrace.ts +38 -0
  34. package/src/domains/doctor/operations/checks/checkKeStore.ts +5 -5
  35. package/src/domains/doctor/operations/checks/checkPackageRefs.ts +35 -41
  36. package/src/domains/doctor/operations/checks.test.ts +4 -1
  37. package/src/domains/doctor/operations/runChecks.test.ts +72 -0
  38. package/src/domains/doctor/operations/runChecks.ts +48 -12
  39. package/src/domains/graphql/commands/build.test.ts +194 -0
  40. package/src/domains/graphql/commands/build.ts +125 -0
  41. package/src/domains/graphql/commands/check.test.ts +139 -0
  42. package/src/domains/graphql/commands/check.ts +87 -0
  43. package/src/domains/graphql/commands/index.ts +4 -0
  44. package/src/domains/graphql/formatters/index.ts +3 -0
  45. package/src/domains/graphql/formatters/report.ts +78 -0
  46. package/src/domains/graphql/helpers/index.ts +4 -0
  47. package/src/domains/graphql/helpers/parsePrefixes.test.ts +44 -0
  48. package/src/domains/graphql/helpers/parsePrefixes.ts +38 -0
  49. package/src/domains/graphql/helpers/resolveSourceFiles.test.ts +56 -0
  50. package/src/domains/graphql/helpers/resolveSourceFiles.ts +45 -0
  51. package/src/domains/graphql/index.ts +21 -0
  52. package/src/domains/graphql/operations/compileSchema.test.ts +119 -0
  53. package/src/domains/graphql/operations/compileSchema.ts +109 -0
  54. package/src/domains/graphql/operations/index.ts +7 -0
  55. package/src/domains/graphql/types.ts +29 -0
  56. package/src/domains/info/operations/collectInfo.test.ts +2 -2
  57. package/src/domains/info/operations/collectInfo.ts +4 -4
  58. package/src/domains/llm/capabilities.test.ts +91 -0
  59. package/src/domains/llm/commands/capabilities.ts +28 -0
  60. package/src/domains/llm/commands/index.ts +1 -0
  61. package/src/domains/llm/data/commandReference.ts +90 -18
  62. package/src/domains/llm/data/decisionTrees.ts +15 -13
  63. package/src/domains/llm/data/index.ts +2 -0
  64. package/src/domains/llm/data/toolCatalog.ts +184 -0
  65. package/src/domains/llm/formatters/capabilities.ts +50 -0
  66. package/src/domains/llm/formatters/index.ts +1 -0
  67. package/src/domains/llm/index.ts +3 -2
  68. package/src/domains/llm/mcp/index.ts +1 -1
  69. package/src/domains/llm/mcp/specs.ts +59 -52
  70. package/src/domains/llm/types.ts +40 -0
  71. package/src/domains/modifier/commands/index.ts +2 -1
  72. package/src/domains/modifier/commands/sample.ts +53 -0
  73. package/src/domains/modifier/formatters/index.ts +2 -1
  74. package/src/domains/modifier/formatters/sample.ts +15 -0
  75. package/src/domains/modifier/index.ts +7 -3
  76. package/src/domains/modifier/mcp/specs.ts +47 -0
  77. package/src/domains/modifier/operations/index.ts +2 -1
  78. package/src/domains/modifier/operations/lookup.ts +9 -0
  79. package/src/domains/modifier/operations/sample.ts +32 -0
  80. package/src/domains/modifier/orchestration/modifierEmptyError.test.ts +26 -0
  81. package/src/domains/modifier/orchestration/modifierEmptyError.ts +7 -2
  82. package/src/domains/modifier/orchestration/resolveModifierLookup.ts +14 -2
  83. package/src/domains/refs/operations/index.ts +1 -1
  84. package/src/domains/refs/operations/paths.ts +29 -1
  85. package/src/domains/refs/operations/updateRefs.test.ts +6 -3
  86. package/src/domains/refs/operations/updateRefs.ts +3 -2
  87. package/src/domains/shared/bootStore.ts +88 -49
  88. package/src/domains/shared/contracts.ts +1 -0
  89. package/src/domains/shared/emptyErrorRecovery.test.ts +109 -0
  90. package/src/domains/shared/loaders/bundledLoader.ts +108 -0
  91. package/src/domains/shared/loaders/gitLoader.ts +31 -0
  92. package/src/domains/shared/loaders/index.ts +6 -0
  93. package/src/domains/shared/loaders/localLoader.ts +73 -0
  94. package/src/domains/shared/loaders/readPackageDir.ts +112 -0
  95. package/src/domains/shared/lookupMany.ts +9 -1
  96. package/src/domains/shared/packages.ts +21 -120
  97. package/src/domains/shared/pickRandom.ts +22 -0
  98. package/src/domains/shared/runtime.ts +6 -3
  99. package/src/domains/shared/sampleFormatters.ts +47 -0
  100. package/src/domains/shared/semanticPackage.ts +96 -0
  101. package/src/domains/shared/suggestions/detectCrossDomain.test.ts +43 -0
  102. package/src/domains/shared/suggestions/detectCrossDomain.ts +116 -0
  103. package/src/domains/shared/suggestions/expandGlob.test.ts +92 -0
  104. package/src/domains/shared/suggestions/expandGlob.ts +51 -0
  105. package/src/domains/shared/suggestions/expandLookupQueries.ts +57 -0
  106. package/src/domains/shared/suggestions/index.ts +7 -0
  107. package/src/domains/shared/suggestions/listDomainNames.ts +61 -0
  108. package/src/domains/shared/suggestions/suggestNames.test.ts +70 -0
  109. package/src/domains/shared/suggestions/suggestNames.ts +97 -0
  110. package/src/domains/shared/types/index.ts +1 -0
  111. package/src/domains/shared/types/runtime.ts +4 -1
  112. package/src/domains/shared/types/sample.ts +17 -0
  113. package/src/domains/skill/helpers/resolveSkillSources.ts +49 -16
  114. package/src/domains/standard/commands/index.ts +2 -1
  115. package/src/domains/standard/commands/sample.ts +57 -0
  116. package/src/domains/standard/formatters/index.ts +2 -1
  117. package/src/domains/standard/formatters/sample.ts +15 -0
  118. package/src/domains/standard/index.ts +8 -1
  119. package/src/domains/standard/mcp/specs.ts +48 -1
  120. package/src/domains/standard/operations/index.ts +2 -1
  121. package/src/domains/standard/operations/lookup.ts +9 -0
  122. package/src/domains/standard/operations/sample.ts +35 -0
  123. package/src/domains/standard/orchestration/resolveStandardLookup.ts +14 -2
  124. package/src/domains/standard/orchestration/standardEmptyError.test.ts +33 -0
  125. package/src/domains/standard/orchestration/standardEmptyError.ts +16 -6
  126. package/src/domains/token/commands/index.ts +2 -1
  127. package/src/domains/token/commands/sample.ts +53 -0
  128. package/src/domains/token/formatters/index.ts +2 -1
  129. package/src/domains/token/formatters/sample.ts +16 -0
  130. package/src/domains/token/index.ts +8 -1
  131. package/src/domains/token/mcp/specs.ts +47 -1
  132. package/src/domains/token/operations/index.ts +2 -1
  133. package/src/domains/token/operations/lookup.ts +9 -0
  134. package/src/domains/token/operations/sample.ts +32 -0
  135. package/src/domains/token/orchestration/resolveTokenLookup.ts +14 -2
  136. package/src/domains/token/orchestration/tokenEmptyError.test.ts +33 -0
  137. package/src/domains/token/orchestration/tokenEmptyError.ts +5 -2
  138. package/src/domains/trace/commands/clear.ts +71 -0
  139. package/src/domains/trace/commands/index.ts +5 -0
  140. package/src/domains/trace/commands/sessions.ts +32 -0
  141. package/src/domains/trace/commands/show.ts +145 -0
  142. package/src/domains/trace/formatters/index.ts +9 -0
  143. package/src/domains/trace/formatters/sessions.ts +80 -0
  144. package/src/domains/trace/formatters/show.ts +122 -0
  145. package/src/domains/trace/index.ts +17 -0
  146. package/src/domains/trace/operations/index.ts +8 -0
  147. package/src/domains/trace/operations/listSessions.test.ts +55 -0
  148. package/src/domains/trace/operations/listSessions.ts +52 -0
  149. package/src/domains/trace/operations/readTraceLog.test.ts +100 -0
  150. package/src/domains/trace/operations/readTraceLog.ts +104 -0
  151. package/src/domains/trace/tracePlugin.test.ts +171 -0
  152. package/src/domains/trace/tracePlugin.ts +159 -0
  153. package/src/domains/trace/types.ts +65 -0
  154. package/src/error/PragmaError.ts +15 -2
  155. package/src/error/types.ts +15 -1
  156. package/src/mcp/error/serializeErrorPayload.ts +7 -0
  157. package/src/mcp/error/types.ts +8 -0
  158. package/src/mcp/registerResources.test.ts +38 -16
  159. package/src/mcp/registerResources.ts +57 -8
  160. package/src/mcp/tools/registerTools.test.ts +22 -7
  161. package/src/mcp/utils/wrapTool.test.ts +1 -0
  162. package/src/pipeline/collectCommands.ts +7 -1
  163. package/src/pipeline/renderError.ts +15 -0
  164. package/src/pipeline/resolveCommandKind.ts +8 -1
  165. package/src/pipeline/runCli.ts +12 -1
  166. package/src/testing/createTestMcpClient.ts +1 -0
  167. package/src/testing/graphqlFixtures.ts +72 -0
  168. package/src/testing/index.ts +7 -0
  169. package/src/testing/integration/mcp-surface.test.ts +11 -5
@@ -0,0 +1,109 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { createStore } from "@canonical/ke";
3
+ import {
4
+ CompilationError,
5
+ type CompilerResult,
6
+ compile,
7
+ createStoreQueryFn,
8
+ type Diagnostic,
9
+ hashSources,
10
+ } from "@canonical/ke-graphql";
11
+ import { PragmaError } from "#error";
12
+ import { resolveSourceFiles } from "../helpers/index.js";
13
+
14
+ export interface CompileSchemaOptions {
15
+ /** TTL file paths or glob patterns, resolved from `cwd`. */
16
+ readonly sources: readonly string[];
17
+ /** Prefix map handed to both the ke store and the compiler. */
18
+ readonly prefixes: Readonly<Record<string, string>>;
19
+ /** Working directory for resolving relative source paths. */
20
+ readonly cwd: string;
21
+ }
22
+
23
+ export interface CompileSchemaResult {
24
+ /** `"ok"` when a schema was produced, `"failed"` when composition aborted. */
25
+ readonly status: "ok" | "failed";
26
+ /** All compiler diagnostics, including those carried by a CompilationError. */
27
+ readonly diagnostics: readonly Diagnostic[];
28
+ /** Resolved absolute TTL file paths that were loaded. */
29
+ readonly files: readonly string[];
30
+ /** Fingerprint of the raw source contents (matches ke's onLoad hashing). */
31
+ readonly sourcesHash: string;
32
+ /** Full compiler output; absent when compilation failed. */
33
+ readonly compiled?: CompilerResult;
34
+ }
35
+
36
+ /**
37
+ * Compile TTL sources into a GraphQL schema via the ke-graphql pipeline.
38
+ *
39
+ * Resolves source patterns, hashes the raw file contents (the exact bytes
40
+ * ke loads, so the artifact's `sourcesHash` matches what
41
+ * `createSchemaPlugin` computes from ke's onLoad), boots a throwaway ke
42
+ * store, and runs the compiler. A {@link CompilationError} (schema
43
+ * composition failed) is converted into a `"failed"` result carrying its
44
+ * diagnostics; the store is always disposed.
45
+ *
46
+ * @note Impure — reads filesystem and boots a ke store (WASM + TTL).
47
+ *
48
+ * @param options - Sources, prefixes, and working directory.
49
+ * @returns The compile outcome with diagnostics, files, and sources hash.
50
+ * @throws PragmaError with code `INVALID_INPUT` when no sources resolve.
51
+ * @throws PragmaError with code `STORE_ERROR` when the store fails to load.
52
+ */
53
+ export default async function compileSchema(
54
+ options: CompileSchemaOptions,
55
+ ): Promise<CompileSchemaResult> {
56
+ const files = resolveSourceFiles(options.sources, options.cwd);
57
+
58
+ if (files.length === 0) {
59
+ throw PragmaError.invalidInput("sources", options.sources.join(", "), {
60
+ recovery: {
61
+ message: "Provide at least one existing TTL file or glob pattern.",
62
+ },
63
+ });
64
+ }
65
+
66
+ const contents = files.map((file) => readFileSync(file, "utf-8"));
67
+ const sourcesHash = hashSources(contents);
68
+
69
+ let store: Awaited<ReturnType<typeof createStore>>;
70
+ try {
71
+ store = await createStore({
72
+ sources: [...files],
73
+ prefixes: options.prefixes,
74
+ cwd: options.cwd,
75
+ });
76
+ } catch (error) {
77
+ throw PragmaError.storeError(
78
+ error instanceof Error ? error.message : String(error),
79
+ {
80
+ recovery: {
81
+ message: "Check the TTL syntax of the provided sources.",
82
+ },
83
+ },
84
+ );
85
+ }
86
+
87
+ try {
88
+ const compiled = await compile(createStoreQueryFn(store), options.prefixes);
89
+ return {
90
+ status: "ok",
91
+ diagnostics: compiled.diagnostics,
92
+ files,
93
+ sourcesHash,
94
+ compiled,
95
+ };
96
+ } catch (error) {
97
+ if (error instanceof CompilationError) {
98
+ return {
99
+ status: "failed",
100
+ diagnostics: error.diagnostics,
101
+ files,
102
+ sourcesHash,
103
+ };
104
+ }
105
+ throw error;
106
+ } finally {
107
+ store.dispose();
108
+ }
109
+ }
@@ -0,0 +1,7 @@
1
+ /** @module Barrel for graphql operations. */
2
+
3
+ export type {
4
+ CompileSchemaOptions,
5
+ CompileSchemaResult,
6
+ } from "./compileSchema.js";
7
+ export { default as compileSchema } from "./compileSchema.js";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Type definitions for the graphql domain.
3
+ *
4
+ * The compile report is the shared output shape for `graphql build` and
5
+ * `graphql check`: the full diagnostic list plus source and artifact
6
+ * metadata, rendered by the report formatters.
7
+ */
8
+
9
+ import type { Diagnostic } from "@canonical/ke-graphql";
10
+
11
+ /** Artifact paths written by `pragma graphql build`. */
12
+ export interface GraphqlArtifacts {
13
+ /** Absolute path of the written GraphQL SDL file. */
14
+ readonly sdl: string;
15
+ /** Absolute path of the written extraction artifact. */
16
+ readonly extraction: string;
17
+ }
18
+
19
+ /** Output shape rendered by `graphql build` and `graphql check`. */
20
+ export interface GraphqlCompileReport {
21
+ /** All compiler diagnostics (errors, warnings, info). */
22
+ readonly diagnostics: readonly Diagnostic[];
23
+ /** Resolved absolute TTL file paths that were compiled. */
24
+ readonly files: readonly string[];
25
+ /** Combined fingerprint of the raw TTL source contents. */
26
+ readonly sourcesHash: string;
27
+ /** Written artifact paths (present only for a successful `build`). */
28
+ readonly artifacts?: GraphqlArtifacts;
29
+ }
@@ -51,7 +51,7 @@ describe("collectInfo", () => {
51
51
 
52
52
  it("includes update information and store summary when available", async () => {
53
53
  const dispose = vi.fn();
54
- bootStoreMock.mockResolvedValue({ dispose });
54
+ bootStoreMock.mockResolvedValue({ store: { dispose }, packages: [] });
55
55
  checkRegistryVersionMock.mockResolvedValue({
56
56
  latest: "9.9.9",
57
57
  distTag: "latest",
@@ -91,7 +91,7 @@ describe("collectInfo", () => {
91
91
  it("omits the update section when already on the latest version", async () => {
92
92
  const { VERSION } = await import("#constants");
93
93
  const dispose = vi.fn();
94
- bootStoreMock.mockResolvedValue({ dispose });
94
+ bootStoreMock.mockResolvedValue({ store: { dispose }, packages: [] });
95
95
  checkRegistryVersionMock.mockResolvedValue({
96
96
  latest: VERSION,
97
97
  distTag: "latest",
@@ -48,14 +48,14 @@ export default async function collectInfo(cwd: string): Promise<InfoData> {
48
48
  }
49
49
 
50
50
  let store: InfoData["store"];
51
- let keStore: Awaited<ReturnType<typeof bootStore>> | undefined;
51
+ let bootResult: Awaited<ReturnType<typeof bootStore>> | undefined;
52
52
  try {
53
- keStore = await bootStore({ cwd });
54
- store = await collectStoreSummary(keStore);
53
+ bootResult = await bootStore({ cwd });
54
+ store = await collectStoreSummary(bootResult.store);
55
55
  } catch {
56
56
  // Store unavailable — show info without store section
57
57
  } finally {
58
- keStore?.dispose();
58
+ bootResult?.store.dispose();
59
59
  }
60
60
 
61
61
  // Collect package ref summaries
@@ -0,0 +1,91 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { VERSION } from "#constants";
3
+ import { buildCapabilitiesCommand } from "./commands/index.js";
4
+ import { TOOL_CATALOG } from "./data/index.js";
5
+ import { buildCapabilitiesData } from "./mcp/index.js";
6
+
7
+ describe("buildCapabilitiesData", () => {
8
+ it("returns correct version", () => {
9
+ const data = buildCapabilitiesData();
10
+ expect(data.version).toBe(VERSION);
11
+ });
12
+
13
+ it("includes conventions with three fields", () => {
14
+ const data = buildCapabilitiesData();
15
+ expect(data.conventions.system).toBeTruthy();
16
+ expect(data.conventions.model).toBeTruthy();
17
+ expect(data.conventions.querying).toBeTruthy();
18
+ });
19
+
20
+ it("includes a 3-stage discovery sequence", () => {
21
+ const data = buildCapabilitiesData();
22
+ expect(data.discovery_sequence).toHaveLength(3);
23
+ expect(data.discovery_sequence[0]?.stage).toBe(1);
24
+ expect(data.discovery_sequence[0]?.tool).toBe("capabilities");
25
+ expect(data.discovery_sequence[1]?.tool).toBe("*_sample");
26
+ expect(data.discovery_sequence[2]?.tool).toBe("domain tools");
27
+ });
28
+
29
+ it("includes all 29 tools from TOOL_CATALOG", () => {
30
+ const data = buildCapabilitiesData();
31
+ expect(data.tools).toHaveLength(TOOL_CATALOG.length);
32
+ expect(data.tools).toHaveLength(29);
33
+ });
34
+
35
+ it("every tool has a non-empty use_when", () => {
36
+ const data = buildCapabilitiesData();
37
+ for (const tool of data.tools) {
38
+ expect(tool.use_when.length).toBeGreaterThan(0);
39
+ }
40
+ });
41
+
42
+ it("counts match tool catalog category lengths", () => {
43
+ const data = buildCapabilitiesData();
44
+ expect(data.counts.total).toBe(29);
45
+ expect(data.counts.read).toBe(
46
+ TOOL_CATALOG.filter((t) => t.category === "read").length,
47
+ );
48
+ expect(data.counts.write).toBe(
49
+ TOOL_CATALOG.filter((t) => t.category === "write").length,
50
+ );
51
+ expect(data.counts.orientation).toBe(
52
+ TOOL_CATALOG.filter((t) => t.category === "orientation").length,
53
+ );
54
+ expect(data.counts.diagnostic).toBe(
55
+ TOOL_CATALOG.filter((t) => t.category === "diagnostic").length,
56
+ );
57
+ });
58
+
59
+ it("includes limits section", () => {
60
+ const data = buildCapabilitiesData();
61
+ expect(data.limits.output_modes).toContain("text");
62
+ expect(data.limits.output_modes).toContain("json");
63
+ expect(data.limits.output_modes).toContain("llm");
64
+ expect(data.limits.condensed_available).toBe(true);
65
+ });
66
+ });
67
+
68
+ describe("buildCapabilitiesCommand", () => {
69
+ it("returns an output result with plain renderer", async () => {
70
+ const cmd = buildCapabilitiesCommand();
71
+ expect(cmd.path).toEqual(["capabilities"]);
72
+
73
+ const result = await cmd.execute({}, {} as never);
74
+ expect(result.tag).toBe("output");
75
+ if (result.tag !== "output") throw new Error("Expected output result");
76
+
77
+ const text = result.render.plain(result.value) as string;
78
+ expect(text).toContain("Conventions");
79
+ expect(text).toContain("Discovery Sequence");
80
+ expect(text).toContain("block_list");
81
+ expect(text).toContain("read");
82
+ expect(text).toContain("29 tools");
83
+ });
84
+
85
+ it("does not require a store or runtime", async () => {
86
+ const cmd = buildCapabilitiesCommand();
87
+ // Execute with no context — should succeed because it's static
88
+ const result = await cmd.execute({}, {} as never);
89
+ expect(result.tag).toBe("output");
90
+ });
91
+ });
@@ -0,0 +1,28 @@
1
+ import {
2
+ type CommandDefinition,
3
+ type CommandResult,
4
+ createOutputResult,
5
+ } from "@canonical/cli-core";
6
+ import renderCapabilities from "../formatters/capabilities.js";
7
+ import { buildCapabilitiesData } from "../mcp/specs.js";
8
+
9
+ /**
10
+ * Builds the `pragma capabilities` command definition.
11
+ *
12
+ * Returns a static system map: conventions, tool catalog with behavioral
13
+ * hints, discovery sequence, and output modes. No store needed.
14
+ *
15
+ * @returns A command definition for `capabilities`.
16
+ */
17
+ export default function buildCapabilitiesCommand(): CommandDefinition {
18
+ return {
19
+ path: ["capabilities"],
20
+ description:
21
+ "Discover conventions, available tools, and discovery sequence",
22
+ parameters: [],
23
+ execute: async (): Promise<CommandResult> => {
24
+ const data = buildCapabilitiesData();
25
+ return createOutputResult(data, { plain: renderCapabilities });
26
+ },
27
+ };
28
+ }
@@ -1,3 +1,4 @@
1
1
  /** @module Barrel for llm command builders. */
2
2
 
3
+ export { default as buildCapabilitiesCommand } from "./capabilities.js";
3
4
  export { default as buildLlmCommand } from "./llm.js";
@@ -1,25 +1,97 @@
1
1
  import type { CommandRefEntry } from "../types.js";
2
+ import { TOOL_CATALOG } from "./toolCatalog.js";
3
+
4
+ /** Look up a use_when string from the tool catalog by MCP tool name. */
5
+ function hintFor(mcpName: string): string {
6
+ return TOOL_CATALOG.find((t) => t.name === mcpName)?.use_when ?? "";
7
+ }
2
8
 
3
9
  /**
4
- * Static command reference table with approximate token-cost estimates.
10
+ * Static command reference table with approximate token-cost estimates
11
+ * and behavioral hints for LLM tool selection.
5
12
  *
6
- * Used by the `pragma llm` orientation output to help LLMs budget context.
13
+ * Used by the `pragma llm` orientation output to help LLMs budget context
14
+ * and choose the right tool.
7
15
  */
8
16
  export const COMMAND_REFERENCE: readonly CommandRefEntry[] = [
9
- { command: "block list", tokens: "~200" },
10
- { command: "block lookup <name-or-iri...> --detailed", tokens: "~500" },
11
- { command: "standard list --category <cat>", tokens: "~100" },
12
- { command: "standard lookup <name-or-iri...> --detailed", tokens: "~400" },
13
- { command: "standard categories", tokens: "~50" },
14
- { command: "modifier list", tokens: "~100" },
15
- { command: "modifier lookup <name-or-iri...>", tokens: "~80" },
16
- { command: "token list", tokens: "~400" },
17
- { command: "token lookup <name-or-iri...> --detailed", tokens: "~150" },
18
- { command: "tier list", tokens: "~50" },
19
- { command: "ontology list", tokens: "~80" },
20
- { command: "ontology show <prefix>", tokens: "~300" },
21
- { command: 'graph query "<sparql>"', tokens: "varies" },
22
- { command: "graph inspect <uri>", tokens: "~200" },
23
- { command: "config show", tokens: "~50" },
24
- { command: "info", tokens: "~100" },
17
+ {
18
+ command: "block sample",
19
+ tokens: "~600",
20
+ use_when: hintFor("block_sample"),
21
+ },
22
+ { command: "block list", tokens: "~200", use_when: hintFor("block_list") },
23
+ {
24
+ command: "block lookup <name-or-iri...> --detailed",
25
+ tokens: "~500",
26
+ use_when: hintFor("block_lookup"),
27
+ },
28
+ {
29
+ command: "standard sample",
30
+ tokens: "~500",
31
+ use_when: hintFor("standard_sample"),
32
+ },
33
+ {
34
+ command: "standard list --category <cat>",
35
+ tokens: "~100",
36
+ use_when: hintFor("standard_list"),
37
+ },
38
+ {
39
+ command: "standard lookup <name-or-iri...> --detailed",
40
+ tokens: "~400",
41
+ use_when: hintFor("standard_lookup"),
42
+ },
43
+ {
44
+ command: "standard categories",
45
+ tokens: "~50",
46
+ use_when: hintFor("standard_categories"),
47
+ },
48
+ {
49
+ command: "modifier sample",
50
+ tokens: "~200",
51
+ use_when: hintFor("modifier_sample"),
52
+ },
53
+ {
54
+ command: "modifier list",
55
+ tokens: "~100",
56
+ use_when: hintFor("modifier_list"),
57
+ },
58
+ {
59
+ command: "modifier lookup <name-or-iri...>",
60
+ tokens: "~80",
61
+ use_when: hintFor("modifier_lookup"),
62
+ },
63
+ {
64
+ command: "token sample",
65
+ tokens: "~300",
66
+ use_when: hintFor("token_sample"),
67
+ },
68
+ { command: "token list", tokens: "~400", use_when: hintFor("token_list") },
69
+ {
70
+ command: "token lookup <name-or-iri...> --detailed",
71
+ tokens: "~150",
72
+ use_when: hintFor("token_lookup"),
73
+ },
74
+ { command: "tier list", tokens: "~50", use_when: hintFor("tier_list") },
75
+ {
76
+ command: "ontology list",
77
+ tokens: "~80",
78
+ use_when: hintFor("ontology_list"),
79
+ },
80
+ {
81
+ command: "ontology show <prefix>",
82
+ tokens: "~300",
83
+ use_when: hintFor("ontology_show"),
84
+ },
85
+ {
86
+ command: 'graph query "<sparql>"',
87
+ tokens: "varies",
88
+ use_when: hintFor("graph_query"),
89
+ },
90
+ {
91
+ command: "graph inspect <uri>",
92
+ tokens: "~200",
93
+ use_when: hintFor("graph_inspect"),
94
+ },
95
+ { command: "config show", tokens: "~50", use_when: hintFor("config_show") },
96
+ { command: "info", tokens: "~100", use_when: hintFor("info") },
25
97
  ];
@@ -9,21 +9,22 @@ import type { DecisionTree } from "../types.js";
9
9
  export const DECISION_TREES: readonly DecisionTree[] = [
10
10
  {
11
11
  intent: "Build a block",
12
- tree: `? Know IRI or name?
13
- yes → block lookup <name-or-iri...> --detailed [~500]
14
- e.g. block lookup ds:global.component.button
15
- no → block list [~200] → pick compact IRI → lookup`,
12
+ tree: `? First time seeing block data?
13
+ yes → block sample [~600] → see actual shapes, then query
14
+ no → ? Know IRI or name?
15
+ yes → block lookup <name-or-iri...> --detailed [~500]
16
+ e.g. block lookup ds:global.component.button
17
+ no → block list [~200] → pick compact IRI → lookup`,
16
18
  },
17
19
  {
18
20
  intent: "Audit standards",
19
- tree: `? Know standard IRI or name?
20
- yes → standard lookup <name-or-iri...> --detailed [~400]
21
- e.g. standard lookup react/component/props
22
- no → ? Know block IRI or name?
23
- yes → block lookup <name-or-iri...> --detailed [~500]
24
- → inspect related guidance manually Σ500
25
- no → standard list --category <cat> [~100]
26
- → standard lookup <std-iri...> --detailed [~400] Σ500`,
21
+ tree: `? First time seeing standard data?
22
+ yes → standard sample [~500] → see actual shapes, then query
23
+ no → ? Know standard IRI or name?
24
+ yes → standard lookup <name-or-iri...> --detailed [~400]
25
+ e.g. standard lookup react/component/props
26
+ no → standard list --category <cat> [~100]
27
+ → standard lookup <std-iri...> --detailed [~400] Σ500`,
27
28
  },
28
29
  {
29
30
  intent: "Find a token",
@@ -34,7 +35,8 @@ export const DECISION_TREES: readonly DecisionTree[] = [
34
35
  },
35
36
  {
36
37
  intent: "Explore the design system",
37
- tree: `high-level → ontology list [~80] → ontology show <ns> [~300]
38
+ tree: `first time → block sample / token sample / modifier sample [~300] → see real shapes
39
+ high-level → ontology list [~80] → ontology show <ns> [~300]
38
40
  modifiers → modifier list [~100] → modifier lookup <name-or-iri...> [~80]
39
41
  tiers → tier list [~50]
40
42
  raw → graph query "SELECT ..." → graph inspect <uri> [~200]`,
@@ -2,3 +2,5 @@
2
2
 
3
3
  export { COMMAND_REFERENCE } from "./commandReference.js";
4
4
  export { DECISION_TREES } from "./decisionTrees.js";
5
+ export type { ToolEntry } from "./toolCatalog.js";
6
+ export { TOOL_CATALOG } from "./toolCatalog.js";
@@ -0,0 +1,184 @@
1
+ /** Tool catalog with behavioral hints for agent orientation. */
2
+
3
+ export interface ToolEntry {
4
+ readonly name: string;
5
+ readonly category: "read" | "write" | "orientation" | "diagnostic";
6
+ readonly use_when: string;
7
+ }
8
+
9
+ /** All registered MCP tools with category and behavioral guidance. */
10
+ export const TOOL_CATALOG: readonly ToolEntry[] = [
11
+ // — Read ————————————————————————————————————————————————————————————————————
12
+ {
13
+ name: "block_list",
14
+ category: "read",
15
+ use_when:
16
+ "Browsing available components, patterns, layouts under current tier/channel",
17
+ },
18
+ {
19
+ name: "block_lookup",
20
+ category: "read",
21
+ use_when:
22
+ "Need full anatomy, modifiers, tokens, and standards for specific blocks by name or IRI",
23
+ },
24
+ {
25
+ name: "standard_list",
26
+ category: "read",
27
+ use_when:
28
+ "Browsing code standards, optionally filtered by category or search term",
29
+ },
30
+ {
31
+ name: "standard_lookup",
32
+ category: "read",
33
+ use_when:
34
+ "Need do/don't code examples for specific coding standards by name or IRI",
35
+ },
36
+ {
37
+ name: "standard_categories",
38
+ category: "read",
39
+ use_when: "Discovering which standard categories exist before filtering",
40
+ },
41
+ {
42
+ name: "modifier_list",
43
+ category: "read",
44
+ use_when: "Listing all modifier families and their allowed values",
45
+ },
46
+ {
47
+ name: "modifier_lookup",
48
+ category: "read",
49
+ use_when:
50
+ "Need values and usage details for specific modifier families by name",
51
+ },
52
+ {
53
+ name: "token_list",
54
+ category: "read",
55
+ use_when:
56
+ "Browsing design tokens, optionally filtered by category (color, spacing, etc.)",
57
+ },
58
+ {
59
+ name: "token_lookup",
60
+ category: "read",
61
+ use_when:
62
+ "Need theme values and resolution details for specific tokens by name or IRI",
63
+ },
64
+ {
65
+ name: "tier_list",
66
+ category: "read",
67
+ use_when: "Understanding the tier hierarchy before setting a tier filter",
68
+ },
69
+ {
70
+ name: "config_show",
71
+ category: "read",
72
+ use_when: "Checking active tier and channel before querying",
73
+ },
74
+ {
75
+ name: "ontology_list",
76
+ category: "read",
77
+ use_when:
78
+ "Discovering loaded namespaces, prefixes, and class/property counts",
79
+ },
80
+ {
81
+ name: "ontology_show",
82
+ category: "read",
83
+ use_when:
84
+ "Exploring the full schema of a namespace — classes, properties, and hierarchy",
85
+ },
86
+ {
87
+ name: "graph_query",
88
+ category: "read",
89
+ use_when:
90
+ "Complex SPARQL joins or aggregations that other tools cannot express",
91
+ },
92
+ {
93
+ name: "graph_inspect",
94
+ category: "read",
95
+ use_when:
96
+ "Examining all triples for a specific URI — predicates, objects, and types",
97
+ },
98
+ {
99
+ name: "skill_list",
100
+ category: "read",
101
+ use_when: "Discovering agent skills provided by installed packages",
102
+ },
103
+ {
104
+ name: "block_sample",
105
+ category: "read",
106
+ use_when:
107
+ "See actual block data shapes before querying — returns random instances each call, prevents guessing at property names",
108
+ },
109
+ {
110
+ name: "standard_sample",
111
+ category: "read",
112
+ use_when:
113
+ "See actual standard data shapes (with dos/donts) before querying — returns random instances each call",
114
+ },
115
+ {
116
+ name: "token_sample",
117
+ category: "read",
118
+ use_when:
119
+ "See actual token data shapes (with theme values) before querying — returns random instances each call",
120
+ },
121
+ {
122
+ name: "modifier_sample",
123
+ category: "read",
124
+ use_when:
125
+ "See actual modifier data shapes (with value lists) before querying — returns random instances each call",
126
+ },
127
+
128
+ // — Write ———————————————————————————————————————————————————————————————————
129
+ {
130
+ name: "config_tier",
131
+ category: "write",
132
+ use_when: "Setting or resetting the active tier filter",
133
+ },
134
+ {
135
+ name: "config_channel",
136
+ category: "write",
137
+ use_when:
138
+ "Setting the release channel (normal, experimental, or prerelease)",
139
+ },
140
+ {
141
+ name: "tokens_add_config",
142
+ category: "write",
143
+ use_when: "Generating a tokens.config.mjs for the terrazzo token pipeline",
144
+ },
145
+ {
146
+ name: "create_component",
147
+ category: "write",
148
+ use_when:
149
+ "Scaffolding a new design system component (React, Svelte, or Lit)",
150
+ },
151
+ {
152
+ name: "create_package",
153
+ category: "write",
154
+ use_when:
155
+ "Scaffolding a new npm package with proper monorepo configuration",
156
+ },
157
+
158
+ // — Orientation —————————————————————————————————————————————————————————————
159
+ {
160
+ name: "llm",
161
+ category: "orientation",
162
+ use_when:
163
+ "Need live context, decision trees, and command reference for design system work",
164
+ },
165
+ {
166
+ name: "capabilities",
167
+ category: "orientation",
168
+ use_when:
169
+ "Starting a session — understand conventions, available tools, and discovery flow",
170
+ },
171
+
172
+ // — Diagnostic ——————————————————————————————————————————————————————————————
173
+ {
174
+ name: "doctor",
175
+ category: "diagnostic",
176
+ use_when:
177
+ "Diagnosing environment issues — config, store, completions, MCP health",
178
+ },
179
+ {
180
+ name: "info",
181
+ category: "diagnostic",
182
+ use_when: "Checking pragma version, configuration summary, and store state",
183
+ },
184
+ ];