@canonical/pragma-cli 0.35.0 → 0.37.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 +24 -20
- package/dist/pragma.conf.js +266 -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/capabilities/hints.js +1 -1
- package/dist/src/capabilities/capabilities/hints.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/create.verb.js +2 -1
- package/dist/src/capabilities/create/create.verb.js.map +1 -1
- package/dist/src/capabilities/create/createSurface.generated.js +23 -1
- package/dist/src/capabilities/create/createSurface.generated.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/checkNodeVersion.js +11 -6
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.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/isSupportedNodeVersion.js +38 -0
- package/dist/src/capabilities/doctor/checks/isSupportedNodeVersion.js.map +1 -0
- 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/setupCompletions.js +6 -2
- package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupConfig.js +4 -2
- package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupGenerator.js +156 -58
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupLsp.js +136 -38
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupMcp.js +101 -52
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -1
- package/dist/src/capabilities/setup/operations/setupSkills.js +329 -49
- 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 +165 -63
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -1
- package/dist/src/capabilities/setup/targets.js +122 -51
- package/dist/src/capabilities/setup/targets.js.map +1 -1
- package/dist/src/capabilities/shared/index.js +7 -6
- 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 +13 -2
- 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 +310 -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 +46 -24
- 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 +42 -9
- 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/runtime/graphpack/embedded/pack.generated.js +2 -3
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js +13 -6
- package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -1
- package/dist/src/kernel/runtime/graphpack/read.js +14 -9
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -1
- package/dist/src/kernel/runtime/loadSession.js +3 -1
- package/dist/src/kernel/runtime/loadSession.js.map +1 -1
- package/dist/src/kernel/runtime/probe.js +1 -1
- package/dist/src/kernel/runtime/probe.js.map +1 -1
- package/dist/src/kernel/runtime/refs/parseRef.js +17 -1
- package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -1
- package/dist/src/kernel/runtime/refs/resolve.js +9 -3
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -1
- package/dist/src/kernel/spec/emitReference.js +1 -1
- package/dist/src/kernel/spec/emitReference.js.map +1 -1
- package/package.json +24 -20
- package/pragma.conf.ts +272 -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/capabilities/hints.ts +1 -1
- package/src/capabilities/colophon/colophon.render.ts +1 -2
- package/src/capabilities/colophon/colophon.test.ts +2 -2
- package/src/capabilities/config/collectConfigShow.test.ts +1 -0
- package/src/capabilities/create/byteEquality.test.ts +28 -1
- package/src/capabilities/create/create.test.ts +1 -0
- package/src/capabilities/create/create.verb.ts +2 -1
- package/src/capabilities/create/createGrammar.test.ts +5 -2
- package/src/capabilities/create/createSurface.generated.ts +23 -1
- package/src/capabilities/create/crossCli.subprocess.test.ts +10 -3
- package/src/capabilities/create/mount.ts +3 -3
- package/src/capabilities/distribution.parity.test.ts +4 -0
- package/src/capabilities/doctor/checks/checkNodeVersion.test.ts +49 -0
- package/src/capabilities/doctor/checks/checkNodeVersion.ts +11 -7
- 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/isSupportedNodeVersion.test.ts +111 -0
- package/src/capabilities/doctor/checks/isSupportedNodeVersion.ts +34 -0
- package/src/capabilities/doctor/checks/mcpCommand.test.ts +7 -1
- 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/lazy.test.ts +26 -2
- package/src/capabilities/listLookup.shipped.exec.test.ts +340 -0
- package/src/capabilities/prompt/prompt.render.ts +2 -2
- package/src/capabilities/renderVocabularySync.test.ts +82 -0
- package/src/capabilities/resources/resources.test.ts +38 -2
- 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/setupCompletions.ts +9 -2
- package/src/capabilities/setup/operations/setupConfig.ts +7 -2
- package/src/capabilities/setup/operations/setupGenerator.ts +227 -84
- package/src/capabilities/setup/operations/setupLsp.ts +203 -38
- package/src/capabilities/setup/operations/setupMcp.ts +139 -62
- package/src/capabilities/setup/operations/setupSkills.ts +399 -60
- 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 +1126 -50
- package/src/capabilities/setup/setup.verb.ts +174 -68
- package/src/capabilities/setup/targets.ts +138 -60
- package/src/capabilities/setup/types.ts +10 -18
- package/src/capabilities/shared/index.ts +18 -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 +14 -6
- 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 +14 -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 +19 -3
- package/src/kernel/config/readConfig.test.ts +1 -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 +327 -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 +48 -25
- 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 +44 -8
- package/src/kernel/project/mcp/registerVerb.ts +20 -1
- package/src/kernel/render/prefixes.test.ts +2 -0
- 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/runtime/graphpack/embedded/pack.generated.ts +2 -3
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +1 -1
- package/src/kernel/runtime/graphpack/embedded/pack.manifest.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +14 -6
- package/src/kernel/runtime/graphpack/graphpack.test.ts +31 -5
- package/src/kernel/runtime/graphpack/read.ts +14 -12
- package/src/kernel/runtime/loadSession.ts +3 -1
- package/src/kernel/runtime/probe.ts +1 -1
- package/src/kernel/runtime/refs/parseRef.test.ts +49 -1
- package/src/kernel/runtime/refs/parseRef.ts +25 -1
- package/src/kernel/runtime/refs/resolve.ts +9 -3
- package/src/kernel/runtime/types.ts +17 -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/src/testing/helpers/runCli.test.ts +44 -0
- package/src/testing/helpers/runCli.ts +27 -3
- 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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* THE target table — the one list `setup` and `doctor` both read.
|
|
3
3
|
*
|
|
4
|
-
* Five rows, each with a
|
|
4
|
+
* Five rows, each with a scope column. This table drives the `setup <target>`
|
|
5
5
|
* sub-verbs, the wizard's choices, the `--dry-run` plan, the progress lines, the
|
|
6
6
|
* recap, the doctor rows, and each doctor row's `fix:` line. Adding a sixth
|
|
7
7
|
* target is one row here — not a new sub-verb, a new check, a new recap branch
|
|
8
8
|
* and a new fix string that four separate files have to agree about.
|
|
9
9
|
*
|
|
10
10
|
* A row owns: its identity (`id` is BOTH the sub-verb argument and the doctor
|
|
11
|
-
* row name, so `mcp` and `setup mcp` visibly share a token), which
|
|
11
|
+
* row name, so `mcp` and `setup mcp` visibly share a token), which scopes it can
|
|
12
12
|
* be installed into, how to DETECT its current state, how to PLAN a run from
|
|
13
13
|
* that detection, and how to COMPOSE the forward and removal effects. Detection
|
|
14
14
|
* runs once per invocation and feeds every reader, so setup and doctor cannot
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* doctor's), so nothing here lands on the `--help`/`__complete` fast path.
|
|
25
25
|
*/
|
|
26
26
|
|
|
27
|
+
import { dirname } from "node:path";
|
|
27
28
|
import type { Task } from "@canonical/task";
|
|
28
29
|
import { BIN_NAME } from "../../constants.js";
|
|
29
30
|
import type { PragmaRuntime } from "../../kernel/runtime/index.js";
|
|
@@ -47,7 +48,7 @@ import {
|
|
|
47
48
|
type LspDetection,
|
|
48
49
|
lspEditorNames,
|
|
49
50
|
lspSkipReason,
|
|
50
|
-
|
|
51
|
+
ownedLspEditors,
|
|
51
52
|
} from "./operations/setupLsp.js";
|
|
52
53
|
import {
|
|
53
54
|
composeMcp,
|
|
@@ -65,6 +66,8 @@ import {
|
|
|
65
66
|
ownedSkillLinks,
|
|
66
67
|
type SkillsDetection,
|
|
67
68
|
skillsSkipReason,
|
|
69
|
+
skillsSkipRemedy,
|
|
70
|
+
staleSkillLinks,
|
|
68
71
|
} from "./operations/setupSkills.js";
|
|
69
72
|
import {
|
|
70
73
|
type PlanAction,
|
|
@@ -73,7 +76,7 @@ import {
|
|
|
73
76
|
shortenPath,
|
|
74
77
|
type TargetId,
|
|
75
78
|
} from "./plan.js";
|
|
76
|
-
import type {
|
|
79
|
+
import type { Scope } from "./types.js";
|
|
77
80
|
|
|
78
81
|
/** What a target contributes to one plan row, before selection is applied. */
|
|
79
82
|
export interface TargetDraft {
|
|
@@ -98,20 +101,24 @@ export interface TargetDefinition<D> {
|
|
|
98
101
|
readonly id: TargetId;
|
|
99
102
|
/** Human title, used where a sentence needs one; the id is the row name. */
|
|
100
103
|
readonly title: string;
|
|
101
|
-
readonly
|
|
102
|
-
/** Real reads, up front, once per (target,
|
|
103
|
-
detect(rt: PragmaRuntime,
|
|
104
|
+
readonly scopes: readonly Scope[];
|
|
105
|
+
/** Real reads, up front, once per (target, scope) per invocation. */
|
|
106
|
+
detect(rt: PragmaRuntime, scope: Scope): Promise<D>;
|
|
104
107
|
/** What a forward run would do. */
|
|
105
|
-
plan(detection: D,
|
|
108
|
+
plan(detection: D, scope: Scope, roots: Roots): TargetDraft;
|
|
106
109
|
/** What a removal would do — composed from what detection says we own. */
|
|
107
|
-
removalPlan(detection: D,
|
|
110
|
+
removalPlan(detection: D, scope: Scope, roots: Roots): TargetDraft;
|
|
108
111
|
/**
|
|
109
112
|
* The forward effects. `chosen` is the row's per-child selection (MCP file
|
|
110
113
|
* paths); a row without children ignores it.
|
|
111
114
|
*/
|
|
112
115
|
compose(detection: D, chosen?: readonly string[]): Task<void>;
|
|
113
|
-
/**
|
|
114
|
-
|
|
116
|
+
/**
|
|
117
|
+
* The removal effects: forward re-assertion carrying the reversal as
|
|
118
|
+
* `undo`. `undoKey` (the row's identity) is stamped on every reversal so
|
|
119
|
+
* the undo interpreter's outcomes can be read back per row.
|
|
120
|
+
*/
|
|
121
|
+
composeRemoval(detection: D, undoKey?: string): Task<void>;
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
/** A table row with its detection type erased — how every consumer holds one. */
|
|
@@ -128,35 +135,35 @@ const defineTarget = <D>(target: TargetDefinition<D>): AnyTarget =>
|
|
|
128
135
|
const configTarget = defineTarget<ConfigDetection>({
|
|
129
136
|
id: "config",
|
|
130
137
|
title: "Global configuration",
|
|
131
|
-
|
|
138
|
+
scopes: ["global"],
|
|
132
139
|
detect: () => detectConfigFile(),
|
|
133
|
-
plan: (d,
|
|
140
|
+
plan: (d, _scope, roots) => {
|
|
134
141
|
const path = shortenPath(d.path, roots);
|
|
135
142
|
if (!d.exists) return { action: "install", detail: path };
|
|
136
143
|
return { action: "none", detail: `${path} — present` };
|
|
137
144
|
},
|
|
138
|
-
removalPlan: (d,
|
|
145
|
+
removalPlan: (d, _scope, roots) => {
|
|
139
146
|
const path = shortenPath(d.path, roots);
|
|
140
147
|
if (!d.exists) return { action: "none", detail: `${path} — absent` };
|
|
141
148
|
if (!d.isSeed) {
|
|
142
149
|
return {
|
|
143
150
|
action: "skip",
|
|
144
151
|
detail: path,
|
|
145
|
-
reason:
|
|
152
|
+
reason: `it holds your own settings, so ${path} stays`,
|
|
146
153
|
};
|
|
147
154
|
}
|
|
148
155
|
return { action: "remove", detail: path };
|
|
149
156
|
},
|
|
150
157
|
compose: (d) => composeConfigFile(d),
|
|
151
|
-
composeRemoval: (d) => composeConfigRemoval(d),
|
|
158
|
+
composeRemoval: (d, undoKey) => composeConfigRemoval(d, undoKey),
|
|
152
159
|
});
|
|
153
160
|
|
|
154
161
|
const completionsTarget = defineTarget<CompletionsDetection>({
|
|
155
162
|
id: "completions",
|
|
156
163
|
title: "Shell completions",
|
|
157
|
-
|
|
164
|
+
scopes: ["global"],
|
|
158
165
|
detect: (rt) => detectCompletions(rt.cwd),
|
|
159
|
-
plan: (d,
|
|
166
|
+
plan: (d, _scope, roots) => {
|
|
160
167
|
// Never guess a shell. Installing for the wrong one is invisible until the
|
|
161
168
|
// user presses TAB and nothing happens, so an unresolved shell is a named
|
|
162
169
|
// skip whose remedy is the one action that DOES settle it.
|
|
@@ -187,26 +194,31 @@ const completionsTarget = defineTarget<CompletionsDetection>({
|
|
|
187
194
|
};
|
|
188
195
|
}
|
|
189
196
|
const where = `${d.shell} → ${shortenPath(d.path, roots)}`;
|
|
190
|
-
|
|
197
|
+
// A no-op row says what it FOUND, not just where it looked: `no change`
|
|
198
|
+
// beside a bare path leaves the reader to guess whether the script is
|
|
199
|
+
// there and current or missing and unreachable.
|
|
200
|
+
if (d.state === "installed") {
|
|
201
|
+
return { action: "none", detail: `${where} — already up to date` };
|
|
202
|
+
}
|
|
191
203
|
return {
|
|
192
204
|
action: d.state === "stale" ? "update" : "install",
|
|
193
205
|
detail: where,
|
|
194
206
|
};
|
|
195
207
|
},
|
|
196
|
-
removalPlan: (d,
|
|
208
|
+
removalPlan: (d, _scope, roots) => {
|
|
197
209
|
if (d.path === null || d.state === "absent") {
|
|
198
210
|
return { action: "none", detail: "no script installed" };
|
|
199
211
|
}
|
|
200
212
|
return { action: "remove", detail: shortenPath(d.path, roots) };
|
|
201
213
|
},
|
|
202
214
|
compose: (d) => composeCompletions(d),
|
|
203
|
-
composeRemoval: (d) => composeCompletionsRemoval(d),
|
|
215
|
+
composeRemoval: (d, undoKey) => composeCompletionsRemoval(d, undoKey),
|
|
204
216
|
});
|
|
205
217
|
|
|
206
218
|
const lspTarget = defineTarget<LspDetection>({
|
|
207
219
|
id: "lsp",
|
|
208
220
|
title: "Terrazzo LSP extension",
|
|
209
|
-
|
|
221
|
+
scopes: ["global"],
|
|
210
222
|
detect: (rt) => detectLsp(rt.cwd),
|
|
211
223
|
plan: (d) => {
|
|
212
224
|
if (d.state === "unknown") {
|
|
@@ -225,32 +237,71 @@ const lspTarget = defineTarget<LspDetection>({
|
|
|
225
237
|
label: `${e.editor.cli} — ${e.editor.name}`,
|
|
226
238
|
action: e.installed ? ("unchanged" as const) : ("add" as const),
|
|
227
239
|
}));
|
|
240
|
+
// The detail names WHAT is being placed and WHERE — never the row's own
|
|
241
|
+
// state, which the action column already carries. `installed (VSCodium)`
|
|
242
|
+
// beside a child row reading `codium — VSCodium (unchanged)` said the
|
|
243
|
+
// editor's name twice and "nothing happens here" twice.
|
|
228
244
|
if (d.state === "installed") {
|
|
229
245
|
return {
|
|
230
246
|
action: "none",
|
|
231
|
-
detail: `
|
|
247
|
+
detail: `Terrazzo extension in ${lspEditorNames(d).join(", ")}`,
|
|
232
248
|
children,
|
|
233
249
|
};
|
|
234
250
|
}
|
|
235
251
|
const pending = d.editors.filter((e) => !e.installed);
|
|
236
252
|
return {
|
|
237
253
|
action: "install",
|
|
238
|
-
detail:
|
|
254
|
+
detail: `Terrazzo extension → ${pending
|
|
255
|
+
.map((e) => e.editor.name)
|
|
256
|
+
.join(", ")}`,
|
|
239
257
|
children,
|
|
240
258
|
};
|
|
241
259
|
},
|
|
242
|
-
removalPlan: (d) =>
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
260
|
+
removalPlan: (d) => {
|
|
261
|
+
// No editor CLI on PATH is the SAME named skip the forward plan reports:
|
|
262
|
+
// there is nothing on this machine to run an uninstall with.
|
|
263
|
+
if (d.state === "unknown") {
|
|
264
|
+
return {
|
|
265
|
+
action: "skip",
|
|
266
|
+
detail: lspSkipReason(d),
|
|
267
|
+
reason: lspSkipReason(d),
|
|
268
|
+
remedy: LSP_SKIP_REMEDY,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
// Removal is composed from what detection says we OWN — a copy that is
|
|
272
|
+
// present, whatever its version. The forward plan's version gate would let
|
|
273
|
+
// a dead pre-0.8.3 copy this command installed survive its own `--undo`.
|
|
274
|
+
const owned = ownedLspEditors(d);
|
|
275
|
+
if (owned.length === 0) {
|
|
276
|
+
return { action: "none", detail: "no editor carries the extension" };
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
action: "remove",
|
|
280
|
+
detail: `Terrazzo extension from ${owned
|
|
281
|
+
.map((e) => e.editor.name)
|
|
282
|
+
.join(", ")}`,
|
|
283
|
+
children: owned.map((e) => ({
|
|
284
|
+
key: e.editor.cli,
|
|
285
|
+
label: `${e.editor.cli} — ${e.editor.name}`,
|
|
286
|
+
action: "update" as const,
|
|
287
|
+
})),
|
|
288
|
+
};
|
|
289
|
+
},
|
|
250
290
|
compose: (d, chosen) => composeLsp(d, chosen),
|
|
251
|
-
composeRemoval: (d) => composeLspRemoval(d),
|
|
291
|
+
composeRemoval: (d, undoKey) => composeLspRemoval(d, undoKey),
|
|
252
292
|
});
|
|
253
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Why the `mcp` row has nothing to write in a scope — authored once, because
|
|
296
|
+
* `setup`'s row and `doctor`'s row are the same finding and must not word it
|
|
297
|
+
* differently. Neither sentence says "scope": the two scopes are `global` and
|
|
298
|
+
* `local project`, after the `--global` / `--local` flags that select them.
|
|
299
|
+
*/
|
|
300
|
+
export const MCP_NO_LOCATION: Record<Scope, string> = {
|
|
301
|
+
global: "no AI harness on this machine keeps a global config",
|
|
302
|
+
project: "no AI harness in this project keeps a per-project config",
|
|
303
|
+
};
|
|
304
|
+
|
|
254
305
|
/** One MCP file as a plan child: its path, the harnesses sharing it, its state. */
|
|
255
306
|
const mcpChild = (
|
|
256
307
|
d: McpDetection,
|
|
@@ -262,7 +313,7 @@ const mcpChild = (
|
|
|
262
313
|
key: group.path,
|
|
263
314
|
label: shortenPath(group.path, roots),
|
|
264
315
|
action:
|
|
265
|
-
state === "
|
|
316
|
+
state === "registered"
|
|
266
317
|
? "unchanged"
|
|
267
318
|
: state === "drifted"
|
|
268
319
|
? "update"
|
|
@@ -273,35 +324,34 @@ const mcpChild = (
|
|
|
273
324
|
const mcpTarget = defineTarget<McpDetection>({
|
|
274
325
|
id: "mcp",
|
|
275
326
|
title: "MCP server registration",
|
|
276
|
-
|
|
277
|
-
detect: (rt,
|
|
278
|
-
plan: (d,
|
|
327
|
+
scopes: ["global", "project"],
|
|
328
|
+
detect: (rt, scope) => detectMcp(rt, scope),
|
|
329
|
+
plan: (d, scope, roots) => {
|
|
279
330
|
if (d.groups.length === 0) {
|
|
280
331
|
return {
|
|
281
332
|
action: "skip",
|
|
282
|
-
detail:
|
|
283
|
-
reason:
|
|
284
|
-
band === "project"
|
|
285
|
-
? "no AI harness in this project writes a per-repository config"
|
|
286
|
-
: "no detected AI harness declares a user-level config location",
|
|
333
|
+
detail: MCP_NO_LOCATION[scope],
|
|
334
|
+
reason: MCP_NO_LOCATION[scope],
|
|
287
335
|
};
|
|
288
336
|
}
|
|
289
337
|
const children = d.groups.map((group) => mcpChild(d, group, roots));
|
|
290
338
|
const pending = children.filter((c) => c.action !== "unchanged");
|
|
291
339
|
return {
|
|
292
340
|
action: pending.length === 0 ? "none" : "update",
|
|
293
|
-
detail: `${d.groups.length} ${
|
|
341
|
+
detail: `${d.groups.length} ${
|
|
342
|
+
d.groups.length === 1 ? "config file" : "config files"
|
|
343
|
+
}`,
|
|
294
344
|
children,
|
|
295
345
|
};
|
|
296
346
|
},
|
|
297
|
-
removalPlan: (d,
|
|
347
|
+
removalPlan: (d, _scope, roots) => {
|
|
298
348
|
const owned = ownedMcpGroups(d);
|
|
299
349
|
if (owned.length === 0) {
|
|
300
350
|
return { action: "none", detail: "no entry to remove" };
|
|
301
351
|
}
|
|
302
352
|
return {
|
|
303
353
|
action: "remove",
|
|
304
|
-
detail: `${owned.length} ${owned.length === 1 ? "file" : "files"}`,
|
|
354
|
+
detail: `${owned.length} ${owned.length === 1 ? "config file" : "config files"}`,
|
|
305
355
|
children: owned.map((group) => ({
|
|
306
356
|
key: group.path,
|
|
307
357
|
label: shortenPath(group.path, roots),
|
|
@@ -311,30 +361,58 @@ const mcpTarget = defineTarget<McpDetection>({
|
|
|
311
361
|
},
|
|
312
362
|
compose: (d, chosen) =>
|
|
313
363
|
composeMcp(d, chosen ? selectedGroups(d, chosen) : d.groups),
|
|
314
|
-
composeRemoval: (d) => composeMcpRemoval(d),
|
|
364
|
+
composeRemoval: (d, undoKey) => composeMcpRemoval(d, undoKey),
|
|
315
365
|
});
|
|
316
366
|
|
|
317
367
|
const skillsTarget = defineTarget<SkillsDetection>({
|
|
318
368
|
id: "skills",
|
|
319
369
|
title: "Skill symlinks",
|
|
320
|
-
|
|
321
|
-
detect: (rt,
|
|
322
|
-
plan: (d,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
370
|
+
scopes: ["global", "project"],
|
|
371
|
+
detect: (rt, scope) => detectSkills(rt, scope),
|
|
372
|
+
plan: (d, scope, roots) => {
|
|
373
|
+
// A forward run RECONCILES: stale links this scope owns are its work too, so
|
|
374
|
+
// an orphan-only tree is actionable rather than a row that plans `none` and
|
|
375
|
+
// is then deselected into doing nothing. `staleSkillLinks` carries the
|
|
376
|
+
// absent-root safety gate, so a machine whose source root does not exist
|
|
377
|
+
// contributes no sweep and the row falls back to the honest skip.
|
|
378
|
+
const stale = staleSkillLinks(d);
|
|
379
|
+
if (!d.available && stale.length === 0) {
|
|
380
|
+
const short = shortenPath(d.sourceRoot, roots);
|
|
381
|
+
const reason = skillsSkipReason(short, scope, d.rootExists);
|
|
382
|
+
// A skip with no remedy is a dead end — this one names the command that
|
|
383
|
+
// fills the scope's source root, exactly as the completions and lsp skips
|
|
384
|
+
// beside it name theirs.
|
|
385
|
+
return {
|
|
386
|
+
action: "skip",
|
|
387
|
+
detail: reason,
|
|
388
|
+
reason,
|
|
389
|
+
remedy: skillsSkipRemedy(short, scope),
|
|
390
|
+
};
|
|
326
391
|
}
|
|
327
392
|
const dirs = d.targets.map((t) => shortenPath(t.dir, roots)).join(", ");
|
|
328
|
-
const where = `${d.skillCount} ${d.skillCount === 1 ? "skill" : "skills"} → ${d.targets.length} ${d.targets.length === 1 ? "
|
|
393
|
+
const where = `${d.skillCount} ${d.skillCount === 1 ? "skill" : "skills"} → ${d.targets.length} ${d.targets.length === 1 ? "folder" : "folders"} (${dirs})`;
|
|
394
|
+
const detail =
|
|
395
|
+
stale.length === 0
|
|
396
|
+
? where
|
|
397
|
+
: `${where}, ${stale.length} stale ${stale.length === 1 ? "link" : "links"} to remove`;
|
|
329
398
|
const pending = d.actions.filter((a) => a.action !== "skipped");
|
|
330
|
-
|
|
399
|
+
if (pending.length > 0) return { action: "link", detail };
|
|
400
|
+
// Nothing to link, but something to retire: `update` is the table's word
|
|
401
|
+
// for "this row has work that is not a fresh install".
|
|
402
|
+
if (stale.length > 0) return { action: "update", detail };
|
|
403
|
+
return { action: "none", detail };
|
|
331
404
|
},
|
|
332
|
-
removalPlan: (d,
|
|
405
|
+
removalPlan: (d, _scope, roots) => {
|
|
333
406
|
const owned = ownedSkillLinks(d);
|
|
334
407
|
if (owned.length === 0) {
|
|
335
408
|
return { action: "none", detail: "no link to remove" };
|
|
336
409
|
}
|
|
337
|
-
|
|
410
|
+
// Dedupe to the FOLDERS the links live in — `linkPath` itself is one path
|
|
411
|
+
// per link, so a Set over it deduped nothing and the removal preview
|
|
412
|
+
// printed an 18-path wall where the forward plan says `… → 2 folders`.
|
|
413
|
+
const dirs = [
|
|
414
|
+
...new Set(owned.map((a) => shortenPath(dirname(a.linkPath), roots))),
|
|
415
|
+
];
|
|
338
416
|
return {
|
|
339
417
|
action: "remove",
|
|
340
418
|
detail: `${owned.length} ${owned.length === 1 ? "link" : "links"}`,
|
|
@@ -346,7 +424,7 @@ const skillsTarget = defineTarget<SkillsDetection>({
|
|
|
346
424
|
};
|
|
347
425
|
},
|
|
348
426
|
compose: (d) => composeSkills(d),
|
|
349
|
-
composeRemoval: (d) => composeSkillsRemoval(d),
|
|
427
|
+
composeRemoval: (d, undoKey) => composeSkillsRemoval(d, undoKey),
|
|
350
428
|
});
|
|
351
429
|
|
|
352
430
|
/** THE table, in display order. */
|
|
@@ -362,6 +440,6 @@ export const TARGETS: readonly AnyTarget[] = [
|
|
|
362
440
|
export const findTarget = (id: string): AnyTarget | undefined =>
|
|
363
441
|
TARGETS.find((target) => target.id === id);
|
|
364
442
|
|
|
365
|
-
/** Whether a target can be installed into a
|
|
366
|
-
export const
|
|
367
|
-
target.
|
|
443
|
+
/** Whether a target can be installed into a scope. */
|
|
444
|
+
export const supportsScope = (target: AnyTarget, scope: Scope): boolean =>
|
|
445
|
+
target.scopes.includes(scope);
|
|
@@ -15,31 +15,23 @@ export type SetupMode =
|
|
|
15
15
|
| "mcp"
|
|
16
16
|
| "skills";
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The resolved `--scope` selection: which config band(s) a run touches.
|
|
28
|
-
* `global` is the DEFAULT — the user/home band a machine-level installer
|
|
29
|
-
* configures; `project` is the opt-in per-repository band; `both` is the
|
|
30
|
-
* explicit "run each band in one invocation". Structurally mirrors the
|
|
31
|
-
* harnesses `ScopeSelection`.
|
|
32
|
-
*/
|
|
33
|
-
export type ScopeSelection = "project" | "global" | "both";
|
|
18
|
+
// The scope types are part of the rendering vocabulary — the one module that
|
|
19
|
+
// owns both the states and the words for them. Re-exported here so setup's
|
|
20
|
+
// type surface stays complete; the definitions (and the structural pin against
|
|
21
|
+
// `@canonical/harnesses`) live with the vocabulary.
|
|
22
|
+
export type {
|
|
23
|
+
Scope,
|
|
24
|
+
ScopeSelection,
|
|
25
|
+
} from "../../kernel/render/vocabulary.js";
|
|
34
26
|
|
|
35
27
|
/**
|
|
36
28
|
* The prior state of an MCP target file, read up front by `detectMcp`:
|
|
37
|
-
* `absent` (no pragma entry yet), `
|
|
29
|
+
* `absent` (no pragma entry yet), `registered` (a matching pragma entry already
|
|
38
30
|
* present in every write — a re-run skips it), or `drifted` (a pragma entry
|
|
39
31
|
* exists but differs, so a write updates it). Mirrors the skills step's
|
|
40
32
|
* created/skipped/replaced idempotency at the file grain.
|
|
41
33
|
*/
|
|
42
|
-
export type McpTargetState = "absent" | "
|
|
34
|
+
export type McpTargetState = "absent" | "registered" | "drifted";
|
|
43
35
|
|
|
44
36
|
/**
|
|
45
37
|
* The prior on-disk state of the shell-completion script, read up front by
|
|
@@ -8,9 +8,11 @@
|
|
|
8
8
|
* that capability, and the moment something here has a single consumer again
|
|
9
9
|
* it should move back. What survives is the environment the CLI reports on but
|
|
10
10
|
* does not own — how it was installed, what the registry says about it,
|
|
11
|
-
* whether a subprocess it ran actually succeeded
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* whether a subprocess it ran actually succeeded. (The scope labels that keep
|
|
12
|
+
* `setup` and `doctor` calling the two config scopes by the same names used
|
|
13
|
+
* to live here too; they are part of the rendering vocabulary now —
|
|
14
|
+
* `kernel/render/vocabulary.ts` — beside the statuses and glyphs they are
|
|
15
|
+
* printed with.)
|
|
14
16
|
*
|
|
15
17
|
* The exec guard is exported as the pair a caller needs together: `checkExecOk`
|
|
16
18
|
* to classify a result inside a Task and `assertExecOk` to throw on one
|
|
@@ -23,10 +25,20 @@
|
|
|
23
25
|
export {
|
|
24
26
|
assertExecOk,
|
|
25
27
|
checkExecOk,
|
|
28
|
+
failPragma,
|
|
26
29
|
guardMissingBinary,
|
|
27
30
|
} from "./assertExecOk.js";
|
|
28
|
-
export {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
export type {
|
|
32
|
+
EphemeralRunner,
|
|
33
|
+
GlobalInstall,
|
|
34
|
+
InstallProbe,
|
|
35
|
+
InstallSource,
|
|
36
|
+
PackageManager,
|
|
37
|
+
} from "./packageManager.js";
|
|
38
|
+
export {
|
|
39
|
+
detectInstallSource,
|
|
40
|
+
pmUpdateCommand,
|
|
41
|
+
updateGuidance,
|
|
42
|
+
} from "./packageManager.js";
|
|
31
43
|
export type { RegistryCheckResult } from "./registry.js";
|
|
32
44
|
export { checkRegistryVersion, PRAGMA_PACKAGE } from "./registry.js";
|