@canonical/pragma-cli 0.32.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -0
- package/dist/pragma +0 -0
- package/package.json +19 -15
- package/pragma.conf.ts +664 -0
- package/src/bin.ts +15 -6
- package/src/capabilities/block.parity.test.ts +250 -0
- package/src/capabilities/capabilities/capabilities.render.ts +3 -2
- package/src/capabilities/capabilities/capabilities.test.ts +10 -1
- package/src/capabilities/capabilities/capabilities.verb.ts +32 -14
- package/src/capabilities/capabilities/catalog.ts +20 -8
- package/src/capabilities/capabilities/hints.ts +21 -36
- package/src/capabilities/capabilities/types.ts +2 -0
- package/src/capabilities/colophon/collectColophon.ts +34 -19
- package/src/capabilities/colophon/colophon.render.test.ts +31 -4
- package/src/capabilities/colophon/colophon.render.ts +13 -4
- package/src/capabilities/colophon/colophon.test.ts +3 -3
- package/src/capabilities/colophon/colophon.verb.ts +11 -4
- package/src/capabilities/colophon/markdownTerminal.ts +33 -14
- package/src/capabilities/colophon/types.ts +16 -7
- package/src/capabilities/config/collectConfigShow.test.ts +57 -0
- package/src/capabilities/config/collectConfigShow.ts +41 -4
- package/src/capabilities/config/fields.ts +10 -108
- package/src/capabilities/config/set.test.ts +6 -6
- package/src/capabilities/config/set.verb.ts +12 -8
- package/src/capabilities/config/show.render.test.ts +137 -0
- package/src/capabilities/config/show.render.ts +57 -16
- package/src/capabilities/config/show.verb.ts +9 -8
- package/src/capabilities/config/types.ts +8 -0
- package/src/capabilities/create/byteEquality.subprocess.test.ts +1 -1
- package/src/capabilities/create/byteEquality.test.ts +82 -101
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +53 -16
- package/src/capabilities/create/constants.ts +75 -0
- package/src/capabilities/create/create.mcp.test.ts +2 -2
- package/src/capabilities/create/create.test.ts +192 -16
- package/src/capabilities/create/create.verb.ts +208 -79
- package/src/capabilities/create/index.ts +2 -10
- package/src/capabilities/create/pickGenerator.ts +34 -28
- package/src/capabilities/create/templates.embedded.generated.ts +4 -29
- package/src/capabilities/create/types.ts +10 -6
- package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
- package/src/capabilities/distribution.test.ts +120 -0
- package/src/capabilities/distribution.ts +59 -0
- package/src/capabilities/doctor/checks/checkConfigFile.ts +6 -5
- package/src/capabilities/doctor/checks/checkKeStore.ts +2 -2
- package/src/capabilities/doctor/checks/checkMcpCommands.ts +6 -0
- package/src/capabilities/doctor/checks/checkMcpConfigured.ts +15 -8
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +79 -45
- package/src/capabilities/doctor/checks/checkPragmaVersion.ts +3 -2
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +61 -11
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -23
- package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +3 -2
- package/src/capabilities/doctor/checks/deriveBand.test.ts +42 -0
- package/src/capabilities/doctor/checks/deriveBand.ts +28 -0
- package/src/capabilities/doctor/doctor.render.test.ts +170 -0
- package/src/capabilities/doctor/doctor.render.ts +117 -34
- package/src/capabilities/doctor/doctor.test.ts +68 -9
- package/src/capabilities/doctor/doctor.verb.ts +6 -2
- package/src/capabilities/doctor/runChecks.ts +33 -9
- package/src/capabilities/doctor/types.ts +16 -1
- package/src/capabilities/emptyRecovery.test.ts +32 -15
- package/src/capabilities/graph/inspect.verb.ts +3 -2
- package/src/capabilities/graph/query.verb.ts +3 -2
- package/src/capabilities/graph/runQuery.ts +8 -5
- package/src/capabilities/index.ts +22 -18
- package/src/capabilities/info/collectInfo.ts +10 -6
- package/src/capabilities/info/info.render.ts +3 -2
- package/src/capabilities/info/info.verb.ts +3 -2
- package/src/capabilities/lazy.test.ts +93 -2
- package/src/capabilities/ontology/index.ts +10 -3
- package/src/capabilities/ontology/ontology.test.ts +157 -5
- package/src/capabilities/ontology/verbs.ts +203 -104
- package/src/capabilities/prompt/prompt.render.test.ts +94 -0
- package/src/capabilities/prompt/prompt.render.ts +23 -6
- package/src/capabilities/prompt/prompt.test.ts +68 -1
- package/src/capabilities/prompt/verbs.ts +24 -11
- package/src/capabilities/reference.test.ts +32 -0
- package/src/capabilities/resources/provider.ts +58 -25
- package/src/capabilities/resources/resources.test.ts +176 -21
- package/src/capabilities/scopeTypeSync.test.ts +37 -0
- package/src/capabilities/setup/index.ts +7 -1
- package/src/capabilities/setup/operations/setupCompletions.ts +49 -16
- package/src/capabilities/setup/operations/setupGenerator.ts +166 -63
- package/src/capabilities/setup/operations/setupLsp.ts +56 -12
- package/src/capabilities/setup/operations/setupMcp.ts +216 -39
- package/src/capabilities/setup/operations/setupSkills.ts +10 -4
- package/src/capabilities/setup/setup.render.test.ts +109 -0
- package/src/capabilities/setup/setup.render.ts +61 -14
- package/src/capabilities/setup/setup.test.ts +352 -1
- package/src/capabilities/setup/setup.verb.ts +68 -9
- package/src/capabilities/setup/shell.ts +29 -3
- package/src/capabilities/setup/types.ts +59 -2
- package/src/capabilities/shared/bands.ts +16 -0
- package/src/capabilities/skill/discover.ts +11 -5
- package/src/capabilities/skill/render.ts +4 -5
- package/src/capabilities/skill/verbs.ts +7 -7
- package/src/capabilities/sources/collectStatus.ts +69 -49
- package/src/capabilities/sources/index.ts +1 -1
- package/src/capabilities/sources/installSkills.ts +2 -2
- package/src/capabilities/sources/runUpdate.ts +146 -98
- package/src/capabilities/sources/sources.test.ts +264 -84
- package/src/capabilities/sources/status.render.test.ts +94 -0
- package/src/capabilities/sources/status.render.ts +55 -33
- package/src/capabilities/sources/status.verb.ts +15 -8
- package/src/capabilities/sources/types.ts +18 -25
- package/src/capabilities/sources/update.render.ts +9 -2
- package/src/capabilities/sources/update.verb.ts +12 -23
- package/src/capabilities/surface.test.ts +65 -17
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
- package/src/constants.test.ts +9 -7
- package/src/constants.ts +49 -23
- package/src/identity.test.ts +333 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +18 -16
- package/src/kernel/completion/complete.test.ts +3 -5
- package/src/kernel/completion/emitScripts.test.ts +1 -1
- package/src/kernel/completion/emitScripts.ts +4 -2
- package/src/kernel/completion/entitySource.test.ts +185 -41
- package/src/kernel/completion/entitySource.ts +131 -113
- package/src/kernel/completion/model.test.ts +3 -3
- package/src/kernel/completion/model.ts +11 -1
- package/src/kernel/completion/parse.test.ts +2 -4
- package/src/kernel/completion/safety.test.ts +82 -36
- package/src/kernel/completion/shellDrive.test.ts +592 -0
- package/src/kernel/completion/templates/fish.ts +28 -6
- package/src/kernel/completion/types.ts +3 -3
- package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +1 -1
- package/src/kernel/config/defaults.test.ts +85 -0
- package/src/kernel/config/defaults.ts +12 -23
- package/src/kernel/config/evaluateProjectConfig.ts +2 -3
- package/src/kernel/config/findProjectConfig.ts +4 -3
- package/src/kernel/config/firstRun.ts +12 -5
- package/src/kernel/config/globalConfig.ts +2 -2
- package/src/kernel/config/index.ts +4 -5
- package/src/kernel/config/paths.ts +17 -17
- package/src/kernel/config/readConfig.test.ts +242 -6
- package/src/kernel/config/readConfig.ts +8 -8
- package/src/kernel/config/schema.test.ts +50 -0
- package/src/kernel/config/schema.ts +97 -10
- package/src/kernel/config/types.ts +73 -19
- package/src/kernel/copy.test.ts +453 -0
- package/src/kernel/error/PragmaError.test.ts +5 -5
- package/src/kernel/error/constants.ts +3 -2
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +22 -45
- package/src/kernel/error/recovery.ts +22 -27
- package/src/kernel/error/renderError.ts +1 -1
- package/src/kernel/error/types.ts +5 -4
- package/src/kernel/packs/collect.test.ts +195 -11
- package/src/kernel/packs/collect.ts +213 -58
- package/src/kernel/packs/compile.test.ts +163 -7
- package/src/kernel/packs/compile.ts +15 -12
- package/src/kernel/packs/disclosure.test.ts +5 -2
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +11 -10
- package/src/kernel/packs/graphqlSource.test.ts +6 -3
- package/src/kernel/packs/iri.ts +5 -7
- package/src/kernel/packs/renderPack.ts +5 -3
- package/src/kernel/packs/resolveEntity.ts +21 -17
- package/src/kernel/packs/runBodies.ts +15 -14
- package/src/kernel/packs/schema.ts +96 -10
- package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
- package/src/kernel/packs/sparql/runSelect.ts +73 -34
- package/src/kernel/packs/toolDescription.test.ts +10 -2
- package/src/kernel/packs/types.ts +39 -4
- package/src/kernel/packs/uniqueness.ts +4 -4
- package/src/kernel/project/cli/buildProgram.test.ts +60 -11
- package/src/kernel/project/cli/buildProgram.ts +11 -0
- package/src/kernel/project/cli/dispatch.test.ts +67 -0
- package/src/kernel/project/cli/dispatch.ts +34 -12
- package/src/kernel/project/cli/globalFlags.test.ts +12 -4
- package/src/kernel/project/cli/globalFlags.ts +14 -14
- package/src/kernel/project/cli/helpFormat.ts +1 -1
- package/src/kernel/project/cli/rootHelp.ts +109 -107
- package/src/kernel/project/mcp/buildServer.ts +11 -6
- package/src/kernel/project/mcp/instructions.ts +12 -7
- package/src/kernel/project/mcp/mcpError.ts +52 -0
- package/src/kernel/project/mcp/parity.test.ts +39 -1
- package/src/kernel/project/mcp/prompts/prompts.test.ts +128 -5
- package/src/kernel/project/mcp/prompts/provider.ts +51 -7
- package/src/kernel/project/mcp/prompts/source.ts +68 -67
- package/src/kernel/project/mcp/registerVerb.ts +25 -6
- package/src/kernel/project/mcp/serve.ts +11 -3
- package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
- package/src/kernel/render/disclosure.ts +4 -2
- package/src/kernel/render/formatters.ts +5 -4
- package/src/kernel/render/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +35 -1
- package/src/kernel/render/renderers.ts +25 -7
- package/src/kernel/render/style.test.ts +31 -0
- package/src/kernel/render/style.ts +74 -0
- package/src/kernel/runtime/graphpack/build.ts +57 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +149 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +173 -50
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -8
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -4
- package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +37 -11
- package/src/kernel/runtime/graphpack/graphpack.test.ts +274 -6
- package/src/kernel/runtime/graphpack/hash.ts +3 -2
- package/src/kernel/runtime/graphpack/index.ts +1 -1
- package/src/kernel/runtime/graphpack/manifest.ts +114 -12
- package/src/kernel/runtime/graphpack/read.ts +32 -22
- package/src/kernel/runtime/graphpack/schemas.ts +74 -0
- package/src/kernel/runtime/graphpack/stories.ts +84 -0
- package/src/kernel/runtime/graphpack/types.ts +72 -45
- package/src/kernel/runtime/loadSession.ts +4 -12
- package/src/kernel/runtime/paths.ts +64 -15
- package/src/kernel/runtime/probe.test.ts +8 -4
- package/src/kernel/runtime/readEntity.ts +6 -5
- package/src/kernel/runtime/refs/gitOps.ts +1 -19
- package/src/kernel/runtime/refs/parseRef.ts +7 -7
- package/src/kernel/runtime/refs/resolve.ts +141 -65
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +62 -0
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/types.ts +1 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +25 -20
- package/src/kernel/spec/emitReference.test.ts +196 -0
- package/src/kernel/spec/emitReference.ts +624 -0
- package/src/kernel/spec/emitSurface.ts +13 -7
- package/src/kernel/spec/index.ts +2 -0
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/surfaceConformance.ts +8 -0
- package/src/kernel/spec/types.ts +29 -9
- package/src/kernel/spec/validate.ts +2 -1
- package/src/kernel/vocabulary.test.ts +164 -0
- package/src/kernel/vocabulary.ts +146 -0
- package/src/testing/PARITY_GAPS.ts +9 -3
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/autoLlm.e2e.test.ts +12 -2
- package/src/testing/behavioral/completion.test.ts +21 -8
- package/src/testing/behavioral/disclosure.test.ts +12 -0
- package/src/testing/behavioral/docExamples.test.ts +283 -0
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +3 -2
- package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
- package/src/testing/behavioral/harness.foundation.test.ts +14 -5
- package/src/testing/behavioral/journeys.cli.test.ts +116 -73
- package/src/testing/behavioral/journeys.defaultPack.test.ts +477 -0
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.interactiveTty.e2e.test.ts +66 -0
- package/src/testing/behavioral/journeys.livePack.e2e.test.ts +129 -0
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +179 -0
- package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
- package/src/testing/behavioral/liveReadSurface.ts +4 -3
- package/src/testing/behavioral/mcpSurface.test.ts +10 -5
- package/src/testing/behavioral/staleCommands.test.ts +86 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +9 -9
- package/src/testing/eval/cases/assembly.ts +16 -9
- package/src/testing/eval/cases/effectful.ts +31 -16
- package/src/testing/eval/cases/readNouns.ts +23 -18
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/fixtureCapability.ts +201 -1
- package/src/testing/fixtures/graph/canonical.ts +6 -3
- package/src/testing/fixtures/graph/defaultPack.ts +179 -0
- package/src/testing/fixtures/graph/owlExport.ts +97 -0
- package/src/testing/helpers/extractSnippets.ts +29 -0
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- package/src/testing/helpers/golden.ts +1 -1
- package/src/testing/helpers/packRuntime.ts +2 -3
- package/src/testing/helpers/projectCli.ts +2 -1
- package/src/testing/helpers/projectMcp.ts +6 -0
- package/src/testing/perf/budgets.test.ts +4 -0
- package/src/testing/perf/budgets.ts +22 -7
- package/src/testing/perf/globalSetup.ts +121 -6
- package/src/types.ts +2 -2
- package/src/capabilities/block/blockList.verb.ts +0 -150
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -155
- package/src/capabilities/block/parity.test.ts +0 -180
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- package/src/capabilities/config/field.test.ts +0 -188
- package/src/capabilities/modifier/index.ts +0 -15
- package/src/capabilities/modifier/pack.ts +0 -64
- package/src/capabilities/standard/index.ts +0 -18
- package/src/capabilities/standard/pack.ts +0 -128
- package/src/capabilities/tier/index.ts +0 -19
- package/src/capabilities/tier/lookup.render.ts +0 -34
- package/src/capabilities/tier/lookup.test.ts +0 -68
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -59
- package/src/capabilities/token/addConfig.render.ts +0 -27
- package/src/capabilities/token/addConfig.test.ts +0 -62
- package/src/capabilities/token/addConfig.verb.ts +0 -40
- package/src/capabilities/token/index.ts +0 -19
- package/src/capabilities/token/pack.ts +0 -58
- package/src/capabilities/token/runAddConfig.ts +0 -95
- package/src/kernel/completion/bashDrive.test.ts +0 -73
- package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
- package/src/kernel/runtime/lock.ts +0 -90
|
@@ -5,18 +5,19 @@
|
|
|
5
5
|
*
|
|
6
6
|
* - Preview (CLI `--dry-run`, or MCP without `confirm`): NETWORK-FREE. It reads
|
|
7
7
|
* only the config, then hands back a plan-only Task listing the refs it would
|
|
8
|
-
* resolve+build and the
|
|
8
|
+
* resolve+build and the pointer it would write — no git fetch, no compile, no
|
|
9
9
|
* cache write. This is what a dry-run / agent "preview" must be: side-effect
|
|
10
10
|
* free and offline-safe.
|
|
11
|
-
* - Real execution: the heavy work — resolve every configured
|
|
11
|
+
* - Real execution: the heavy work — resolve every configured pack (git
|
|
12
12
|
* clone/fetch, file verify, npm resolve), then build the ONE combined
|
|
13
13
|
* content-addressed pack — runs eagerly (it is not expressible as a task
|
|
14
14
|
* effect: the effect set is fs + exec, and the in-process compile is not an
|
|
15
|
-
* effect at all). The returned Task models the
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
15
|
+
* effect at all). The returned Task models the mutations: the active-pack
|
|
16
|
+
* pointer write (undo restores or removes the prior pointer) and the package
|
|
17
|
+
* skill symlinks.
|
|
18
|
+
*
|
|
19
|
+
* Pinning a revision is the ref's job, not a flag's: put a SHA in the source
|
|
20
|
+
* (`git+https://…#<sha>`) and every update resolves to exactly that commit.
|
|
20
21
|
*/
|
|
21
22
|
|
|
22
23
|
import {
|
|
@@ -29,23 +30,18 @@ import {
|
|
|
29
30
|
type Task,
|
|
30
31
|
writeFile,
|
|
31
32
|
} from "@canonical/task";
|
|
32
|
-
import {
|
|
33
|
-
import type { PackageEntry } from "../../kernel/config/types.js";
|
|
33
|
+
import { VERSION } from "../../constants.js";
|
|
34
34
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
35
35
|
import { cliRecovery } from "../../kernel/error/recovery.js";
|
|
36
36
|
import { buildPack } from "../../kernel/runtime/graphpack/build.js";
|
|
37
|
-
import {
|
|
38
|
-
type PragmaLock,
|
|
39
|
-
readLock,
|
|
40
|
-
serializeLock,
|
|
41
|
-
} from "../../kernel/runtime/lock.js";
|
|
42
|
-
import { LOCK_BASENAME, lockPath } from "../../kernel/runtime/paths.js";
|
|
37
|
+
import { activePackPath, readActivePack } from "../../kernel/runtime/paths.js";
|
|
43
38
|
import type { PackageRef } from "../../kernel/runtime/refs/parseRef.js";
|
|
44
39
|
import {
|
|
45
|
-
|
|
40
|
+
parsePackDeclaration,
|
|
46
41
|
redactUrl,
|
|
47
42
|
} from "../../kernel/runtime/refs/parseRef.js";
|
|
48
43
|
import {
|
|
44
|
+
detectPrefixClashes,
|
|
49
45
|
harvestPrefixes,
|
|
50
46
|
type ResolvedPackage,
|
|
51
47
|
resolvePackage,
|
|
@@ -66,17 +62,43 @@ const CORE_PREFIXES: Readonly<Record<string, string>> = {
|
|
|
66
62
|
dcterms: "http://purl.org/dc/terms/",
|
|
67
63
|
};
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
/**
|
|
66
|
+
* The prefix map a pack is built with: core < the packs' own `@prefix` < config.
|
|
67
|
+
*
|
|
68
|
+
* A resolved package's own declarations are harvested from its TTL (ke does not
|
|
69
|
+
* fold parsed-Turtle prefixes into `store.prefixes`) and merged beneath config
|
|
70
|
+
* so the index compacts pack URIs to `pfx:Local` — the FROZEN `{name,type}`
|
|
71
|
+
* token contract — while config still wins any clash. The merged map is
|
|
72
|
+
* persisted in the manifest, so boot reads the same names.
|
|
73
|
+
*
|
|
74
|
+
* Exported because the bundler (`scripts/bundle.ts`) compiles the embedded pack
|
|
75
|
+
* through this exact precedence. If the two pipelines computed prefixes
|
|
76
|
+
* separately, the embed could compact entities differently from what the SAME
|
|
77
|
+
* config produces on a user's machine — a silent divergence in entity names.
|
|
78
|
+
*
|
|
79
|
+
* @param inputs - The resolved packages' labelled RDF sources.
|
|
80
|
+
* @param configPrefixes - The config layer's `prefixes`, if any.
|
|
81
|
+
* @returns The merged prefix map to build with.
|
|
82
|
+
*/
|
|
83
|
+
export function buildPackPrefixes(
|
|
84
|
+
inputs: readonly { readonly content: string }[],
|
|
85
|
+
configPrefixes: Readonly<Record<string, string>> | undefined,
|
|
86
|
+
): Record<string, string> {
|
|
87
|
+
return {
|
|
88
|
+
...CORE_PREFIXES,
|
|
89
|
+
...harvestPrefixes(inputs),
|
|
90
|
+
...(configPrefixes ?? {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
71
93
|
|
|
72
94
|
/**
|
|
73
95
|
* Build the NETWORK-FREE preview plan for `sources update`.
|
|
74
96
|
*
|
|
75
97
|
* A plan-only Task: it reads the config to list the refs a real update would
|
|
76
|
-
* resolve and build, then models the
|
|
77
|
-
* as effects the dry-run interpreter can describe WITHOUT running them.
|
|
78
|
-
* no compile, no cache write — so `--dry-run` and an MCP plan-first call
|
|
79
|
-
* offline-safe. Config refs are parsed (a cheap, offline validity check) but
|
|
98
|
+
* resolve and build, then models the project mutation (the active-pack pointer
|
|
99
|
+
* write) as effects the dry-run interpreter can describe WITHOUT running them.
|
|
100
|
+
* No git, no compile, no cache write — so `--dry-run` and an MCP plan-first call
|
|
101
|
+
* are offline-safe. Config refs are parsed (a cheap, offline validity check) but
|
|
80
102
|
* never resolved.
|
|
81
103
|
*
|
|
82
104
|
* @param runtime - The per-invocation runtime.
|
|
@@ -86,57 +108,51 @@ async function buildUpdatePlan(
|
|
|
86
108
|
runtime: PragmaRuntime,
|
|
87
109
|
): Promise<Task<SourcesUpdateData>> {
|
|
88
110
|
const layers = await runtime.loadConfig();
|
|
89
|
-
const entries = layers.config.
|
|
90
|
-
const refs = entries.map(
|
|
91
|
-
const path = lockPath(runtime.cwd);
|
|
111
|
+
const entries = layers.config.packs ?? [];
|
|
112
|
+
const refs = entries.map(parsePackDeclaration);
|
|
92
113
|
|
|
93
114
|
const data: SourcesUpdateData = {
|
|
94
115
|
contentHash: "",
|
|
95
116
|
reused: false,
|
|
96
|
-
lockPath: path,
|
|
97
|
-
packs: refs.map((ref) => ({ name: ref.pkg, resolved: "", sourceCount: 0 })),
|
|
98
|
-
};
|
|
99
|
-
// A representative (never-written) lock, so the previewed write shows a
|
|
100
|
-
// plausible shape/size. Placeholders make clear nothing was resolved.
|
|
101
|
-
const previewLock: PragmaLock = {
|
|
102
|
-
version: 1,
|
|
103
|
-
contentHash: "(resolved on execute)",
|
|
104
117
|
packs: refs.map((ref) => ({
|
|
105
118
|
name: ref.pkg,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
119
|
+
resolved: "",
|
|
120
|
+
sourceCount: 0,
|
|
121
|
+
storyCount: 0,
|
|
109
122
|
})),
|
|
110
123
|
};
|
|
111
|
-
const previewContent = serializeLock(previewLock);
|
|
112
124
|
|
|
113
125
|
return gen(function* () {
|
|
114
126
|
yield* $(
|
|
115
127
|
info(
|
|
116
128
|
refs.length > 0
|
|
117
|
-
? `Resolve and build ${refs.length}
|
|
118
|
-
: "No
|
|
129
|
+
? `Resolve and build ${refs.length} pack(s): ${refs.map((ref) => ref.source).join(", ")}`
|
|
130
|
+
: "No packs configured — the embedded pack answers store reads",
|
|
119
131
|
),
|
|
120
132
|
);
|
|
121
|
-
// The
|
|
122
|
-
|
|
133
|
+
// The project mutation, previewed (dry-run never executes it). The content
|
|
134
|
+
// is a placeholder: the real hash only exists once the build has run.
|
|
135
|
+
yield* $(
|
|
136
|
+
writeFile(activePackPath(runtime.cwd), "(the pack hash, on execute)"),
|
|
137
|
+
);
|
|
123
138
|
return data;
|
|
124
139
|
});
|
|
125
140
|
}
|
|
126
141
|
|
|
127
142
|
/**
|
|
128
|
-
* Resolve, build, and produce the
|
|
143
|
+
* Resolve, build, and produce the pointer-writing Task — or, for a preview, the
|
|
129
144
|
* network-free plan.
|
|
130
145
|
*
|
|
131
146
|
* @param runtime - The per-invocation runtime.
|
|
132
|
-
* @param
|
|
133
|
-
*
|
|
147
|
+
* @param skipInvalid - Drop sources that fail to parse (warning about each)
|
|
148
|
+
* rather than failing the whole update.
|
|
149
|
+
* @returns A Task that points the project at the built pack and returns the
|
|
150
|
+
* update result.
|
|
134
151
|
* @note Impure — resolves packages (may hit git) and builds the pack eagerly,
|
|
135
152
|
* UNLESS `runtime.mutation.preview` is set, in which case it stays offline.
|
|
136
153
|
*/
|
|
137
154
|
export async function buildUpdateTask(
|
|
138
155
|
runtime: PragmaRuntime,
|
|
139
|
-
frozen: boolean,
|
|
140
156
|
skipInvalid = false,
|
|
141
157
|
): Promise<Task<SourcesUpdateData>> {
|
|
142
158
|
if (runtime.mutation?.preview) return buildUpdatePlan(runtime);
|
|
@@ -148,37 +164,59 @@ export async function buildUpdateTask(
|
|
|
148
164
|
const verbose = runtime.globalFlags.verbose;
|
|
149
165
|
|
|
150
166
|
const layers = await runtime.loadConfig();
|
|
151
|
-
const entries = layers.config.
|
|
152
|
-
const
|
|
153
|
-
const priorContent = existing ? serializeLock(existing) : undefined;
|
|
167
|
+
const entries = layers.config.packs ?? [];
|
|
168
|
+
const priorHash = readActivePack(runtime.cwd);
|
|
154
169
|
|
|
155
|
-
const resolved: ResolvedPackage[]
|
|
170
|
+
const resolved: (ResolvedPackage & { readonly kind: PackageRef["kind"] })[] =
|
|
171
|
+
[];
|
|
156
172
|
for (const entry of entries) {
|
|
157
|
-
const ref =
|
|
173
|
+
const ref = parsePackDeclaration(entry);
|
|
158
174
|
report?.(resolveProgress(ref));
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
await resolvePackage(ref, {
|
|
162
|
-
|
|
163
|
-
frozen,
|
|
164
|
-
pinned: pinned?.resolved,
|
|
165
|
-
}),
|
|
166
|
-
);
|
|
175
|
+
resolved.push({
|
|
176
|
+
kind: ref.kind,
|
|
177
|
+
...(await resolvePackage(ref, { cwd: runtime.cwd })),
|
|
178
|
+
});
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
// Prefix precedence: core < pack < config. A resolved package's own
|
|
170
|
-
// `@prefix` declarations are harvested from its TTL and merged beneath config
|
|
171
|
-
// so the index compacts pack URIs to `pfx:Local` (the FROZEN {name,type}
|
|
172
|
-
// token contract); config still wins any clash. The merged map is persisted
|
|
173
|
-
// in the manifest, so boot reads the same names.
|
|
174
181
|
const inputs = resolved.flatMap((pkg) => pkg.sources);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
182
|
+
// The packages' own `stories/*.json`, carried into the pack verbatim (see
|
|
183
|
+
// graphpack/types.STORIES_FILE). Raw text: nothing interprets them here.
|
|
184
|
+
const stories = resolved.flatMap((pkg) => pkg.stories);
|
|
185
|
+
|
|
186
|
+
// Refuse to build an empty store (A4). A package that ships no `.ttl` (or no
|
|
187
|
+
// configured packs at all) would build a 0-triple pack whose empty
|
|
188
|
+
// `data.nq` fails the completeness gate — so the "successful" update boots to
|
|
189
|
+
// a PERMANENT `STORE_UNAVAILABLE` loop. Fail loudly here, leaving the embedded
|
|
190
|
+
// pack (or the prior build) answering reads, instead of pointing at that one.
|
|
191
|
+
if (inputs.length === 0) {
|
|
192
|
+
throw PragmaError.configError(
|
|
193
|
+
entries.length === 0
|
|
194
|
+
? "No packs are configured, so there are no sources to build a store from. The embedded pack answers reads until you add a pack."
|
|
195
|
+
: `The ${entries.length} configured pack(s) resolved 0 RDF sources (no definitions/**.ttl or data/**.ttl). Refusing to build an empty store.`,
|
|
196
|
+
{
|
|
197
|
+
recovery: cliRecovery(
|
|
198
|
+
"sources update --verbose",
|
|
199
|
+
"Add a pack that ships `.ttl` under definitions/ or data/, then re-run.",
|
|
200
|
+
),
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const prefixes = buildPackPrefixes(inputs, layers.config.prefixes);
|
|
206
|
+
|
|
207
|
+
// Warn on conflicting `@prefix` declarations across packages (A5): last-wins
|
|
208
|
+
// is silent otherwise, compacting the losing package's URIs to the wrong
|
|
209
|
+
// prefix. Display-only, so a warning (not a hard failure) is the right call.
|
|
210
|
+
for (const clash of detectPrefixClashes(inputs)) {
|
|
211
|
+
report?.(
|
|
212
|
+
`Prefix "${clash.label}:" is declared with conflicting IRIs across packages (${clash.iris.join(" vs ")}); last wins, so some entities may compact to the wrong prefix.`,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
180
216
|
report?.(`Building store from ${inputs.length} source(s)`);
|
|
181
217
|
if (verbose) for (const input of inputs) report?.(` parse ${input.path}`);
|
|
218
|
+
if (stories.length > 0)
|
|
219
|
+
report?.(`Carrying ${stories.length} package read story file(s)`);
|
|
182
220
|
|
|
183
221
|
// Build the pack. On a parse/build failure, classify it as a NAMED data error
|
|
184
222
|
// (U6) — not INTERNAL_ERROR's "please report this issue" — identifying the
|
|
@@ -186,7 +224,20 @@ export async function buildUpdateTask(
|
|
|
186
224
|
// With `--skip-invalid`, drop the unparseable sources (warning LOUDLY about
|
|
187
225
|
// each — never a silent partial graph) and build from the rest instead of
|
|
188
226
|
// failing the whole update.
|
|
189
|
-
|
|
227
|
+
// `<name>@<kind>:<resolved>` — the SAME provenance label the bundler writes
|
|
228
|
+
// for the embed, so the manifest field means one thing whoever built the pack,
|
|
229
|
+
// and `sources status` / `doctor` can still answer "which revision is my store
|
|
230
|
+
// built from?" now that no lock records it. A `file:` pack resolves to a local
|
|
231
|
+
// PATH rather than a revision, so it contributes its name alone: a machine
|
|
232
|
+
// path is not provenance, and `sources status` already lists the ref.
|
|
233
|
+
const sourceRef =
|
|
234
|
+
resolved
|
|
235
|
+
.map((pkg) =>
|
|
236
|
+
pkg.kind === "file"
|
|
237
|
+
? pkg.name
|
|
238
|
+
: `${pkg.name}@${pkg.kind}:${pkg.resolved}`,
|
|
239
|
+
)
|
|
240
|
+
.join(", ") || "embedded";
|
|
190
241
|
let built: Awaited<ReturnType<typeof buildPack>>;
|
|
191
242
|
try {
|
|
192
243
|
built = await buildPack(inputs, {
|
|
@@ -194,6 +245,7 @@ export async function buildUpdateTask(
|
|
|
194
245
|
version: VERSION,
|
|
195
246
|
sourceRef,
|
|
196
247
|
prefixes,
|
|
248
|
+
stories,
|
|
197
249
|
});
|
|
198
250
|
} catch (error) {
|
|
199
251
|
if (!skipInvalid) throw await classifySourceBuildError(error, inputs);
|
|
@@ -213,7 +265,7 @@ export async function buildUpdateTask(
|
|
|
213
265
|
`All ${inputs.length} configured source(s) failed to parse — nothing to build.`,
|
|
214
266
|
{
|
|
215
267
|
recovery: cliRecovery(
|
|
216
|
-
|
|
268
|
+
"sources update --verbose",
|
|
217
269
|
"Fix the reported sources, then re-run.",
|
|
218
270
|
),
|
|
219
271
|
},
|
|
@@ -225,11 +277,8 @@ export async function buildUpdateTask(
|
|
|
225
277
|
sourceRef,
|
|
226
278
|
// Re-harvest prefixes from only the sources that survived, so a dropped
|
|
227
279
|
// file's declarations don't skew compaction.
|
|
228
|
-
prefixes:
|
|
229
|
-
|
|
230
|
-
...harvestPrefixes(usableInputs),
|
|
231
|
-
...(layers.config.prefixes ?? {}),
|
|
232
|
-
},
|
|
280
|
+
prefixes: buildPackPrefixes(usableInputs, layers.config.prefixes),
|
|
281
|
+
stories,
|
|
233
282
|
});
|
|
234
283
|
} catch (rebuildError) {
|
|
235
284
|
throw await classifySourceBuildError(rebuildError, usableInputs);
|
|
@@ -239,38 +288,37 @@ export async function buildUpdateTask(
|
|
|
239
288
|
`${built.reused ? "Reused" : "Built"} store ${built.contentHash.slice(0, 12)}`,
|
|
240
289
|
);
|
|
241
290
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
291
|
+
// Refuse a 0-triple build (A4): non-empty sources can still parse to no
|
|
292
|
+
// triples (e.g. comment-only TTL, or a file of only `@prefix` lines). Pointing
|
|
293
|
+
// the project at an empty pack boots to the same `STORE_UNAVAILABLE` loop, so
|
|
294
|
+
// treat it as a data error rather than a silent "success". (A manifest
|
|
295
|
+
// predating the triple count is left alone — `undefined` never trips this.)
|
|
296
|
+
if (built.manifest.tripleCount === 0) {
|
|
297
|
+
throw PragmaError.configError(
|
|
298
|
+
`The configured sources parsed to 0 RDF triples, so the store would be empty. Refusing to build an empty store.`,
|
|
299
|
+
{
|
|
300
|
+
recovery: cliRecovery(
|
|
301
|
+
"sources update --verbose",
|
|
302
|
+
"Check that the package sources actually contain RDF triples, then re-run.",
|
|
303
|
+
),
|
|
304
|
+
},
|
|
305
|
+
);
|
|
306
|
+
}
|
|
258
307
|
|
|
308
|
+
const path = activePackPath(runtime.cwd);
|
|
259
309
|
const data: SourcesUpdateData = {
|
|
260
310
|
contentHash: built.contentHash,
|
|
261
311
|
reused: built.reused,
|
|
262
|
-
lockPath: path,
|
|
263
312
|
packs: resolved.map((pkg) => ({
|
|
264
313
|
name: pkg.name,
|
|
265
314
|
resolved: pkg.resolved,
|
|
266
315
|
sourceCount: pkg.sources.length,
|
|
316
|
+
storyCount: pkg.stories.length,
|
|
267
317
|
})),
|
|
268
318
|
};
|
|
269
319
|
|
|
270
320
|
const undo =
|
|
271
|
-
|
|
272
|
-
? writeFile(path, priorContent)
|
|
273
|
-
: deleteFile(path);
|
|
321
|
+
priorHash !== undefined ? writeFile(path, priorHash) : deleteFile(path);
|
|
274
322
|
|
|
275
323
|
// Install package-provided skills (U10): symlink each resolved package's
|
|
276
324
|
// `skills/*` into the installed-skills root, so `skill list` / `setup skills`
|
|
@@ -282,9 +330,9 @@ export async function buildUpdateTask(
|
|
|
282
330
|
if (skillLinks.length > 0)
|
|
283
331
|
report?.(`Installing ${skillLinks.length} skill(s)`);
|
|
284
332
|
|
|
285
|
-
report?.(`
|
|
333
|
+
report?.(`Pointing ${runtime.cwd} at pack ${built.contentHash.slice(0, 12)}`);
|
|
286
334
|
return gen(function* () {
|
|
287
|
-
yield* $(writeFile(path,
|
|
335
|
+
yield* $(writeFile(path, built.contentHash, { undo }));
|
|
288
336
|
if (skillLinks.length > 0) {
|
|
289
337
|
yield* $(mkdir(installedSkillsDir(), true));
|
|
290
338
|
for (const link of skillLinks) {
|
|
@@ -341,7 +389,7 @@ export async function classifySourceBuildError(
|
|
|
341
389
|
: "The configured package sources could not be built into a store";
|
|
342
390
|
return PragmaError.configError(`${where}: ${detail}`, {
|
|
343
391
|
recovery: cliRecovery(
|
|
344
|
-
|
|
392
|
+
"sources update --verbose",
|
|
345
393
|
"Re-run with --verbose to see each file as it parses. If a package ships malformed RDF, report it to that package's maintainer.",
|
|
346
394
|
),
|
|
347
395
|
});
|