@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.
Files changed (250) hide show
  1. package/README.md +7 -7
  2. package/dist/pragma +0 -0
  3. package/package.json +18 -15
  4. package/pragma.conf.ts +664 -0
  5. package/src/bin.ts +13 -4
  6. package/src/capabilities/block.parity.test.ts +250 -0
  7. package/src/capabilities/capabilities/capabilities.render.ts +3 -2
  8. package/src/capabilities/capabilities/capabilities.verb.ts +31 -13
  9. package/src/capabilities/capabilities/catalog.ts +18 -10
  10. package/src/capabilities/capabilities/hints.ts +13 -19
  11. package/src/capabilities/colophon/collectColophon.ts +34 -19
  12. package/src/capabilities/colophon/colophon.verb.ts +8 -4
  13. package/src/capabilities/colophon/types.ts +16 -7
  14. package/src/capabilities/config/collectConfigShow.test.ts +57 -0
  15. package/src/capabilities/config/collectConfigShow.ts +41 -4
  16. package/src/capabilities/config/fields.ts +0 -27
  17. package/src/capabilities/config/set.verb.ts +7 -3
  18. package/src/capabilities/config/show.render.test.ts +77 -5
  19. package/src/capabilities/config/show.render.ts +7 -12
  20. package/src/capabilities/config/show.verb.ts +4 -3
  21. package/src/capabilities/config/types.ts +8 -0
  22. package/src/capabilities/create/byteEquality.test.ts +78 -100
  23. package/src/capabilities/create/compiledCreate.subprocess.test.ts +52 -15
  24. package/src/capabilities/create/constants.ts +75 -0
  25. package/src/capabilities/create/create.mcp.test.ts +2 -2
  26. package/src/capabilities/create/create.test.ts +162 -15
  27. package/src/capabilities/create/create.verb.ts +140 -69
  28. package/src/capabilities/create/index.ts +2 -10
  29. package/src/capabilities/create/pickGenerator.ts +34 -28
  30. package/src/capabilities/create/templates.embedded.generated.ts +4 -29
  31. package/src/capabilities/create/types.ts +10 -6
  32. package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
  33. package/src/capabilities/distribution.test.ts +120 -0
  34. package/src/capabilities/distribution.ts +59 -0
  35. package/src/capabilities/doctor/checks/checkConfigFile.ts +6 -5
  36. package/src/capabilities/doctor/checks/checkKeStore.ts +2 -2
  37. package/src/capabilities/doctor/checks/checkMcpConfigured.ts +7 -6
  38. package/src/capabilities/doctor/checks/checkPackageRefs.ts +79 -45
  39. package/src/capabilities/doctor/checks/checkPragmaVersion.ts +3 -2
  40. package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +61 -11
  41. package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -23
  42. package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +3 -2
  43. package/src/capabilities/doctor/doctor.render.test.ts +6 -6
  44. package/src/capabilities/doctor/doctor.render.ts +2 -1
  45. package/src/capabilities/doctor/doctor.test.ts +37 -8
  46. package/src/capabilities/doctor/doctor.verb.ts +6 -2
  47. package/src/capabilities/doctor/runChecks.ts +5 -5
  48. package/src/capabilities/doctor/types.ts +1 -1
  49. package/src/capabilities/emptyRecovery.test.ts +32 -15
  50. package/src/capabilities/graph/inspect.verb.ts +3 -2
  51. package/src/capabilities/graph/query.verb.ts +3 -2
  52. package/src/capabilities/graph/runQuery.ts +8 -5
  53. package/src/capabilities/index.ts +22 -18
  54. package/src/capabilities/info/collectInfo.ts +10 -6
  55. package/src/capabilities/info/info.render.ts +3 -2
  56. package/src/capabilities/info/info.verb.ts +3 -2
  57. package/src/capabilities/lazy.test.ts +93 -2
  58. package/src/capabilities/ontology/verbs.ts +21 -21
  59. package/src/capabilities/prompt/prompt.test.ts +12 -6
  60. package/src/capabilities/prompt/verbs.ts +24 -11
  61. package/src/capabilities/resources/provider.ts +30 -11
  62. package/src/capabilities/resources/resources.test.ts +85 -29
  63. package/src/capabilities/setup/operations/setupGenerator.ts +16 -9
  64. package/src/capabilities/setup/operations/setupMcp.ts +2 -2
  65. package/src/capabilities/setup/operations/setupSkills.ts +3 -3
  66. package/src/capabilities/setup/setup.verb.ts +12 -5
  67. package/src/capabilities/setup/shell.ts +29 -3
  68. package/src/capabilities/skill/discover.ts +11 -5
  69. package/src/capabilities/skill/render.ts +4 -5
  70. package/src/capabilities/skill/verbs.ts +7 -7
  71. package/src/capabilities/sources/collectStatus.ts +55 -50
  72. package/src/capabilities/sources/index.ts +1 -1
  73. package/src/capabilities/sources/installSkills.ts +2 -2
  74. package/src/capabilities/sources/runUpdate.ts +113 -122
  75. package/src/capabilities/sources/sources.test.ts +111 -117
  76. package/src/capabilities/sources/status.render.test.ts +53 -24
  77. package/src/capabilities/sources/status.render.ts +24 -29
  78. package/src/capabilities/sources/status.verb.ts +15 -8
  79. package/src/capabilities/sources/types.ts +18 -25
  80. package/src/capabilities/sources/update.render.ts +9 -2
  81. package/src/capabilities/sources/update.verb.ts +12 -23
  82. package/src/capabilities/surface.test.ts +33 -10
  83. package/src/capabilities/tier.parity.test.ts +144 -0
  84. package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
  85. package/src/constants.test.ts +8 -6
  86. package/src/constants.ts +47 -21
  87. package/src/identity.test.ts +333 -0
  88. package/src/index.ts +2 -2
  89. package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +5 -2
  90. package/src/kernel/completion/emitScripts.test.ts +1 -1
  91. package/src/kernel/completion/emitScripts.ts +4 -2
  92. package/src/kernel/completion/entitySource.test.ts +185 -41
  93. package/src/kernel/completion/entitySource.ts +117 -107
  94. package/src/kernel/completion/model.test.ts +1 -1
  95. package/src/kernel/completion/model.ts +11 -0
  96. package/src/kernel/completion/safety.test.ts +82 -36
  97. package/src/kernel/completion/shellDrive.test.ts +592 -0
  98. package/src/kernel/completion/templates/fish.ts +28 -6
  99. package/src/kernel/completion/types.ts +3 -3
  100. package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +1 -1
  101. package/src/kernel/config/defaults.test.ts +85 -0
  102. package/src/kernel/config/defaults.ts +12 -23
  103. package/src/kernel/config/evaluateProjectConfig.ts +2 -3
  104. package/src/kernel/config/findProjectConfig.ts +4 -3
  105. package/src/kernel/config/firstRun.ts +12 -5
  106. package/src/kernel/config/globalConfig.ts +2 -2
  107. package/src/kernel/config/index.ts +4 -5
  108. package/src/kernel/config/paths.ts +17 -17
  109. package/src/kernel/config/readConfig.test.ts +242 -6
  110. package/src/kernel/config/readConfig.ts +8 -8
  111. package/src/kernel/config/schema.test.ts +50 -0
  112. package/src/kernel/config/schema.ts +97 -10
  113. package/src/kernel/config/types.ts +73 -19
  114. package/src/kernel/copy.test.ts +453 -0
  115. package/src/kernel/error/PragmaError.test.ts +1 -1
  116. package/src/kernel/error/constants.ts +3 -2
  117. package/src/kernel/error/index.ts +1 -1
  118. package/src/kernel/error/recovery.test.ts +22 -45
  119. package/src/kernel/error/recovery.ts +22 -27
  120. package/src/kernel/error/types.ts +5 -4
  121. package/src/kernel/packs/collect.test.ts +195 -11
  122. package/src/kernel/packs/collect.ts +213 -58
  123. package/src/kernel/packs/compile.test.ts +163 -7
  124. package/src/kernel/packs/compile.ts +15 -12
  125. package/src/kernel/packs/disclosure.test.ts +5 -2
  126. package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +11 -10
  127. package/src/kernel/packs/graphqlSource.test.ts +6 -3
  128. package/src/kernel/packs/iri.ts +5 -7
  129. package/src/kernel/packs/renderPack.ts +5 -3
  130. package/src/kernel/packs/resolveEntity.ts +21 -17
  131. package/src/kernel/packs/runBodies.ts +15 -14
  132. package/src/kernel/packs/schema.ts +96 -10
  133. package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
  134. package/src/kernel/packs/sparql/runSelect.ts +73 -34
  135. package/src/kernel/packs/toolDescription.test.ts +10 -2
  136. package/src/kernel/packs/types.ts +39 -4
  137. package/src/kernel/packs/uniqueness.ts +4 -4
  138. package/src/kernel/project/cli/buildProgram.test.ts +9 -4
  139. package/src/kernel/project/cli/dispatch.test.ts +67 -0
  140. package/src/kernel/project/cli/dispatch.ts +34 -12
  141. package/src/kernel/project/cli/helpFormat.ts +1 -1
  142. package/src/kernel/project/cli/rootHelp.ts +105 -105
  143. package/src/kernel/project/mcp/buildServer.ts +11 -6
  144. package/src/kernel/project/mcp/instructions.ts +11 -6
  145. package/src/kernel/project/mcp/parity.test.ts +39 -1
  146. package/src/kernel/project/mcp/prompts/prompts.test.ts +120 -5
  147. package/src/kernel/project/mcp/prompts/provider.ts +22 -8
  148. package/src/kernel/project/mcp/prompts/source.ts +68 -67
  149. package/src/kernel/project/mcp/registerVerb.ts +25 -6
  150. package/src/kernel/project/mcp/serve.ts +11 -3
  151. package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
  152. package/src/kernel/render/disclosure.ts +4 -2
  153. package/src/kernel/render/prefixes.test.ts +36 -0
  154. package/src/kernel/render/prefixes.ts +40 -13
  155. package/src/kernel/render/renderers.test.ts +1 -1
  156. package/src/kernel/runtime/graphpack/build.ts +29 -3
  157. package/src/kernel/runtime/graphpack/buildIndex.test.ts +46 -0
  158. package/src/kernel/runtime/graphpack/buildIndex.ts +52 -17
  159. package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -5
  160. package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -3
  161. package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
  162. package/src/kernel/runtime/graphpack/embedded.ts +37 -11
  163. package/src/kernel/runtime/graphpack/graphpack.test.ts +205 -5
  164. package/src/kernel/runtime/graphpack/hash.ts +3 -2
  165. package/src/kernel/runtime/graphpack/index.ts +1 -1
  166. package/src/kernel/runtime/graphpack/manifest.ts +114 -12
  167. package/src/kernel/runtime/graphpack/read.ts +4 -9
  168. package/src/kernel/runtime/graphpack/schemas.ts +74 -0
  169. package/src/kernel/runtime/graphpack/stories.ts +84 -0
  170. package/src/kernel/runtime/graphpack/types.ts +61 -48
  171. package/src/kernel/runtime/paths.ts +64 -15
  172. package/src/kernel/runtime/probe.test.ts +8 -4
  173. package/src/kernel/runtime/readEntity.ts +6 -5
  174. package/src/kernel/runtime/refs/gitOps.ts +1 -19
  175. package/src/kernel/runtime/refs/parseRef.ts +7 -7
  176. package/src/kernel/runtime/refs/resolve.ts +78 -62
  177. package/src/kernel/runtime/resolveSources.test.ts +63 -24
  178. package/src/kernel/runtime/resolveSources.ts +36 -25
  179. package/src/kernel/runtime/storeReadiness.ts +9 -8
  180. package/src/kernel/runtime/storeless.test.ts +1 -1
  181. package/src/kernel/runtime/wasmEmbed.test.ts +22 -19
  182. package/src/kernel/spec/emitReference.test.ts +3 -3
  183. package/src/kernel/spec/emitReference.ts +144 -11
  184. package/src/kernel/spec/emitSurface.ts +9 -5
  185. package/src/kernel/spec/surfaceConformance.test.ts +2 -2
  186. package/src/kernel/spec/surfaceConformance.ts +8 -0
  187. package/src/kernel/spec/types.ts +29 -9
  188. package/src/kernel/spec/validate.ts +2 -1
  189. package/src/kernel/vocabulary.test.ts +164 -0
  190. package/src/kernel/vocabulary.ts +146 -0
  191. package/src/testing/PARITY_GAPS.ts +8 -2
  192. package/src/testing/behavioral/README.md +3 -3
  193. package/src/testing/behavioral/completion.test.ts +19 -6
  194. package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
  195. package/src/testing/behavioral/errorMatrix.storeless.test.ts +1 -1
  196. package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
  197. package/src/testing/behavioral/harness.foundation.test.ts +14 -5
  198. package/src/testing/behavioral/journeys.cli.test.ts +116 -75
  199. package/src/testing/behavioral/journeys.defaultPack.test.ts +82 -176
  200. package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
  201. package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +9 -6
  202. package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
  203. package/src/testing/behavioral/liveReadSurface.ts +4 -3
  204. package/src/testing/behavioral/mcpSurface.test.ts +9 -4
  205. package/src/testing/behavioral/staleCommands.test.ts +10 -0
  206. package/src/testing/eval/__snapshots__/eval.test.ts.snap +7 -7
  207. package/src/testing/eval/cases/assembly.ts +13 -6
  208. package/src/testing/eval/cases/effectful.ts +25 -13
  209. package/src/testing/eval/cases/readNouns.ts +22 -20
  210. package/src/testing/eval/cases/stable.ts +5 -1
  211. package/src/testing/eval/eval.test.ts +7 -1
  212. package/src/testing/fixtures/fixtureCapability.ts +45 -1
  213. package/src/testing/fixtures/graph/canonical.ts +6 -3
  214. package/src/testing/fixtures/graph/defaultPack.ts +6 -5
  215. package/src/testing/fixtures/graph/owlExport.ts +7 -5
  216. package/src/testing/helpers/fixtureGraph.ts +33 -16
  217. package/src/testing/helpers/packRuntime.ts +2 -3
  218. package/src/testing/helpers/projectCli.ts +2 -1
  219. package/src/testing/helpers/projectMcp.ts +6 -0
  220. package/src/testing/perf/budgets.test.ts +4 -0
  221. package/src/testing/perf/budgets.ts +22 -7
  222. package/src/testing/perf/globalSetup.ts +121 -6
  223. package/src/types.ts +2 -2
  224. package/src/capabilities/block/blockList.test.ts +0 -79
  225. package/src/capabilities/block/blockList.verb.ts +0 -163
  226. package/src/capabilities/block/index.ts +0 -25
  227. package/src/capabilities/block/pack.ts +0 -166
  228. package/src/capabilities/block/parity.test.ts +0 -187
  229. package/src/capabilities/block/tierChain.ts +0 -78
  230. package/src/capabilities/colophon/pragmaColophon.ts +0 -66
  231. package/src/capabilities/modifier/index.ts +0 -15
  232. package/src/capabilities/modifier/pack.ts +0 -64
  233. package/src/capabilities/standard/index.ts +0 -18
  234. package/src/capabilities/standard/pack.ts +0 -128
  235. package/src/capabilities/tier/index.ts +0 -19
  236. package/src/capabilities/tier/lookup.render.test.ts +0 -72
  237. package/src/capabilities/tier/lookup.render.ts +0 -59
  238. package/src/capabilities/tier/lookup.test.ts +0 -83
  239. package/src/capabilities/tier/lookup.verb.ts +0 -44
  240. package/src/capabilities/tier/pack.ts +0 -28
  241. package/src/capabilities/tier/runLookup.ts +0 -87
  242. package/src/capabilities/token/addConfig.render.ts +0 -27
  243. package/src/capabilities/token/addConfig.test.ts +0 -62
  244. package/src/capabilities/token/addConfig.verb.ts +0 -40
  245. package/src/capabilities/token/index.ts +0 -19
  246. package/src/capabilities/token/pack.ts +0 -58
  247. package/src/capabilities/token/runAddConfig.ts +0 -95
  248. package/src/kernel/completion/bashDrive.test.ts +0 -73
  249. package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
  250. package/src/kernel/runtime/lock.ts +0 -90
