@canonical/pragma-cli 0.35.0 → 0.36.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 +2 -2
- package/bundled-skills/add-standard/SKILL.md +338 -0
- package/bundled-skills/adoption-a1-styles/SKILL.md +269 -0
- package/bundled-skills/adoption-a2-components/SKILL.md +291 -0
- package/bundled-skills/adoption-a3-forms/SKILL.md +260 -0
- package/bundled-skills/anatomy-author/ANATOMY_DSL_SPEC.md +406 -0
- package/bundled-skills/anatomy-author/SKILL.md +1226 -0
- package/bundled-skills/design-auditor/SKILL.md +455 -0
- package/bundled-skills/implement-component/SKILL.md +333 -0
- package/bundled-skills/specify-component/SKILL.md +331 -0
- package/bundled-skills/specify-pattern/SKILL.md +292 -0
- package/dist/package.json +16 -15
- package/dist/pragma.conf.js +236 -34
- package/dist/pragma.conf.js.map +1 -1
- package/dist/src/bin.js +1 -1
- package/dist/src/bin.js.map +1 -1
- package/dist/src/capabilities/colophon/colophon.render.js +1 -1
- package/dist/src/capabilities/colophon/colophon.render.js.map +1 -1
- package/dist/src/capabilities/create/mount.js +4 -3
- package/dist/src/capabilities/create/mount.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +60 -4
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/checkShellCompletions.js +8 -8
- package/dist/src/capabilities/doctor/checks/checkShellCompletions.js.map +1 -1
- package/dist/src/capabilities/doctor/checks/harnessInventory.js +195 -0
- package/dist/src/capabilities/doctor/checks/harnessInventory.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/index.js +6 -6
- package/dist/src/capabilities/doctor/checks/targetHealth.js +194 -50
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -1
- package/dist/src/capabilities/doctor/doctor.render.js +43 -64
- package/dist/src/capabilities/doctor/doctor.render.js.map +1 -1
- package/dist/src/capabilities/doctor/doctor.verb.js +6 -2
- package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -1
- package/dist/src/capabilities/doctor/runChecks.js +14 -11
- package/dist/src/capabilities/doctor/runChecks.js.map +1 -1
- package/dist/src/capabilities/graph/query.render.js +2 -2
- package/dist/src/capabilities/graph/query.render.js.map +1 -1
- package/dist/src/capabilities/info/collectInfo.js +8 -2
- package/dist/src/capabilities/info/collectInfo.js.map +1 -1
- package/dist/src/capabilities/info/info.render.js +6 -2
- package/dist/src/capabilities/info/info.render.js.map +1 -1
- package/dist/src/capabilities/prompt/prompt.render.js +2 -2
- package/dist/src/capabilities/prompt/prompt.render.js.map +1 -1
- package/dist/src/capabilities/setup/buildPlan.js +43 -39
- package/dist/src/capabilities/setup/buildPlan.js.map +1 -1
- package/dist/src/capabilities/setup/mode.js +2 -2
- package/dist/src/capabilities/setup/operations/index.js +4 -4
- package/dist/src/capabilities/setup/operations/index.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupGenerator.js +92 -45
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupLsp.js +88 -36
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupMcp.js +97 -51
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupSkills.js +325 -47
- package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -1
- package/dist/src/capabilities/setup/plan.js.map +1 -1
- package/dist/src/capabilities/setup/plan.render.js +144 -66
- package/dist/src/capabilities/setup/plan.render.js.map +1 -1
- package/dist/src/capabilities/setup/setup.render.js +1 -1
- package/dist/src/capabilities/setup/setup.verb.js +86 -33
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/setup/targets.js +110 -45
- package/dist/src/capabilities/setup/targets.js.map +1 -1
- package/dist/src/capabilities/shared/index.js +6 -5
- package/dist/src/capabilities/shared/index.js.map +1 -1
- package/dist/src/capabilities/shared/packageManager.js +300 -54
- package/dist/src/capabilities/shared/packageManager.js.map +1 -1
- package/dist/src/capabilities/skill/discover.js +97 -11
- package/dist/src/capabilities/skill/discover.js.map +1 -1
- package/dist/src/capabilities/skill/render.js +2 -2
- package/dist/src/capabilities/skill/render.js.map +1 -1
- package/dist/src/capabilities/sources/installSkills.js +145 -3
- package/dist/src/capabilities/sources/installSkills.js.map +1 -1
- package/dist/src/capabilities/sources/runUpdate.js +68 -2
- package/dist/src/capabilities/sources/runUpdate.js.map +1 -1
- package/dist/src/capabilities/sources/update.verb.js +3 -3
- package/dist/src/capabilities/sources/update.verb.js.map +1 -1
- package/dist/src/capabilities/upgrade/runUpgrade.js +43 -7
- package/dist/src/capabilities/upgrade/runUpgrade.js.map +1 -1
- package/dist/src/capabilities/upgrade/upgrade.render.js +10 -2
- package/dist/src/capabilities/upgrade/upgrade.render.js.map +1 -1
- package/dist/src/constants.js +6 -1
- package/dist/src/constants.js.map +1 -1
- package/dist/src/kernel/index.js +11 -2
- package/dist/src/kernel/index.js.map +1 -1
- package/dist/src/kernel/interactivity.js +68 -0
- package/dist/src/kernel/interactivity.js.map +1 -0
- package/dist/src/kernel/packs/renderPack.js +3 -3
- package/dist/src/kernel/packs/renderPack.js.map +1 -1
- package/dist/src/kernel/packs/resolveEntity.js +63 -12
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -1
- package/dist/src/kernel/packs/runBodies.js +57 -4
- package/dist/src/kernel/packs/runBodies.js.map +1 -1
- package/dist/src/kernel/packs/schema.js +54 -2
- package/dist/src/kernel/packs/schema.js.map +1 -1
- package/dist/src/kernel/packs/sparql/applyFilters.js +104 -5
- package/dist/src/kernel/packs/sparql/applyFilters.js.map +1 -1
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +306 -43
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -1
- package/dist/src/kernel/packs/types.js.map +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js +1 -1
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -1
- package/dist/src/kernel/project/cli/dispatch.js +23 -23
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -1
- package/dist/src/kernel/project/cli/globalFlags.js +4 -1
- package/dist/src/kernel/project/cli/globalFlags.js.map +1 -1
- package/dist/src/kernel/project/cli/helpFormat.js +1 -2
- package/dist/src/kernel/project/cli/helpFormat.js.map +1 -1
- package/dist/src/kernel/project/cli/rootHelp.js +34 -4
- package/dist/src/kernel/project/cli/rootHelp.js.map +1 -1
- package/dist/src/kernel/project/mcp/registerVerb.js +16 -1
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -1
- package/dist/src/kernel/render/renderers.js +1 -1
- package/dist/src/kernel/render/style.js +29 -9
- package/dist/src/kernel/render/style.js.map +1 -1
- package/dist/src/kernel/render/vocabulary.js +174 -0
- package/dist/src/kernel/render/vocabulary.js.map +1 -0
- package/dist/src/kernel/spec/emitReference.js +1 -1
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/package.json +16 -15
- package/pragma.conf.ts +241 -34
- package/src/bin.ts +8 -1
- package/src/capabilities/block.parity.test.ts +25 -11
- package/src/capabilities/block.shipped.exec.test.ts +282 -0
- package/src/capabilities/block.tierRank.exec.test.ts +300 -0
- package/src/capabilities/colophon/colophon.render.ts +1 -2
- package/src/capabilities/colophon/colophon.test.ts +2 -2
- package/src/capabilities/create/createGrammar.test.ts +1 -1
- package/src/capabilities/create/mount.ts +3 -3
- package/src/capabilities/distribution.parity.test.ts +4 -0
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +69 -4
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +6 -4
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +8 -8
- package/src/capabilities/doctor/checks/harnessInventory.test.ts +219 -0
- package/src/capabilities/doctor/checks/harnessInventory.ts +298 -0
- package/src/capabilities/doctor/checks/index.ts +6 -6
- package/src/capabilities/doctor/checks/targetHealth.ts +229 -59
- package/src/capabilities/doctor/doctor.render.test.ts +108 -32
- package/src/capabilities/doctor/doctor.render.ts +56 -80
- package/src/capabilities/doctor/doctor.test.ts +247 -35
- package/src/capabilities/doctor/doctor.verb.ts +7 -2
- package/src/capabilities/doctor/runChecks.ts +14 -11
- package/src/capabilities/doctor/types.ts +15 -24
- package/src/capabilities/emptyRecovery.test.ts +10 -2
- package/src/capabilities/graph/query.render.ts +2 -2
- package/src/capabilities/info/collectInfo.ts +8 -1
- package/src/capabilities/info/info.render.ts +6 -2
- package/src/capabilities/info/info.test.ts +37 -1
- package/src/capabilities/info/types.ts +10 -2
- package/src/capabilities/prompt/prompt.render.ts +2 -2
- package/src/capabilities/renderVocabularySync.test.ts +82 -0
- package/src/capabilities/scopeTypeSync.test.ts +29 -15
- package/src/capabilities/setup/buildPlan.ts +45 -41
- package/src/capabilities/setup/index.ts +1 -1
- package/src/capabilities/setup/mode.ts +2 -2
- package/src/capabilities/setup/operations/index.ts +6 -1
- package/src/capabilities/setup/operations/setupGenerator.ts +144 -70
- package/src/capabilities/setup/operations/setupLsp.ts +129 -37
- package/src/capabilities/setup/operations/setupMcp.ts +132 -61
- package/src/capabilities/setup/operations/setupSkills.ts +392 -58
- package/src/capabilities/setup/plan.render.ts +171 -76
- package/src/capabilities/setup/plan.ts +17 -12
- package/src/capabilities/setup/setup.mcp.correctness.test.ts +9 -9
- package/src/capabilities/setup/setup.render.test.ts +50 -36
- package/src/capabilities/setup/setup.render.ts +1 -1
- package/src/capabilities/setup/setup.test.ts +881 -50
- package/src/capabilities/setup/setup.verb.ts +91 -33
- package/src/capabilities/setup/targets.ts +120 -52
- package/src/capabilities/setup/types.ts +10 -18
- package/src/capabilities/shared/index.ts +17 -6
- package/src/capabilities/shared/packageManager.test.ts +421 -6
- package/src/capabilities/shared/packageManager.ts +394 -59
- package/src/capabilities/skill/bundledSkills.test.ts +347 -0
- package/src/capabilities/skill/discover.ts +100 -11
- package/src/capabilities/skill/render.ts +2 -2
- package/src/capabilities/skill/skill.test.ts +17 -4
- package/src/capabilities/sources/installSkills.ts +181 -3
- package/src/capabilities/sources/runUpdate.ts +78 -2
- package/src/capabilities/sources/sources.test.ts +228 -0
- package/src/capabilities/sources/update.verb.ts +3 -3
- package/src/capabilities/surface.test.ts +2 -2
- package/src/capabilities/upgrade/runUpgrade.ts +45 -6
- package/src/capabilities/upgrade/types.ts +10 -2
- package/src/capabilities/upgrade/upgrade.render.ts +9 -2
- package/src/capabilities/upgrade/upgrade.test.ts +72 -0
- package/src/constants.ts +6 -1
- package/src/identity.test.ts +18 -5
- package/src/kernel/completion/entitySource.test.ts +15 -2
- package/src/kernel/completion/safety.test.ts +16 -9
- package/src/kernel/config/defaults.test.ts +2 -1
- package/src/kernel/index.ts +11 -2
- package/src/kernel/interactivity.test.ts +76 -0
- package/src/kernel/interactivity.ts +69 -0
- package/src/kernel/packs/compile.test.ts +92 -0
- package/src/kernel/packs/renderPack.ts +3 -3
- package/src/kernel/packs/resolveEntity.test.ts +75 -14
- package/src/kernel/packs/resolveEntity.ts +88 -24
- package/src/kernel/packs/runBodies.ts +84 -19
- package/src/kernel/packs/schema.ts +60 -4
- package/src/kernel/packs/sparql/applyFilters.ts +125 -4
- package/src/kernel/packs/sparql/buildLookupQuery.test.ts +290 -0
- package/src/kernel/packs/sparql/buildLookupQuery.ts +323 -45
- package/src/kernel/packs/toolDescription.test.ts +35 -1
- package/src/kernel/packs/types.ts +125 -2
- package/src/kernel/project/cli/buildProgram.test.ts +73 -2
- package/src/kernel/project/cli/buildProgram.ts +8 -1
- package/src/kernel/project/cli/dispatch.test.ts +5 -4
- package/src/kernel/project/cli/dispatch.ts +25 -24
- package/src/kernel/project/cli/globalFlags.ts +4 -1
- package/src/kernel/project/cli/helpFormat.ts +1 -2
- package/src/kernel/project/cli/rootHelp.ts +36 -3
- package/src/kernel/project/mcp/registerVerb.ts +20 -1
- package/src/kernel/render/renderers.ts +1 -1
- package/src/kernel/render/style.ts +32 -9
- package/src/kernel/render/vocabulary.ts +276 -0
- package/src/kernel/spec/emitReference.ts +1 -1
- package/src/kernel/spec/types.ts +35 -6
- package/src/testing/PARITY_GAPS.ts +9 -3
- package/src/testing/behavioral/docExamples.test.ts +4 -2
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +110 -7
- package/src/testing/behavioral/journeys.firstInstall.test.ts +7 -2
- package/src/testing/behavioral/journeys.packageStories.test.ts +6 -3
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +26 -1
- package/src/testing/eval/cases/readNouns.ts +245 -9
- package/src/testing/fixtures/blockGraph.ts +28 -13
- package/src/testing/fixtures/graph/canonical.ts +95 -12
- package/dist/src/capabilities/shared/bands.js +0 -16
- package/dist/src/capabilities/shared/bands.js.map +0 -1
- package/src/capabilities/shared/bands.ts +0 -16
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Detection ALSO reads each group's existing config (via `readMcpConfigFrom`,
|
|
13
13
|
* FOR REAL up front) and classifies every group as `absent` (no pragma entry
|
|
14
|
-
* yet), `
|
|
14
|
+
* yet), `registered` (the pragma entry already matches what we'd write), or
|
|
15
15
|
* `drifted` (a pragma entry exists but differs). The wizard shows that prior
|
|
16
|
-
* state in each row and DEFAULT-DESELECTS the already-`
|
|
16
|
+
* state in each row and DEFAULT-DESELECTS the already-`registered` files; the
|
|
17
17
|
* write itself stays idempotent (a re-merge of the identical entry is
|
|
18
18
|
* byte-for-byte), so a re-run is a no-op the recap reports as "unchanged" — the
|
|
19
19
|
* same state-awareness `setup skills` has always had.
|
|
@@ -38,78 +38,101 @@ const MCP_SERVE_ARGV = ["mcp", "serve"];
|
|
|
38
38
|
/**
|
|
39
39
|
* The pragma MCP server entry we register — the SINGLE source of truth both the
|
|
40
40
|
* classifier (does the existing entry match this?) and the writer (`composeMcp`)
|
|
41
|
-
* consume, so "already
|
|
41
|
+
* consume, so "already registered" means byte-for-byte what a write would emit.
|
|
42
42
|
*
|
|
43
|
-
* The entry is
|
|
43
|
+
* The entry is SCOPE-shaped: a project-scope entry records the project root as
|
|
44
44
|
* `cwd` (that binding is the point of a per-repo registration), while a
|
|
45
|
-
* global-
|
|
45
|
+
* global-scope entry OMITS `cwd` entirely — a per-user server must not be
|
|
46
46
|
* pinned to whatever directory `setup mcp --global` happened to run from
|
|
47
47
|
* (observed: a global registration from `~/Downloads` permanently served
|
|
48
48
|
* `~/Downloads`, and re-running from repo B "repaired" it to repo B,
|
|
49
|
-
* ping-ponging the machine
|
|
49
|
+
* ping-ponging the machine scope between projects). The per-harness
|
|
50
50
|
* serializers already omit an undefined `cwd`, and the matcher treats an
|
|
51
51
|
* omitted controlled field as must-be-absent, so a stale global entry still
|
|
52
52
|
* carrying a `cwd` classifies as `drifted` and converges on the next write.
|
|
53
53
|
*
|
|
54
|
-
* @param cwd - The project root (recorded only on project-
|
|
55
|
-
* @param
|
|
54
|
+
* @param cwd - The project root (recorded only on project-scope entries).
|
|
55
|
+
* @param scope - The config scope the entry is written to.
|
|
56
56
|
* @returns The pragma {@link McpServerConfig}.
|
|
57
57
|
*/
|
|
58
|
-
export function pragmaMcpEntry(cwd,
|
|
59
|
-
return
|
|
58
|
+
export function pragmaMcpEntry(cwd, scope) {
|
|
59
|
+
return scope === "project"
|
|
60
60
|
? { command: MCP_SERVER_NAME, args: [...MCP_SERVE_ARGV], cwd }
|
|
61
61
|
: { command: MCP_SERVER_NAME, args: [...MCP_SERVE_ARGV] };
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
|
-
* Classify
|
|
65
|
-
*
|
|
66
|
-
* already
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* per-harness serializer would emit for the group's
|
|
64
|
+
* Classify ONE write against its on-disk config: `absent` when the file carries
|
|
65
|
+
* no pragma entry under this write's `mcpKey`, `registered` when the entry
|
|
66
|
+
* already matches what this write would emit, `drifted` when one is there and
|
|
67
|
+
* differs. Reads the file for real via `readMcpConfigFrom` (which reads only
|
|
68
|
+
* this write's key), and matches the raw entry against what THAT write's
|
|
69
|
+
* per-harness serializer would emit for the group's SCOPE (`mcpEntryMatches`
|
|
70
70
|
* compares the serializer's controlled fields — so a global entry still
|
|
71
71
|
* pinning a `cwd` reads as drifted — and ignores extra keys a harness or user
|
|
72
72
|
* added, so we never churn a file we did not author).
|
|
73
73
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* The write, not the file, is the unit that can be classified honestly: a
|
|
75
|
+
* shared `.vscode/mcp.json` holds VS Code's `servers` and Cline's `mcpServers`
|
|
76
|
+
* as two independent entries, and "the file" has no single state when one is
|
|
77
|
+
* current and the other is missing.
|
|
78
|
+
*
|
|
79
|
+
* @param write - The resolved config target to inspect.
|
|
80
|
+
* @param want - The canonical pragma entry for the group's scope.
|
|
76
81
|
* @param harnessesApi - The dynamically imported harnesses module.
|
|
77
82
|
* @param runTask - The node Task interpreter.
|
|
83
|
+
* @returns This write's {@link McpTargetState}.
|
|
84
|
+
* @note Impure — reads the write's config file.
|
|
85
|
+
*/
|
|
86
|
+
async function classifyWrite(write, want, harnessesApi, runTask) {
|
|
87
|
+
const servers = await runTask(harnessesApi.readMcpConfigFrom(write));
|
|
88
|
+
const existing = servers[MCP_SERVER_NAME];
|
|
89
|
+
if (existing === undefined)
|
|
90
|
+
return "absent";
|
|
91
|
+
return harnessesApi.mcpEntryMatches(existing, want, write.serializeEntry)
|
|
92
|
+
? "registered"
|
|
93
|
+
: "drifted";
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* The state of a whole FILE, aggregated from its writes: `absent` when no write
|
|
97
|
+
* carries the entry, `registered` when every write already carries a matching
|
|
98
|
+
* one, `drifted` otherwise. This is the rule the write side needs — a file is
|
|
99
|
+
* rewritten unless it is `registered` everywhere — and it is deliberately the
|
|
100
|
+
* only place the per-write states are collapsed, so nothing else re-derives it.
|
|
101
|
+
*
|
|
102
|
+
* @param states - Each write's own state, in the group's write order.
|
|
78
103
|
* @returns The group's {@link McpTargetState}.
|
|
79
|
-
* @note Impure — reads each write's config file.
|
|
80
104
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
let matching = 0;
|
|
84
|
-
for (const write of group.writes) {
|
|
85
|
-
const servers = await runTask(harnessesApi.readMcpConfigFrom(write));
|
|
86
|
-
const existing = servers[MCP_SERVER_NAME];
|
|
87
|
-
if (existing === undefined)
|
|
88
|
-
continue;
|
|
89
|
-
present += 1;
|
|
90
|
-
if (harnessesApi.mcpEntryMatches(existing, want, write.serializeEntry)) {
|
|
91
|
-
matching += 1;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (present === 0)
|
|
105
|
+
const aggregateMcpStates = (states) => {
|
|
106
|
+
if (states.every((state) => state === "absent"))
|
|
95
107
|
return "absent";
|
|
96
|
-
if (
|
|
97
|
-
return "
|
|
108
|
+
if (states.every((state) => state === "registered"))
|
|
109
|
+
return "registered";
|
|
98
110
|
return "drifted";
|
|
99
|
-
}
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* The key one write's state is recorded under: the file it lands in AND the
|
|
114
|
+
* `mcpKey` it owns there. `(path, mcpKey)` is exactly the write-dedup key
|
|
115
|
+
* `groupConfigTargets` builds its `writes` from, so the map has one entry per
|
|
116
|
+
* write and no two harnesses sharing a file can collide. The separator is NUL
|
|
117
|
+
* because a config path may legally contain everything else.
|
|
118
|
+
*
|
|
119
|
+
* @param write - The resolved config target.
|
|
120
|
+
* @returns Its lookup key in {@link McpDetection.stateByWrite}.
|
|
121
|
+
*/
|
|
122
|
+
const mcpWriteKey = (write) => `${write.path}\u0000${write.mcpKey}`;
|
|
100
123
|
/**
|
|
101
124
|
* Detect the AI harnesses present in the project (real reads, up front),
|
|
102
125
|
* resolve+dedup their config targets for the chosen scope, AND read each
|
|
103
|
-
* group's existing config to classify it `absent`/`
|
|
104
|
-
* the wizard can show prior state and default-deselect already-`
|
|
126
|
+
* group's existing config to classify it `absent`/`registered`/`drifted` — so
|
|
127
|
+
* the wizard can show prior state and default-deselect already-`registered`
|
|
105
128
|
* files.
|
|
106
129
|
*
|
|
107
130
|
* @param rt - The per-invocation runtime.
|
|
108
|
-
* @param
|
|
109
|
-
* @returns The
|
|
131
|
+
* @param scope - The scope being planned (global or project).
|
|
132
|
+
* @returns The scope's target groups, their prior states, + the config writer.
|
|
110
133
|
* @note Impure — reads the filesystem via `detectHarnesses` + `readMcpConfigFrom`.
|
|
111
134
|
*/
|
|
112
|
-
export async function detectMcp(rt,
|
|
135
|
+
export async function detectMcp(rt, scope) {
|
|
113
136
|
const cwd = rt.cwd;
|
|
114
137
|
const [{ detectHarnesses, groupTargetsForScope, mcpEntryMatches, readMcpConfigFrom, readPlatformEnv, removeMcpConfigFrom, writeMcpConfigTargets, }, { runTask },] = await Promise.all([
|
|
115
138
|
import("@canonical/harnesses"),
|
|
@@ -117,20 +140,31 @@ export async function detectMcp(rt, band) {
|
|
|
117
140
|
]);
|
|
118
141
|
const platform = readPlatformEnv();
|
|
119
142
|
const detected = await runTask(detectHarnesses(cwd, platform));
|
|
120
|
-
const groups = groupTargetsForScope(detected, cwd,
|
|
143
|
+
const groups = groupTargetsForScope(detected, cwd, scope, platform);
|
|
121
144
|
// Read each group's existing config (for real, up front) so the recap/preview
|
|
122
145
|
// and the default selection reflect true prior state — the same discipline
|
|
123
146
|
// `detectSkills` uses for its per-link create/skip/replace decision. The
|
|
124
|
-
// wanted entry is
|
|
125
|
-
// per group, not once.
|
|
147
|
+
// wanted entry is SCOPE-shaped (a global entry omits `cwd`), so it is built
|
|
148
|
+
// per group, not once. Each WRITE is classified and kept; the file's state is
|
|
149
|
+
// their aggregate, so the coarse view is derived from the fine one rather
|
|
150
|
+
// than measured separately.
|
|
126
151
|
const stateByPath = new Map();
|
|
152
|
+
const stateByWrite = new Map();
|
|
127
153
|
await Promise.all(groups.map(async (group) => {
|
|
128
|
-
const
|
|
129
|
-
|
|
154
|
+
const want = pragmaMcpEntry(cwd, group.scope);
|
|
155
|
+
const classified = await Promise.all(group.writes.map(async (write) => ({
|
|
156
|
+
write,
|
|
157
|
+
state: await classifyWrite(write, want, { readMcpConfigFrom, mcpEntryMatches }, runTask),
|
|
158
|
+
})));
|
|
159
|
+
for (const { write, state } of classified) {
|
|
160
|
+
stateByWrite.set(mcpWriteKey(write), state);
|
|
161
|
+
}
|
|
162
|
+
stateByPath.set(group.path, aggregateMcpStates(classified.map((c) => c.state)));
|
|
130
163
|
}));
|
|
131
164
|
return {
|
|
132
165
|
groups,
|
|
133
166
|
stateByPath,
|
|
167
|
+
stateByWrite,
|
|
134
168
|
cwd,
|
|
135
169
|
platform,
|
|
136
170
|
writeMcpConfigTargets,
|
|
@@ -144,13 +178,25 @@ export async function detectMcp(rt, band) {
|
|
|
144
178
|
export function mcpGroupState(d, path) {
|
|
145
179
|
return d.stateByPath.get(path) ?? "absent";
|
|
146
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* The prior state of ONE write — the state of the single harness key it owns,
|
|
183
|
+
* not of the file it shares. Defaults to `absent` for an unknown write, the
|
|
184
|
+
* same way {@link mcpGroupState} does for an unknown path.
|
|
185
|
+
*
|
|
186
|
+
* @param d - The detection gathered up front.
|
|
187
|
+
* @param write - One of a group's {@link ConfigTarget} writes.
|
|
188
|
+
* @returns That write's {@link McpTargetState}.
|
|
189
|
+
*/
|
|
190
|
+
export function mcpWriteState(d, write) {
|
|
191
|
+
return d.stateByWrite.get(mcpWriteKey(write)) ?? "absent";
|
|
192
|
+
}
|
|
147
193
|
/** The target groups the user selected (by path), or all when none recorded. */
|
|
148
194
|
export function selectedGroups(d, selectedPaths) {
|
|
149
195
|
return d.groups.filter((g) => selectedPaths.includes(g.path));
|
|
150
196
|
}
|
|
151
197
|
/**
|
|
152
198
|
* Compose the per-target config writes for the SELECTED groups (pure —
|
|
153
|
-
* re-runnable; builds ABSOLUTE config paths itself). An already-`
|
|
199
|
+
* re-runnable; builds ABSOLUTE config paths itself). An already-`registered`
|
|
154
200
|
* group composes NOTHING: the entry on disk is byte-for-byte what a write would
|
|
155
201
|
* emit, so re-writing it would only move an mtime. Removal no longer depends on
|
|
156
202
|
* the forward plan having written something ({@link composeMcpRemoval}), which
|
|
@@ -166,13 +212,13 @@ export function composeMcp(d, groups) {
|
|
|
166
212
|
// Re-runnable combinators (NOT a single-use `gen`): `execute` interprets the
|
|
167
213
|
// task twice (preview + perform). One combined write per file keeps a shared
|
|
168
214
|
// file (VS Code + Cline) a single read-modify-write — dry-run safe. The
|
|
169
|
-
// written entry is
|
|
170
|
-
const pending = groups.filter((group) => mcpGroupState(d, group.path) !== "
|
|
215
|
+
// written entry is SCOPE-shaped per group (a global entry omits `cwd`).
|
|
216
|
+
const pending = groups.filter((group) => mcpGroupState(d, group.path) !== "registered");
|
|
171
217
|
return sequence_(pending.map((group) => d.writeMcpConfigTargets(group.writes, MCP_SERVER_NAME, pragmaMcpEntry(d.cwd, group.scope))));
|
|
172
218
|
}
|
|
173
219
|
/**
|
|
174
|
-
* The groups this
|
|
175
|
-
* pragma entry as present (`
|
|
220
|
+
* The groups this scope OWNS right now — every file where detection classifies a
|
|
221
|
+
* pragma entry as present (`registered` or `drifted`). Removal acts on exactly
|
|
176
222
|
* this set, so a file that never carried the entry is never rewritten and a
|
|
177
223
|
* foreign server in a file that does is never touched.
|
|
178
224
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupMcp.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupMcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"setupMcp.js","sourceRoot":"","sources":["../../../../../src/capabilities/setup/operations/setupMcp.ts"],"names":[],"mappings":"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"}
|