@canonical/pragma-cli 0.33.0 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/pragma +0 -0
- package/package.json +18 -15
- package/pragma.conf.ts +664 -0
- package/src/bin.ts +13 -4
- package/src/capabilities/block.parity.test.ts +250 -0
- package/src/capabilities/capabilities/capabilities.render.ts +3 -2
- package/src/capabilities/capabilities/capabilities.verb.ts +31 -13
- package/src/capabilities/capabilities/catalog.ts +18 -10
- package/src/capabilities/capabilities/hints.ts +13 -19
- package/src/capabilities/colophon/collectColophon.ts +34 -19
- package/src/capabilities/colophon/colophon.verb.ts +8 -4
- package/src/capabilities/colophon/types.ts +16 -7
- package/src/capabilities/config/collectConfigShow.test.ts +57 -0
- package/src/capabilities/config/collectConfigShow.ts +41 -4
- package/src/capabilities/config/fields.ts +0 -27
- package/src/capabilities/config/set.verb.ts +7 -3
- package/src/capabilities/config/show.render.test.ts +77 -5
- package/src/capabilities/config/show.render.ts +7 -12
- package/src/capabilities/config/show.verb.ts +4 -3
- package/src/capabilities/config/types.ts +8 -0
- package/src/capabilities/create/byteEquality.test.ts +78 -100
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +52 -15
- package/src/capabilities/create/constants.ts +75 -0
- package/src/capabilities/create/create.mcp.test.ts +2 -2
- package/src/capabilities/create/create.test.ts +162 -15
- package/src/capabilities/create/create.verb.ts +140 -69
- package/src/capabilities/create/index.ts +2 -10
- package/src/capabilities/create/pickGenerator.ts +34 -28
- package/src/capabilities/create/templates.embedded.generated.ts +4 -29
- package/src/capabilities/create/types.ts +10 -6
- package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
- package/src/capabilities/distribution.test.ts +120 -0
- package/src/capabilities/distribution.ts +59 -0
- package/src/capabilities/doctor/checks/checkConfigFile.ts +6 -5
- package/src/capabilities/doctor/checks/checkKeStore.ts +2 -2
- package/src/capabilities/doctor/checks/checkMcpConfigured.ts +7 -6
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +79 -45
- package/src/capabilities/doctor/checks/checkPragmaVersion.ts +3 -2
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +61 -11
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +63 -23
- package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +3 -2
- package/src/capabilities/doctor/doctor.render.test.ts +6 -6
- package/src/capabilities/doctor/doctor.render.ts +2 -1
- package/src/capabilities/doctor/doctor.test.ts +37 -8
- package/src/capabilities/doctor/doctor.verb.ts +6 -2
- package/src/capabilities/doctor/runChecks.ts +5 -5
- package/src/capabilities/doctor/types.ts +1 -1
- package/src/capabilities/emptyRecovery.test.ts +32 -15
- package/src/capabilities/graph/inspect.verb.ts +3 -2
- package/src/capabilities/graph/query.verb.ts +3 -2
- package/src/capabilities/graph/runQuery.ts +8 -5
- package/src/capabilities/index.ts +22 -18
- package/src/capabilities/info/collectInfo.ts +10 -6
- package/src/capabilities/info/info.render.ts +3 -2
- package/src/capabilities/info/info.verb.ts +3 -2
- package/src/capabilities/lazy.test.ts +93 -2
- package/src/capabilities/ontology/verbs.ts +21 -21
- package/src/capabilities/prompt/prompt.test.ts +12 -6
- package/src/capabilities/prompt/verbs.ts +24 -11
- package/src/capabilities/resources/provider.ts +30 -11
- package/src/capabilities/resources/resources.test.ts +85 -29
- package/src/capabilities/setup/operations/setupGenerator.ts +16 -9
- package/src/capabilities/setup/operations/setupMcp.ts +2 -2
- package/src/capabilities/setup/operations/setupSkills.ts +3 -3
- package/src/capabilities/setup/setup.verb.ts +12 -5
- package/src/capabilities/setup/shell.ts +29 -3
- package/src/capabilities/skill/discover.ts +11 -5
- package/src/capabilities/skill/render.ts +4 -5
- package/src/capabilities/skill/verbs.ts +7 -7
- package/src/capabilities/sources/collectStatus.ts +55 -50
- package/src/capabilities/sources/index.ts +1 -1
- package/src/capabilities/sources/installSkills.ts +2 -2
- package/src/capabilities/sources/runUpdate.ts +113 -122
- package/src/capabilities/sources/sources.test.ts +111 -117
- package/src/capabilities/sources/status.render.test.ts +53 -24
- package/src/capabilities/sources/status.render.ts +24 -29
- package/src/capabilities/sources/status.verb.ts +15 -8
- package/src/capabilities/sources/types.ts +18 -25
- package/src/capabilities/sources/update.render.ts +9 -2
- package/src/capabilities/sources/update.verb.ts +12 -23
- package/src/capabilities/surface.test.ts +33 -10
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/upgrade.verb.ts +7 -3
- package/src/constants.test.ts +8 -6
- package/src/constants.ts +47 -21
- package/src/identity.test.ts +333 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +5 -2
- package/src/kernel/completion/emitScripts.test.ts +1 -1
- package/src/kernel/completion/emitScripts.ts +4 -2
- package/src/kernel/completion/entitySource.test.ts +185 -41
- package/src/kernel/completion/entitySource.ts +117 -107
- package/src/kernel/completion/model.test.ts +1 -1
- package/src/kernel/completion/model.ts +11 -0
- package/src/kernel/completion/safety.test.ts +82 -36
- package/src/kernel/completion/shellDrive.test.ts +592 -0
- package/src/kernel/completion/templates/fish.ts +28 -6
- package/src/kernel/completion/types.ts +3 -3
- package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +1 -1
- package/src/kernel/config/defaults.test.ts +85 -0
- package/src/kernel/config/defaults.ts +12 -23
- package/src/kernel/config/evaluateProjectConfig.ts +2 -3
- package/src/kernel/config/findProjectConfig.ts +4 -3
- package/src/kernel/config/firstRun.ts +12 -5
- package/src/kernel/config/globalConfig.ts +2 -2
- package/src/kernel/config/index.ts +4 -5
- package/src/kernel/config/paths.ts +17 -17
- package/src/kernel/config/readConfig.test.ts +242 -6
- package/src/kernel/config/readConfig.ts +8 -8
- package/src/kernel/config/schema.test.ts +50 -0
- package/src/kernel/config/schema.ts +97 -10
- package/src/kernel/config/types.ts +73 -19
- package/src/kernel/copy.test.ts +453 -0
- package/src/kernel/error/PragmaError.test.ts +1 -1
- package/src/kernel/error/constants.ts +3 -2
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +22 -45
- package/src/kernel/error/recovery.ts +22 -27
- package/src/kernel/error/types.ts +5 -4
- package/src/kernel/packs/collect.test.ts +195 -11
- package/src/kernel/packs/collect.ts +213 -58
- package/src/kernel/packs/compile.test.ts +163 -7
- package/src/kernel/packs/compile.ts +15 -12
- package/src/kernel/packs/disclosure.test.ts +5 -2
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +11 -10
- package/src/kernel/packs/graphqlSource.test.ts +6 -3
- package/src/kernel/packs/iri.ts +5 -7
- package/src/kernel/packs/renderPack.ts +5 -3
- package/src/kernel/packs/resolveEntity.ts +21 -17
- package/src/kernel/packs/runBodies.ts +15 -14
- package/src/kernel/packs/schema.ts +96 -10
- package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
- package/src/kernel/packs/sparql/runSelect.ts +73 -34
- package/src/kernel/packs/toolDescription.test.ts +10 -2
- package/src/kernel/packs/types.ts +39 -4
- package/src/kernel/packs/uniqueness.ts +4 -4
- package/src/kernel/project/cli/buildProgram.test.ts +9 -4
- package/src/kernel/project/cli/dispatch.test.ts +67 -0
- package/src/kernel/project/cli/dispatch.ts +34 -12
- package/src/kernel/project/cli/helpFormat.ts +1 -1
- package/src/kernel/project/cli/rootHelp.ts +105 -105
- package/src/kernel/project/mcp/buildServer.ts +11 -6
- package/src/kernel/project/mcp/instructions.ts +11 -6
- package/src/kernel/project/mcp/parity.test.ts +39 -1
- package/src/kernel/project/mcp/prompts/prompts.test.ts +120 -5
- package/src/kernel/project/mcp/prompts/provider.ts +22 -8
- package/src/kernel/project/mcp/prompts/source.ts +68 -67
- package/src/kernel/project/mcp/registerVerb.ts +25 -6
- package/src/kernel/project/mcp/serve.ts +11 -3
- package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
- package/src/kernel/render/disclosure.ts +4 -2
- package/src/kernel/render/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +1 -1
- package/src/kernel/runtime/graphpack/build.ts +29 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +46 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +52 -17
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -5
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -3
- package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +37 -11
- package/src/kernel/runtime/graphpack/graphpack.test.ts +205 -5
- package/src/kernel/runtime/graphpack/hash.ts +3 -2
- package/src/kernel/runtime/graphpack/index.ts +1 -1
- package/src/kernel/runtime/graphpack/manifest.ts +114 -12
- package/src/kernel/runtime/graphpack/read.ts +4 -9
- package/src/kernel/runtime/graphpack/schemas.ts +74 -0
- package/src/kernel/runtime/graphpack/stories.ts +84 -0
- package/src/kernel/runtime/graphpack/types.ts +61 -48
- package/src/kernel/runtime/paths.ts +64 -15
- package/src/kernel/runtime/probe.test.ts +8 -4
- package/src/kernel/runtime/readEntity.ts +6 -5
- package/src/kernel/runtime/refs/gitOps.ts +1 -19
- package/src/kernel/runtime/refs/parseRef.ts +7 -7
- package/src/kernel/runtime/refs/resolve.ts +78 -62
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +9 -8
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +22 -19
- package/src/kernel/spec/emitReference.test.ts +3 -3
- package/src/kernel/spec/emitReference.ts +144 -11
- package/src/kernel/spec/emitSurface.ts +9 -5
- package/src/kernel/spec/surfaceConformance.test.ts +2 -2
- package/src/kernel/spec/surfaceConformance.ts +8 -0
- package/src/kernel/spec/types.ts +29 -9
- package/src/kernel/spec/validate.ts +2 -1
- package/src/kernel/vocabulary.test.ts +164 -0
- package/src/kernel/vocabulary.ts +146 -0
- package/src/testing/PARITY_GAPS.ts +8 -2
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/completion.test.ts +19 -6
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +4 -3
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +1 -1
- package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
- package/src/testing/behavioral/harness.foundation.test.ts +14 -5
- package/src/testing/behavioral/journeys.cli.test.ts +116 -75
- package/src/testing/behavioral/journeys.defaultPack.test.ts +82 -176
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +9 -6
- package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
- package/src/testing/behavioral/liveReadSurface.ts +4 -3
- package/src/testing/behavioral/mcpSurface.test.ts +9 -4
- package/src/testing/behavioral/staleCommands.test.ts +10 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +7 -7
- package/src/testing/eval/cases/assembly.ts +13 -6
- package/src/testing/eval/cases/effectful.ts +25 -13
- package/src/testing/eval/cases/readNouns.ts +22 -20
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/fixtureCapability.ts +45 -1
- package/src/testing/fixtures/graph/canonical.ts +6 -3
- package/src/testing/fixtures/graph/defaultPack.ts +6 -5
- package/src/testing/fixtures/graph/owlExport.ts +7 -5
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- package/src/testing/helpers/packRuntime.ts +2 -3
- package/src/testing/helpers/projectCli.ts +2 -1
- package/src/testing/helpers/projectMcp.ts +6 -0
- package/src/testing/perf/budgets.test.ts +4 -0
- package/src/testing/perf/budgets.ts +22 -7
- package/src/testing/perf/globalSetup.ts +121 -6
- package/src/types.ts +2 -2
- package/src/capabilities/block/blockList.test.ts +0 -79
- package/src/capabilities/block/blockList.verb.ts +0 -163
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -166
- package/src/capabilities/block/parity.test.ts +0 -187
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- package/src/capabilities/modifier/index.ts +0 -15
- package/src/capabilities/modifier/pack.ts +0 -64
- package/src/capabilities/standard/index.ts +0 -18
- package/src/capabilities/standard/pack.ts +0 -128
- package/src/capabilities/tier/index.ts +0 -19
- package/src/capabilities/tier/lookup.render.test.ts +0 -72
- package/src/capabilities/tier/lookup.render.ts +0 -59
- package/src/capabilities/tier/lookup.test.ts +0 -83
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -87
- package/src/capabilities/token/addConfig.render.ts +0 -27
- package/src/capabilities/token/addConfig.test.ts +0 -62
- package/src/capabilities/token/addConfig.verb.ts +0 -40
- package/src/capabilities/token/index.ts +0 -19
- package/src/capabilities/token/pack.ts +0 -58
- package/src/capabilities/token/runAddConfig.ts +0 -95
- package/src/kernel/completion/bashDrive.test.ts +0 -73
- package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
- package/src/kernel/runtime/lock.ts +0 -90
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
* Formatters for `skill list` and `skill lookup`.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { BIN_NAME } from "../../constants.js";
|
|
5
6
|
import type { Formatters } from "../../kernel/spec/types.js";
|
|
6
7
|
import type { DiscoveredSkill } from "./discover.js";
|
|
7
8
|
import type { SkillLookup } from "./verbs.js";
|
|
8
9
|
|
|
9
|
-
/** Empty-state guidance (U5) — where skills come from now that
|
|
10
|
-
const EMPTY_PLAIN =
|
|
11
|
-
|
|
12
|
-
const EMPTY_LLM =
|
|
13
|
-
"## Skills (0)\n\nNo skills found. Skills come from installed design-system packages — add one to the project config, run `pragma sources update`, then `pragma setup skills`.";
|
|
10
|
+
/** Empty-state guidance (U5) — where skills come from now that packs ship them. */
|
|
11
|
+
const EMPTY_PLAIN = `No skills found.\nSkills come from design-system packs — add one to your config's packs, run \`${BIN_NAME} sources update\`, then \`${BIN_NAME} setup skills\`.`;
|
|
12
|
+
const EMPTY_LLM = `## Skills (0)\n\nNo skills found. Skills come from design-system packs — add one to the project config's packs, run \`${BIN_NAME} sources update\`, then \`${BIN_NAME} setup skills\`.`;
|
|
14
13
|
|
|
15
14
|
export const skillListFormatters: Formatters<DiscoveredSkill[]> = {
|
|
16
15
|
plain: (skills) =>
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
import { readFileSync } from "node:fs";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
+
import { BIN_NAME } from "../../constants.js";
|
|
11
12
|
import { PragmaError } from "../../kernel/error/PragmaError.js";
|
|
13
|
+
import { cliRecovery } from "../../kernel/error/recovery.js";
|
|
12
14
|
import { suggestNames } from "../../kernel/project/cli/suggestNames.js";
|
|
13
15
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
14
16
|
import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
@@ -26,7 +28,7 @@ const listVerb: VerbSpec<Record<string, unknown>, DiscoveredSkill[]> = {
|
|
|
26
28
|
summary: "List discovered skills (SKILL.md files under the skill roots).",
|
|
27
29
|
params: [],
|
|
28
30
|
output: { formatters: skillListFormatters },
|
|
29
|
-
examples: [{ cmd:
|
|
31
|
+
examples: [{ cmd: `${BIN_NAME} skill list` }],
|
|
30
32
|
capability: {
|
|
31
33
|
needsStore: false,
|
|
32
34
|
mutates: false,
|
|
@@ -53,7 +55,7 @@ const lookupVerb: VerbSpec<Record<string, unknown>, SkillLookup> = {
|
|
|
53
55
|
},
|
|
54
56
|
],
|
|
55
57
|
output: { formatters: skillLookupFormatters },
|
|
56
|
-
examples: [{ cmd:
|
|
58
|
+
examples: [{ cmd: `${BIN_NAME} skill lookup docx` }],
|
|
57
59
|
capability: {
|
|
58
60
|
needsStore: false,
|
|
59
61
|
mutates: false,
|
|
@@ -74,11 +76,9 @@ const lookupVerb: VerbSpec<Record<string, unknown>, SkillLookup> = {
|
|
|
74
76
|
name,
|
|
75
77
|
skills.map((skill) => skill.name),
|
|
76
78
|
),
|
|
77
|
-
recovery: {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
mcp: { tool: "skill_list" },
|
|
81
|
-
},
|
|
79
|
+
recovery: cliRecovery("skill list", "List discovered skills.", {
|
|
80
|
+
tool: "skill_list",
|
|
81
|
+
}),
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
return { ...match, instructions: readInstructions(match.sourcePath) };
|
|
@@ -1,35 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Collect the `sources status` payload — storeless.
|
|
3
3
|
*
|
|
4
|
-
* Reports the store's readiness without booting it
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
4
|
+
* Reports the store's readiness without booting it. The `store` field IS the
|
|
5
|
+
* boot decision ({@link resolveSources}) — status never re-derives which pack
|
|
6
|
+
* answers reads, so it can never disagree with what the next read actually
|
|
7
|
+
* loads. Everything else is provenance read straight off that pack's manifest
|
|
8
|
+
* (a plain `JSON.parse`, no store, no oxigraph). This is the capability that
|
|
9
|
+
* must stay off the store factory (the storeless-guarantee spy covers it). It
|
|
10
|
+
* absorbs the v1 `info store` summary.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
13
14
|
import { join } from "node:path";
|
|
14
|
-
import type {
|
|
15
|
+
import type { PackDeclaration } from "../../kernel/config/types.js";
|
|
16
|
+
import { embeddedManifest } from "../../kernel/runtime/graphpack/embedded.js";
|
|
15
17
|
import { readManifest } from "../../kernel/runtime/graphpack/manifest.js";
|
|
16
18
|
import { INDEX_FILE } from "../../kernel/runtime/graphpack/types.js";
|
|
17
|
-
import {
|
|
18
|
-
import { packDir } from "../../kernel/runtime/paths.js";
|
|
19
|
+
import { resolveSources } from "../../kernel/runtime/resolveSources.js";
|
|
19
20
|
import type { PragmaRuntime } from "../../kernel/runtime/types.js";
|
|
20
|
-
import type {
|
|
21
|
-
SourceStaleness,
|
|
22
|
-
SourceStatusEntry,
|
|
23
|
-
SourcesStatusData,
|
|
24
|
-
} from "./types.js";
|
|
21
|
+
import type { SourcesStatusData } from "./types.js";
|
|
25
22
|
|
|
26
|
-
const entryName = (entry:
|
|
23
|
+
const entryName = (entry: PackDeclaration): string =>
|
|
27
24
|
typeof entry === "string" ? entry : entry.name;
|
|
28
|
-
const entrySource = (entry:
|
|
25
|
+
const entrySource = (entry: PackDeclaration): string =>
|
|
29
26
|
typeof entry === "string" ? entry : (entry.source ?? entry.name);
|
|
30
27
|
|
|
31
28
|
/**
|
|
32
|
-
* The distinct-abox entity count from a
|
|
29
|
+
* The distinct-abox entity count from a built pack's index.json (storeless).
|
|
33
30
|
*
|
|
34
31
|
* Only reached for LEGACY packs whose manifest predates the persisted
|
|
35
32
|
* `entityCount` (A10) — a current pack's count is read straight from the
|
|
@@ -59,44 +56,52 @@ function indexEntityCount(dir: string): number | null {
|
|
|
59
56
|
*
|
|
60
57
|
* @param runtime - The per-invocation runtime.
|
|
61
58
|
* @returns The storeless status payload.
|
|
62
|
-
* @note Impure — reads config, the
|
|
59
|
+
* @note Impure — reads config, the active-pack pointer, and the pack cache.
|
|
63
60
|
*/
|
|
64
61
|
export async function collectStatus(
|
|
65
62
|
runtime: PragmaRuntime,
|
|
66
63
|
): Promise<SourcesStatusData> {
|
|
67
64
|
const layers = await runtime.loadConfig();
|
|
68
|
-
const
|
|
69
|
-
|
|
65
|
+
const sources = (layers.config.packs ?? []).map((entry) => ({
|
|
66
|
+
name: entryName(entry),
|
|
67
|
+
ref: entrySource(entry),
|
|
68
|
+
}));
|
|
69
|
+
const decision = resolveSources(layers, runtime.cwd);
|
|
70
|
+
const base = { cwd: runtime.cwd, sources };
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
} else if (!lockEntry || lockEntry.source !== ref) {
|
|
83
|
-
staleness = "config-drift";
|
|
84
|
-
} else {
|
|
85
|
-
staleness = "up-to-date";
|
|
72
|
+
switch (decision.kind) {
|
|
73
|
+
case "embedded": {
|
|
74
|
+
const manifest = embeddedManifest();
|
|
75
|
+
return {
|
|
76
|
+
...base,
|
|
77
|
+
store: "embedded",
|
|
78
|
+
contentHash: manifest.contentHash,
|
|
79
|
+
sourceRef: manifest.sourceRef,
|
|
80
|
+
builtAt: manifest.createdAt,
|
|
81
|
+
entityCount: manifest.entityCount ?? null,
|
|
82
|
+
};
|
|
86
83
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
84
|
+
case "pack": {
|
|
85
|
+
const manifest = readManifest(decision.dir);
|
|
86
|
+
return {
|
|
87
|
+
...base,
|
|
88
|
+
store: "built",
|
|
89
|
+
contentHash: decision.contentHash,
|
|
90
|
+
sourceRef: manifest?.sourceRef ?? null,
|
|
91
|
+
builtAt: manifest?.createdAt ?? null,
|
|
92
|
+
// Prefer the manifest's persisted count (no index parse); a legacy pack
|
|
93
|
+
// without it falls back to counting the index's abox subjects (A10).
|
|
94
|
+
entityCount: manifest?.entityCount ?? indexEntityCount(decision.dir),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
case "unavailable":
|
|
98
|
+
return {
|
|
99
|
+
...base,
|
|
100
|
+
store: "unavailable",
|
|
101
|
+
contentHash: null,
|
|
102
|
+
sourceRef: null,
|
|
103
|
+
builtAt: null,
|
|
104
|
+
entityCount: null,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
102
107
|
}
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Design-system packages ship a top-level `skills/<name>/SKILL.md`, but skill
|
|
5
5
|
* discovery only scans the project root and the installed-skills root — never a
|
|
6
6
|
* resolved package's clone/dir. So `sources update` INSTALLS each package's
|
|
7
|
-
* skills into the installed-skills root (`$XDG_DATA_HOME
|
|
7
|
+
* skills into the installed-skills root (`$XDG_DATA_HOME/<bin>/skills`) as
|
|
8
8
|
* symlinks, exactly the root `discoverSkills` already reads. Precedence is
|
|
9
|
-
* preserved (a project
|
|
9
|
+
* preserved (a project `.<bin>/skills` entry still wins — it is discovered
|
|
10
10
|
* first), and the update Task stays reversible (each created link carries an
|
|
11
11
|
* unlink undo).
|
|
12
12
|
*
|
|
@@ -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,20 +30,14 @@ 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 {
|
|
@@ -67,17 +62,43 @@ const CORE_PREFIXES: Readonly<Record<string, string>> = {
|
|
|
67
62
|
dcterms: "http://purl.org/dc/terms/",
|
|
68
63
|
};
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
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
|
+
}
|
|
72
93
|
|
|
73
94
|
/**
|
|
74
95
|
* Build the NETWORK-FREE preview plan for `sources update`.
|
|
75
96
|
*
|
|
76
97
|
* A plan-only Task: it reads the config to list the refs a real update would
|
|
77
|
-
* resolve and build, then models the
|
|
78
|
-
* as effects the dry-run interpreter can describe WITHOUT running them.
|
|
79
|
-
* no compile, no cache write — so `--dry-run` and an MCP plan-first call
|
|
80
|
-
* 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
|
|
81
102
|
* never resolved.
|
|
82
103
|
*
|
|
83
104
|
* @param runtime - The per-invocation runtime.
|
|
@@ -87,57 +108,51 @@ async function buildUpdatePlan(
|
|
|
87
108
|
runtime: PragmaRuntime,
|
|
88
109
|
): Promise<Task<SourcesUpdateData>> {
|
|
89
110
|
const layers = await runtime.loadConfig();
|
|
90
|
-
const entries = layers.config.
|
|
91
|
-
const refs = entries.map(
|
|
92
|
-
const path = lockPath(runtime.cwd);
|
|
111
|
+
const entries = layers.config.packs ?? [];
|
|
112
|
+
const refs = entries.map(parsePackDeclaration);
|
|
93
113
|
|
|
94
114
|
const data: SourcesUpdateData = {
|
|
95
115
|
contentHash: "",
|
|
96
116
|
reused: false,
|
|
97
|
-
lockPath: path,
|
|
98
|
-
packs: refs.map((ref) => ({ name: ref.pkg, resolved: "", sourceCount: 0 })),
|
|
99
|
-
};
|
|
100
|
-
// A representative (never-written) lock, so the previewed write shows a
|
|
101
|
-
// plausible shape/size. Placeholders make clear nothing was resolved.
|
|
102
|
-
const previewLock: PragmaLock = {
|
|
103
|
-
version: 1,
|
|
104
|
-
contentHash: "(resolved on execute)",
|
|
105
117
|
packs: refs.map((ref) => ({
|
|
106
118
|
name: ref.pkg,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
119
|
+
resolved: "",
|
|
120
|
+
sourceCount: 0,
|
|
121
|
+
storyCount: 0,
|
|
110
122
|
})),
|
|
111
123
|
};
|
|
112
|
-
const previewContent = serializeLock(previewLock);
|
|
113
124
|
|
|
114
125
|
return gen(function* () {
|
|
115
126
|
yield* $(
|
|
116
127
|
info(
|
|
117
128
|
refs.length > 0
|
|
118
|
-
? `Resolve and build ${refs.length}
|
|
119
|
-
: "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",
|
|
120
131
|
),
|
|
121
132
|
);
|
|
122
|
-
// The
|
|
123
|
-
|
|
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
|
+
);
|
|
124
138
|
return data;
|
|
125
139
|
});
|
|
126
140
|
}
|
|
127
141
|
|
|
128
142
|
/**
|
|
129
|
-
* Resolve, build, and produce the
|
|
143
|
+
* Resolve, build, and produce the pointer-writing Task — or, for a preview, the
|
|
130
144
|
* network-free plan.
|
|
131
145
|
*
|
|
132
146
|
* @param runtime - The per-invocation runtime.
|
|
133
|
-
* @param
|
|
134
|
-
*
|
|
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.
|
|
135
151
|
* @note Impure — resolves packages (may hit git) and builds the pack eagerly,
|
|
136
152
|
* UNLESS `runtime.mutation.preview` is set, in which case it stays offline.
|
|
137
153
|
*/
|
|
138
154
|
export async function buildUpdateTask(
|
|
139
155
|
runtime: PragmaRuntime,
|
|
140
|
-
frozen: boolean,
|
|
141
156
|
skipInvalid = false,
|
|
142
157
|
): Promise<Task<SourcesUpdateData>> {
|
|
143
158
|
if (runtime.mutation?.preview) return buildUpdatePlan(runtime);
|
|
@@ -149,55 +164,45 @@ export async function buildUpdateTask(
|
|
|
149
164
|
const verbose = runtime.globalFlags.verbose;
|
|
150
165
|
|
|
151
166
|
const layers = await runtime.loadConfig();
|
|
152
|
-
const entries = layers.config.
|
|
153
|
-
const
|
|
154
|
-
const priorContent = existing ? serializeLock(existing) : undefined;
|
|
167
|
+
const entries = layers.config.packs ?? [];
|
|
168
|
+
const priorHash = readActivePack(runtime.cwd);
|
|
155
169
|
|
|
156
|
-
const resolved: ResolvedPackage[]
|
|
170
|
+
const resolved: (ResolvedPackage & { readonly kind: PackageRef["kind"] })[] =
|
|
171
|
+
[];
|
|
157
172
|
for (const entry of entries) {
|
|
158
|
-
const ref =
|
|
173
|
+
const ref = parsePackDeclaration(entry);
|
|
159
174
|
report?.(resolveProgress(ref));
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
await resolvePackage(ref, {
|
|
163
|
-
|
|
164
|
-
frozen,
|
|
165
|
-
pinned: pinned?.resolved,
|
|
166
|
-
}),
|
|
167
|
-
);
|
|
175
|
+
resolved.push({
|
|
176
|
+
kind: ref.kind,
|
|
177
|
+
...(await resolvePackage(ref, { cwd: runtime.cwd })),
|
|
178
|
+
});
|
|
168
179
|
}
|
|
169
180
|
|
|
170
|
-
// Prefix precedence: core < pack < config. A resolved package's own
|
|
171
|
-
// `@prefix` declarations are harvested from its TTL and merged beneath config
|
|
172
|
-
// so the index compacts pack URIs to `pfx:Local` (the FROZEN {name,type}
|
|
173
|
-
// token contract); config still wins any clash. The merged map is persisted
|
|
174
|
-
// in the manifest, so boot reads the same names.
|
|
175
181
|
const inputs = resolved.flatMap((pkg) => pkg.sources);
|
|
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);
|
|
176
185
|
|
|
177
|
-
// Refuse to
|
|
178
|
-
// configured
|
|
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
|
|
179
188
|
// `data.nq` fails the completeness gate — so the "successful" update boots to
|
|
180
189
|
// a PERMANENT `STORE_UNAVAILABLE` loop. Fail loudly here, leaving the embedded
|
|
181
|
-
//
|
|
190
|
+
// pack (or the prior build) answering reads, instead of pointing at that one.
|
|
182
191
|
if (inputs.length === 0) {
|
|
183
192
|
throw PragmaError.configError(
|
|
184
193
|
entries.length === 0
|
|
185
|
-
? "No
|
|
186
|
-
: `The ${entries.length} configured
|
|
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.`,
|
|
187
196
|
{
|
|
188
197
|
recovery: cliRecovery(
|
|
189
|
-
|
|
190
|
-
"Add a
|
|
198
|
+
"sources update --verbose",
|
|
199
|
+
"Add a pack that ships `.ttl` under definitions/ or data/, then re-run.",
|
|
191
200
|
),
|
|
192
201
|
},
|
|
193
202
|
);
|
|
194
203
|
}
|
|
195
204
|
|
|
196
|
-
const prefixes =
|
|
197
|
-
...CORE_PREFIXES,
|
|
198
|
-
...harvestPrefixes(inputs),
|
|
199
|
-
...(layers.config.prefixes ?? {}),
|
|
200
|
-
};
|
|
205
|
+
const prefixes = buildPackPrefixes(inputs, layers.config.prefixes);
|
|
201
206
|
|
|
202
207
|
// Warn on conflicting `@prefix` declarations across packages (A5): last-wins
|
|
203
208
|
// is silent otherwise, compacting the losing package's URIs to the wrong
|
|
@@ -210,6 +215,8 @@ export async function buildUpdateTask(
|
|
|
210
215
|
|
|
211
216
|
report?.(`Building store from ${inputs.length} source(s)`);
|
|
212
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)`);
|
|
213
220
|
|
|
214
221
|
// Build the pack. On a parse/build failure, classify it as a NAMED data error
|
|
215
222
|
// (U6) — not INTERNAL_ERROR's "please report this issue" — identifying the
|
|
@@ -217,7 +224,20 @@ export async function buildUpdateTask(
|
|
|
217
224
|
// With `--skip-invalid`, drop the unparseable sources (warning LOUDLY about
|
|
218
225
|
// each — never a silent partial graph) and build from the rest instead of
|
|
219
226
|
// failing the whole update.
|
|
220
|
-
|
|
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";
|
|
221
241
|
let built: Awaited<ReturnType<typeof buildPack>>;
|
|
222
242
|
try {
|
|
223
243
|
built = await buildPack(inputs, {
|
|
@@ -225,6 +245,7 @@ export async function buildUpdateTask(
|
|
|
225
245
|
version: VERSION,
|
|
226
246
|
sourceRef,
|
|
227
247
|
prefixes,
|
|
248
|
+
stories,
|
|
228
249
|
});
|
|
229
250
|
} catch (error) {
|
|
230
251
|
if (!skipInvalid) throw await classifySourceBuildError(error, inputs);
|
|
@@ -244,7 +265,7 @@ export async function buildUpdateTask(
|
|
|
244
265
|
`All ${inputs.length} configured source(s) failed to parse — nothing to build.`,
|
|
245
266
|
{
|
|
246
267
|
recovery: cliRecovery(
|
|
247
|
-
|
|
268
|
+
"sources update --verbose",
|
|
248
269
|
"Fix the reported sources, then re-run.",
|
|
249
270
|
),
|
|
250
271
|
},
|
|
@@ -256,11 +277,8 @@ export async function buildUpdateTask(
|
|
|
256
277
|
sourceRef,
|
|
257
278
|
// Re-harvest prefixes from only the sources that survived, so a dropped
|
|
258
279
|
// file's declarations don't skew compaction.
|
|
259
|
-
prefixes:
|
|
260
|
-
|
|
261
|
-
...harvestPrefixes(usableInputs),
|
|
262
|
-
...(layers.config.prefixes ?? {}),
|
|
263
|
-
},
|
|
280
|
+
prefixes: buildPackPrefixes(usableInputs, layers.config.prefixes),
|
|
281
|
+
stories,
|
|
264
282
|
});
|
|
265
283
|
} catch (rebuildError) {
|
|
266
284
|
throw await classifySourceBuildError(rebuildError, usableInputs);
|
|
@@ -270,64 +288,37 @@ export async function buildUpdateTask(
|
|
|
270
288
|
`${built.reused ? "Reused" : "Built"} store ${built.contentHash.slice(0, 12)}`,
|
|
271
289
|
);
|
|
272
290
|
|
|
273
|
-
// Refuse
|
|
274
|
-
//
|
|
275
|
-
//
|
|
276
|
-
// as a data error rather than a silent "success". (A manifest
|
|
277
|
-
// triple count is left alone — `undefined` never trips this.)
|
|
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.)
|
|
278
296
|
if (built.manifest.tripleCount === 0) {
|
|
279
297
|
throw PragmaError.configError(
|
|
280
|
-
`The configured sources parsed to 0 RDF triples, so the store would be empty. Refusing to
|
|
298
|
+
`The configured sources parsed to 0 RDF triples, so the store would be empty. Refusing to build an empty store.`,
|
|
281
299
|
{
|
|
282
300
|
recovery: cliRecovery(
|
|
283
|
-
|
|
301
|
+
"sources update --verbose",
|
|
284
302
|
"Check that the package sources actually contain RDF triples, then re-run.",
|
|
285
303
|
),
|
|
286
304
|
},
|
|
287
305
|
);
|
|
288
306
|
}
|
|
289
307
|
|
|
290
|
-
const
|
|
291
|
-
const lock: PragmaLock = {
|
|
292
|
-
version: 1,
|
|
293
|
-
contentHash: built.contentHash,
|
|
294
|
-
packs: resolved.map((pkg) => {
|
|
295
|
-
const prev = existing?.packs.find((entry) => entry.name === pkg.name);
|
|
296
|
-
// Preserve the prior `resolvedAt` when nothing actually changed — under
|
|
297
|
-
// --frozen (re-pinned to the same revision) AND on a plain re-run that
|
|
298
|
-
// resolves the IDENTICAL revision from the same source. Otherwise every
|
|
299
|
-
// `sources update` stamped a fresh timestamp and rewrote the lock, dirtying
|
|
300
|
-
// the git tree on a no-op run (L1). A moved revision still restamps.
|
|
301
|
-
const reproducible =
|
|
302
|
-
prev !== undefined &&
|
|
303
|
-
(frozen ||
|
|
304
|
-
(prev.resolved === pkg.resolved && prev.source === pkg.source));
|
|
305
|
-
return {
|
|
306
|
-
name: pkg.name,
|
|
307
|
-
source: pkg.source,
|
|
308
|
-
resolved: pkg.resolved,
|
|
309
|
-
resolvedAt: reproducible && prev ? prev.resolvedAt : now,
|
|
310
|
-
};
|
|
311
|
-
}),
|
|
312
|
-
};
|
|
313
|
-
const newContent = serializeLock(lock);
|
|
314
|
-
const path = lockPath(runtime.cwd);
|
|
315
|
-
|
|
308
|
+
const path = activePackPath(runtime.cwd);
|
|
316
309
|
const data: SourcesUpdateData = {
|
|
317
310
|
contentHash: built.contentHash,
|
|
318
311
|
reused: built.reused,
|
|
319
|
-
lockPath: path,
|
|
320
312
|
packs: resolved.map((pkg) => ({
|
|
321
313
|
name: pkg.name,
|
|
322
314
|
resolved: pkg.resolved,
|
|
323
315
|
sourceCount: pkg.sources.length,
|
|
316
|
+
storyCount: pkg.stories.length,
|
|
324
317
|
})),
|
|
325
318
|
};
|
|
326
319
|
|
|
327
320
|
const undo =
|
|
328
|
-
|
|
329
|
-
? writeFile(path, priorContent)
|
|
330
|
-
: deleteFile(path);
|
|
321
|
+
priorHash !== undefined ? writeFile(path, priorHash) : deleteFile(path);
|
|
331
322
|
|
|
332
323
|
// Install package-provided skills (U10): symlink each resolved package's
|
|
333
324
|
// `skills/*` into the installed-skills root, so `skill list` / `setup skills`
|
|
@@ -339,9 +330,9 @@ export async function buildUpdateTask(
|
|
|
339
330
|
if (skillLinks.length > 0)
|
|
340
331
|
report?.(`Installing ${skillLinks.length} skill(s)`);
|
|
341
332
|
|
|
342
|
-
report?.(`
|
|
333
|
+
report?.(`Pointing ${runtime.cwd} at pack ${built.contentHash.slice(0, 12)}`);
|
|
343
334
|
return gen(function* () {
|
|
344
|
-
yield* $(writeFile(path,
|
|
335
|
+
yield* $(writeFile(path, built.contentHash, { undo }));
|
|
345
336
|
if (skillLinks.length > 0) {
|
|
346
337
|
yield* $(mkdir(installedSkillsDir(), true));
|
|
347
338
|
for (const link of skillLinks) {
|
|
@@ -398,7 +389,7 @@ export async function classifySourceBuildError(
|
|
|
398
389
|
: "The configured package sources could not be built into a store";
|
|
399
390
|
return PragmaError.configError(`${where}: ${detail}`, {
|
|
400
391
|
recovery: cliRecovery(
|
|
401
|
-
|
|
392
|
+
"sources update --verbose",
|
|
402
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.",
|
|
403
394
|
),
|
|
404
395
|
});
|