@@ -1,58 +0,0 @@
1
- /**
2
- * The bundled `token` pack — design tokens as data.
3
- *
4
- * SPARQL-sourced on both verbs: there is no `ds:Token` GraphQL type to project
5
- * against when the graph ships no tokens, and the lookup reads a property path
6
- * (`ds:tokenType/rdfs:label`) only SPARQL can express. `token add-config` (a
7
- * mutation) is out of PR3; the `emptyRecovery` install hint is the story users
8
- * see on an empty store.
9
- */
10
-
11
- import type { PackDefinition } from "../../kernel/packs/types.js";
12
-
13
- export const tokenPack: PackDefinition = {
14
- noun: "token",
15
- description: "List all design tokens.",
16
- toolDescription:
17
- "List all design tokens with their type. Use when browsing which tokens exist under the active scope. Example: token_list {}.",
18
- list: {
19
- query: [
20
- "SELECT ?uri ?name ?category WHERE {",
21
- " ?uri a ds:Token ;",
22
- " ds:tokenId ?name .",
23
- " OPTIONAL {",
24
- " ?uri ds:tokenType ?type .",
25
- " ?type rdfs:label ?category .",
26
- " }",
27
- "}",
28
- "ORDER BY ?name",
29
- ].join("\n"),
30
- columns: [
31
- { field: "uri", label: "IRI" },
32
- { field: "name", label: "Name" },
33
- { field: "category", label: "Type" },
34
- ],
35
- emptyRecovery: {
36
- message:
37
- "No tokens in the store. Build it from the configured design-system packages.",
38
- cli: "pragma sources update",
39
- },
40
- },
41
- lookup: {
42
- source: "sparql",
43
- by: "ds:tokenId",
44
- type: "ds:Token",
45
- toolDescription:
46
- 'Get type and theme values for one or more design tokens by name. Use when resolving specific tokens\' light/dark values. Example: token_lookup { names: ["color.primary"] }.',
47
- fields: [
48
- { name: "category", property: "ds:tokenType/rdfs:label", label: "Type" },
49
- { name: "valueLight", property: "ds:valueLight", label: "Light value" },
50
- { name: "valueDark", property: "ds:valueDark", label: "Dark value" },
51
- ],
52
- sample: {
53
- fixedCount: true,
54
- toolDescription:
55
- "Return randomly selected complete design tokens (with theme values) as exemplars. Use BEFORE writing queries to see actual data shapes.",
56
- },
57
- },
58
- };
@@ -1,95 +0,0 @@
1
- /**
2
- * The `token add-config` write body (lazily imported, off the fast path).
3
- *
4
- * A store-backed mutation: it counts the design tokens in the active graph (so
5
- * the plan reports how many tokens the config will cover) and derives the
6
- * terrazzo token-source globs from the configured design-system packages, then
7
- * returns a Task that writes `tokens.config.mjs`. The store read happens in the
8
- * async setup; the file write is the Task's single `WriteFile` effect, so a
9
- * plan-only preview (`mutation.preview`) describes the write without performing
10
- * it. Ported from the old shell's `token add-config` (terrazzo `defineConfig`).
11
- */
12
-
13
- import { resolve } from "node:path";
14
- import { $, exists, gen, type Task, writeFile } from "@canonical/task";
15
- import type { PragmaRuntime } from "../../kernel/runtime/types.js";
16
-
17
- /** The default token source when no design-system packages are configured. */
18
- const DEFAULT_TOKEN_SOURCE =
19
- "node_modules/@canonical/ds-global/tokens/**/*.json";
20
-
21
- /** The result of generating a terrazzo tokens config. */
22
- export interface AddConfigResult {
23
- /** The absolute path written. */
24
- readonly path: string;
25
- /** How many `ds:Token` entities the active graph holds. */
26
- readonly tokenCount: number;
27
- /** The token-source globs written into the config. */
28
- readonly sources: readonly string[];
29
- /** Whether a `tokens.config.mjs` already existed (it is overwritten). */
30
- readonly alreadyExisted: boolean;
31
- }
32
-
33
- /** Count the `ds:Token` entities in the booted store (best-effort). */
34
- async function countTokens(rt: PragmaRuntime): Promise<number> {
35
- try {
36
- const result = (await rt.query.sparql(
37
- "SELECT (COUNT(DISTINCT ?token) AS ?count) WHERE { ?token a ds:Token }",
38
- )) as { type?: string; bindings?: { count?: string }[] };
39
- const raw = result.bindings?.[0]?.count;
40
- return raw ? Number(raw) : 0;
41
- } catch {
42
- return 0;
43
- }
44
- }
45
-
46
- /** Derive the terrazzo token-source globs from the configured packages. */
47
- async function resolveSources(rt: PragmaRuntime): Promise<string[]> {
48
- const { config } = await rt.loadConfig();
49
- const packages = config.packages ?? [];
50
- if (packages.length === 0) return [DEFAULT_TOKEN_SOURCE];
51
- return packages.map((pkg) => {
52
- const name = typeof pkg === "string" ? pkg : pkg.name;
53
- return `node_modules/${name}/tokens/**/*.json`;
54
- });
55
- }
56
-
57
- /** Render the terrazzo `tokens.config.mjs` content. */
58
- function generateConfig(sources: readonly string[]): string {
59
- const sourceList = sources
60
- .map((source) => ` ${JSON.stringify(source)}`)
61
- .join(",\n");
62
- return `// tokens.config.mjs — generated by \`pragma token add-config\`
63
- import { defineConfig } from "@canonical/terrazzo";
64
-
65
- export default defineConfig({
66
- tokens: [
67
- ${sourceList},
68
- ],
69
- outDir: "./tokens/",
70
- plugins: [],
71
- });
72
- `;
73
- }
74
-
75
- /**
76
- * Build the Task that writes `tokens.config.mjs` for the terrazzo pipeline.
77
- *
78
- * @param rt - The runtime (its store is booted by the projector for needsStore).
79
- * @returns A Task yielding the write outcome.
80
- * @note Impure — reads the store + config; the write is the Task's effect.
81
- */
82
- export async function runAddConfig(
83
- rt: PragmaRuntime,
84
- ): Promise<Task<AddConfigResult>> {
85
- const tokenCount = await countTokens(rt);
86
- const sources = await resolveSources(rt);
87
- const path = resolve(rt.cwd, "tokens.config.mjs");
88
- const content = generateConfig(sources);
89
-
90
- return gen(function* () {
91
- const alreadyExisted = yield* $(exists(path));
92
- yield* $(writeFile(path, content));
93
- return { path, tokenCount, sources, alreadyExisted };
94
- });
95
- }
@@ -1,73 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { mkdtempSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { describe, expect, it } from "vitest";
6
- import { completionFixture } from "../../testing/fixtures/completionFixture.js";
7
- import { emitScripts } from "./emitScripts.js";
8
-
9
- /**
10
- * M1 regression: the generated bash script must complete the `--flag=value`
11
- * wordbreak form. With `=` in COMP_WORDBREAKS, bash splits `--format=` into
12
- * `--format` `=` `` (or `` after `=`); without the normalization at the top of
13
- * `_pragma`, the value slot falls through to the noun/positional arm and
14
- * offers the WRONG candidates. These tests drive the REAL bash to prove the
15
- * fix, so the static tier answers `--format=<TAB>` as a flag value with zero
16
- * exec (the resolver is only reached for `{kind:"entity"}` contexts).
17
- */
18
-
19
- /** Whether a usable bash is on PATH (the package pins os:["linux"], so it is). */
20
- const bashOk =
21
- spawnSync("bash", ["-c", "printf ok"], { encoding: "utf-8" }).stdout === "ok";
22
-
23
- /** The bash completion script for the fixture grammar (has the global --format). */
24
- const script = emitScripts([completionFixture]).bash;
25
-
26
- /**
27
- * Source the generated script in a real bash, place the cursor per COMP_WORDS
28
- * / COMP_CWORD, invoke `_pragma`, and return COMPREPLY line-by-line.
29
- */
30
- function driveBash(words: readonly string[], cword: number): string[] {
31
- const dir = mkdtempSync(join(tmpdir(), "pragma-bashdrive-"));
32
- const file = join(dir, "completion.bash");
33
- writeFileSync(file, script);
34
- const wordsLiteral = words
35
- .map((word) => `'${word.replace(/'/g, "'\\''")}'`)
36
- .join(" ");
37
- const driver = [
38
- `source '${file}'`,
39
- `COMP_WORDS=(${wordsLiteral})`,
40
- `COMP_CWORD=${cword}`,
41
- "_pragma",
42
- `printf '%s\\n' "\${COMPREPLY[@]}"`,
43
- ].join("\n");
44
- const result = spawnSync("bash", ["--norc", "--noprofile", "-c", driver], {
45
- encoding: "utf-8",
46
- });
47
- return result.stdout.split("\n").filter((line) => line.length > 0);
48
- }
49
-
50
- describe.skipIf(!bashOk)("generated bash — --flag=value wordbreak (M1)", () => {
51
- it("routes --format=<TAB> to the format values (not nouns/positionals)", () => {
52
- // Default COMP_WORDBREAKS split: `--format` `=` `` (empty current word).
53
- const reply = driveBash(["pragma", "--format", "=", ""], 3);
54
- expect(reply.sort()).toEqual(["json", "llm", "plain"]);
55
- });
56
-
57
- it("filters the value by the partial typed after =", () => {
58
- const reply = driveBash(["pragma", "--format", "=", "j"], 3);
59
- expect(reply).toEqual(["json"]);
60
- });
61
-
62
- it("routes a verb-scoped --format=<TAB> the same way", () => {
63
- // After a noun/verb the value must still route as a flag value, never as
64
- // block's positional (which would offer entity/enum candidates instead).
65
- const reply = driveBash(["pragma", "block", "get", "--format", "=", ""], 5);
66
- expect(reply.sort()).toEqual(["json", "llm", "plain"]);
67
- });
68
-
69
- it("still completes the space form --format <TAB> (unbroken)", () => {
70
- const reply = driveBash(["pragma", "--format", ""], 2);
71
- expect(reply.sort()).toEqual(["json", "llm", "plain"]);
72
- });
73
- });
@@ -1,39 +0,0 @@
1
- # Embedded fallback pack source — a small, self-contained sample ontology.
2
- #
3
- # Compiled by `scripts/genEmbedded.ts` into `pack.generated.ts`. It exists so a
4
- # fresh install (no configured packages, no lock) can answer store-backed reads
5
- # without a network round-trip. Keep it tiny: it ships inside the binary.
6
-
7
- @prefix ex: <https://pragma.canonical.com/sample#> .
8
- @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
9
- @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
10
- @prefix owl: <http://www.w3.org/2002/07/owl#> .
11
- @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
12
-
13
- ex:Component a owl:Class ;
14
- rdfs:label "Component" ;
15
- rdfs:comment "A reusable design-system building block." .
16
-
17
- ex:componentName a owl:DatatypeProperty ;
18
- rdfs:label "component name" ;
19
- rdfs:domain ex:Component ;
20
- rdfs:range xsd:string .
21
-
22
- ex:dependsOn a owl:ObjectProperty ;
23
- rdfs:label "depends on" ;
24
- rdfs:domain ex:Component ;
25
- rdfs:range ex:Component .
26
-
27
- ex:Button a ex:Component ;
28
- rdfs:label "Button" ;
29
- ex:componentName "Button" .
30
-
31
- ex:Card a ex:Component ;
32
- rdfs:label "Card" ;
33
- ex:componentName "Card" ;
34
- ex:dependsOn ex:Button .
35
-
36
- ex:Dialog a ex:Component ;
37
- rdfs:label "Dialog" ;
38
- ex:componentName "Dialog" ;
39
- ex:dependsOn ex:Button , ex:Card .
@@ -1,90 +0,0 @@
1
- /**
2
- * The project lock — `pragma.lock.json`, committed at the project root.
3
- *
4
- * It pins the single combined pack the store boots from: `contentHash` names
5
- * the pack's cache directory, and `packs[]` records the resolved provenance of
6
- * every configured source (so `sources status` reports it and a `--frozen`
7
- * update re-resolves to exactly these commits). Serialization is canonical —
8
- * fixed field order, packs sorted by name, one trailing newline — so a
9
- * `--frozen` update that changes nothing rewrites a byte-identical file.
10
- *
11
- * Pure: zod + fs only, no store code, so both the storeless `sources status`
12
- * verb and the store-boot decision table read it without booting oxigraph.
13
- */
14
-
15
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
16
- import { z } from "zod";
17
- import { lockPath } from "./paths.js";
18
-
19
- /** One resolved source's provenance in the lock. */
20
- export const lockPackageSchema = z.object({
21
- /** Package name (config `packages` entry name / npm name). */
22
- name: z.string(),
23
- /** The config `packages` source ref, verbatim (e.g. `git+https://…#main`). */
24
- source: z.string(),
25
- /** The resolved commit / version / absolute path this ref pinned to. */
26
- resolved: z.string(),
27
- /** ISO timestamp the ref was resolved. */
28
- resolvedAt: z.string(),
29
- });
30
-
31
- /** The lock document. */
32
- export const pragmaLockSchema = z.object({
33
- version: z.literal(1),
34
- /** The combined pack's content hash — names its cache directory. */
35
- contentHash: z.string(),
36
- packs: z.array(lockPackageSchema),
37
- });
38
-
39
- /** One resolved source's provenance in the lock. */
40
- export type PragmaLockPackage = z.infer<typeof lockPackageSchema>;
41
- /** The parsed lock document. */
42
- export type PragmaLock = z.infer<typeof pragmaLockSchema>;
43
-
44
- /**
45
- * Read and validate the lock for a working directory.
46
- *
47
- * @param cwd - The project directory.
48
- * @returns The parsed lock, or `undefined` when absent or invalid.
49
- * @note Impure — reads from disk.
50
- */
51
- export function readLock(cwd: string): PragmaLock | undefined {
52
- const path = lockPath(cwd);
53
- if (!existsSync(path)) return undefined;
54
- try {
55
- return pragmaLockSchema.parse(JSON.parse(readFileSync(path, "utf-8")));
56
- } catch {
57
- return undefined;
58
- }
59
- }
60
-
61
- /** Serialize a lock canonically — stable field order, sorted packs, newline. */
62
- export function serializeLock(lock: PragmaLock): string {
63
- const packs = [...lock.packs]
64
- .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))
65
- .map((pack) => ({
66
- name: pack.name,
67
- source: pack.source,
68
- resolved: pack.resolved,
69
- resolvedAt: pack.resolvedAt,
70
- }));
71
- return `${JSON.stringify(
72
- { version: lock.version, contentHash: lock.contentHash, packs },
73
- null,
74
- 2,
75
- )}\n`;
76
- }
77
-
78
- /**
79
- * Write the lock for a working directory.
80
- *
81
- * @param cwd - The project directory.
82
- * @param lock - The lock to persist.
83
- * @returns The exact bytes written (for the write effect / assertions).
84
- * @note Impure — writes `pragma.lock.json`.
85
- */
86
- export function writeLock(cwd: string, lock: PragmaLock): string {
87
- const content = serializeLock(lock);
88
- writeFileSync(lockPath(cwd), content);
89
- return content;
90
- }