@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The
|
|
2
|
+
* The scoped doctor rows, derived from the setup target table.
|
|
3
3
|
*
|
|
4
|
-
* `doctor` and `setup` are the SAME LIST. Every
|
|
4
|
+
* `doctor` and `setup` are the SAME LIST. Every scoped row here carries a
|
|
5
5
|
* target id verbatim — `completions`, not "Shell completions"; `mcp`, not "MCP
|
|
6
6
|
* configured" — because the row name IS the fix command's argument, and a user
|
|
7
7
|
* who reads `✗ mcp` beside `fix: pragma setup mcp` can see that they are the
|
|
@@ -11,23 +11,32 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Every row's detection comes from the target table's own `detect`, so the two
|
|
13
13
|
* surfaces cannot disagree about what they looked at, and every `fix:` is
|
|
14
|
-
* derived from the row's id and
|
|
14
|
+
* derived from the row's id and scope rather than authored per check.
|
|
15
15
|
*
|
|
16
|
-
* Doctor's
|
|
16
|
+
* Doctor's UNSCOPED environment checks (Node version, the CLI's own version,
|
|
17
17
|
* pack refs, the store) diagnose things setup cannot install and stay outside
|
|
18
18
|
* this list.
|
|
19
|
+
*
|
|
20
|
+
* ONE scoped row is not a target: `harnesses`, the per-scope inventory. It is an
|
|
21
|
+
* inventory of the machine the targets are measured against, not a target that
|
|
22
|
+
* can be set up, so it deliberately carries no `fix:` and can never be `fail`
|
|
23
|
+
* or `available` — see {@link inventoryChecks}. The bijection between the other
|
|
24
|
+
* rows and the setup table is untouched: `harnesses` is not a `TargetId`, and
|
|
25
|
+
* nothing derives a command from it.
|
|
19
26
|
*/
|
|
20
27
|
import { MCP_SERVER_NAME } from "../../../constants.js";
|
|
21
28
|
import { detectionFailure, detectTargets, resolveRoots, } from "../../setup/buildPlan.js";
|
|
22
|
-
import { lspEditorNames, lspSkipReason, mcpGroupState, skillsSkipReason, } from "../../setup/operations/index.js";
|
|
29
|
+
import { lspEditorNames, lspSkipReason, mcpGroupState, mcpWriteState, skillsSkipReason, skillsSkipRemedy, } from "../../setup/operations/index.js";
|
|
23
30
|
import { shortenPath, TARGET_IDS } from "../../setup/plan.js";
|
|
31
|
+
import { MCP_NO_LOCATION } from "../../setup/targets.js";
|
|
24
32
|
import { checkShellCompletions } from "./checkShellCompletions.js";
|
|
33
|
+
import { harnessInventory, inventoryHealth, } from "./harnessInventory.js";
|
|
25
34
|
import { commandResolves } from "./mcpCommand.js";
|
|
26
35
|
/** The `config` row: the global config file exists and parses. */
|
|
27
36
|
const configHealth = (d, roots) => {
|
|
28
37
|
const path = shortenPath(d.path, roots);
|
|
29
38
|
if (!d.exists)
|
|
30
|
-
return { status: "available", detail: `${path} not
|
|
39
|
+
return { status: "available", detail: `${path} does not exist yet` };
|
|
31
40
|
if (!d.parses) {
|
|
32
41
|
return { status: "fail", detail: `${path} cannot be parsed as JSON` };
|
|
33
42
|
}
|
|
@@ -40,8 +49,8 @@ const lspHealth = (d) => {
|
|
|
40
49
|
}
|
|
41
50
|
const editors = lspEditorNames(d).join(", ");
|
|
42
51
|
return d.state === "installed"
|
|
43
|
-
? { status: "pass", detail: `installed
|
|
44
|
-
: { status: "available", detail: `not installed
|
|
52
|
+
? { status: "pass", detail: `installed in ${editors}` }
|
|
53
|
+
: { status: "available", detail: `not installed in ${editors}` };
|
|
45
54
|
};
|
|
46
55
|
/**
|
|
47
56
|
* The `mcp` row: one sub-item per file, each saying whether the entry is
|
|
@@ -49,19 +58,16 @@ const lspHealth = (d) => {
|
|
|
49
58
|
* one for presence, one for command resolution — and the second judged every
|
|
50
59
|
* server in the file, so a foreign server's dead command failed this CLI's row.
|
|
51
60
|
*/
|
|
52
|
-
async function mcpHealth(d,
|
|
61
|
+
async function mcpHealth(d, scope, cwd, roots) {
|
|
53
62
|
if (d.groups.length === 0) {
|
|
54
|
-
return {
|
|
55
|
-
status: "skip",
|
|
56
|
-
detail: "no harness config location in this band",
|
|
57
|
-
};
|
|
63
|
+
return { status: "skip", detail: MCP_NO_LOCATION[scope] };
|
|
58
64
|
}
|
|
59
65
|
const resolves = await commandResolves(MCP_SERVER_NAME, cwd);
|
|
60
66
|
const items = d.groups.map((group) => {
|
|
61
67
|
const state = mcpGroupState(d, group.path);
|
|
62
68
|
const label = shortenPath(group.path, roots);
|
|
63
69
|
if (state === "absent") {
|
|
64
|
-
return { label, status: "available", detail: "not
|
|
70
|
+
return { label, status: "available", detail: "not registered" };
|
|
65
71
|
}
|
|
66
72
|
if (state === "drifted") {
|
|
67
73
|
return { label, status: "fail", detail: "entry differs from current" };
|
|
@@ -70,8 +76,8 @@ async function mcpHealth(d, band, cwd, roots) {
|
|
|
70
76
|
label,
|
|
71
77
|
status: resolves ? "pass" : "fail",
|
|
72
78
|
detail: resolves
|
|
73
|
-
? `
|
|
74
|
-
: `
|
|
79
|
+
? `registered, and \`${MCP_SERVER_NAME}\` is on PATH`
|
|
80
|
+
: `registered, but \`${MCP_SERVER_NAME}\` is not on PATH`,
|
|
75
81
|
};
|
|
76
82
|
});
|
|
77
83
|
const configured = items.filter((item) => item.status === "pass").length;
|
|
@@ -79,33 +85,51 @@ async function mcpHealth(d, band, cwd, roots) {
|
|
|
79
85
|
if (failing > 0) {
|
|
80
86
|
return {
|
|
81
87
|
status: "fail",
|
|
82
|
-
detail: `${failing} of ${items.length} need attention`,
|
|
88
|
+
detail: `${failing} of ${items.length} config files need attention`,
|
|
83
89
|
items,
|
|
84
90
|
};
|
|
85
91
|
}
|
|
86
92
|
if (configured === 0) {
|
|
87
|
-
//
|
|
88
|
-
// repository with no checked-in MCP config is
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
// Absence in the LOCAL PROJECT is not a failure: registering there is
|
|
94
|
+
// opt-in, so a repository with no checked-in MCP config is healthy. The
|
|
95
|
+
// line says so rather than leaving "(opt-in)" to be decoded.
|
|
96
|
+
return scope === "project"
|
|
97
|
+
? {
|
|
98
|
+
status: "skip",
|
|
99
|
+
detail: "not registered for this project — per-project registration is opt-in",
|
|
100
|
+
}
|
|
91
101
|
: {
|
|
92
102
|
status: "available",
|
|
93
|
-
detail:
|
|
103
|
+
detail: `not registered in any of ${items.length} config files`,
|
|
94
104
|
items,
|
|
95
105
|
};
|
|
96
106
|
}
|
|
97
107
|
return {
|
|
98
108
|
status: configured === items.length ? "pass" : "available",
|
|
99
|
-
detail:
|
|
109
|
+
detail: `registered in ${configured} of ${items.length} config files`,
|
|
100
110
|
items,
|
|
101
111
|
};
|
|
102
112
|
}
|
|
103
113
|
/** The `skills` row: every expected link present, lstat-verified, none stale. */
|
|
104
|
-
function skillsHealth(d,
|
|
105
|
-
|
|
114
|
+
function skillsHealth(d, scope, roots) {
|
|
115
|
+
const short = shortenPath(d.sourceRoot, roots);
|
|
116
|
+
// Stale links this scope owns are work even when the root holds no skill, so
|
|
117
|
+
// the row is only a skip once there is nothing left to reconcile either.
|
|
118
|
+
const orphans = d.rootExists ? d.orphans.length : 0;
|
|
119
|
+
if (!d.available && orphans === 0) {
|
|
120
|
+
// The skip carries a remedy — `setup`'s row and this row are the same
|
|
121
|
+
// finding, and the dead-end version of it ("no skills installed", no next
|
|
122
|
+
// step) was reported identically by both surfaces.
|
|
106
123
|
return {
|
|
107
124
|
status: "skip",
|
|
108
|
-
detail: skillsSkipReason(
|
|
125
|
+
detail: skillsSkipReason(short, scope, d.rootExists),
|
|
126
|
+
remedy: skillsSkipRemedy(short, scope),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (orphans > 0) {
|
|
130
|
+
return {
|
|
131
|
+
status: "available",
|
|
132
|
+
detail: `${orphans} link${orphans === 1 ? "" : "s"} point at a skill that is gone`,
|
|
109
133
|
};
|
|
110
134
|
}
|
|
111
135
|
const stale = d.actions.filter((a) => a.action === "replaced").length;
|
|
@@ -120,6 +144,19 @@ function skillsHealth(d, band, roots) {
|
|
|
120
144
|
// and reporting the two the same way made this row say "links current" where
|
|
121
145
|
// no link exists at all. Setup will never clear such a path — it is not this
|
|
122
146
|
// command's to delete — so the row carries the only remedy that settles it.
|
|
147
|
+
// A symlink pointing outside every root pragma owns is `skipped` so setup
|
|
148
|
+
// will never delete it — which would make this row claim "links current" over
|
|
149
|
+
// a path where the user's own link shadows a shipped skill. `skipped` also
|
|
150
|
+
// covers an already-correct link (owned) and a real directory (blocked), so
|
|
151
|
+
// the foreign case is what is left.
|
|
152
|
+
const foreign = d.actions.filter((a) => a.action === "skipped" && !a.owned && !a.blocked).length;
|
|
153
|
+
if (foreign > 0) {
|
|
154
|
+
return {
|
|
155
|
+
status: "available",
|
|
156
|
+
detail: `${foreign} of ${d.actions.length} link paths hold a symlink pragma does not own`,
|
|
157
|
+
remedy: "Move or delete the symlink at that path, then link the skills again.",
|
|
158
|
+
};
|
|
159
|
+
}
|
|
123
160
|
const blocked = d.actions.filter((a) => a.blocked).length;
|
|
124
161
|
if (blocked > 0) {
|
|
125
162
|
return {
|
|
@@ -143,7 +180,7 @@ function skillsHealth(d, band, roots) {
|
|
|
143
180
|
*/
|
|
144
181
|
async function healthOf(row, rt, roots) {
|
|
145
182
|
// A detection that threw is reported as ITS OWN failing row. Letting the
|
|
146
|
-
// rejection escape took the whole
|
|
183
|
+
// rejection escape took the whole scoped section of the report with it, so a
|
|
147
184
|
// single unreadable config file left the user with no rows at all — the one
|
|
148
185
|
// moment the report is most worth having.
|
|
149
186
|
const failure = detectionFailure(row);
|
|
@@ -163,43 +200,150 @@ async function healthOf(row, rt, roots) {
|
|
|
163
200
|
case "lsp":
|
|
164
201
|
return lspHealth(row.detection);
|
|
165
202
|
case "mcp":
|
|
166
|
-
return mcpHealth(row.detection, row.
|
|
203
|
+
return mcpHealth(row.detection, row.scope, rt.cwd, roots);
|
|
167
204
|
default:
|
|
168
|
-
return skillsHealth(row.detection, row.
|
|
205
|
+
return skillsHealth(row.detection, row.scope, roots);
|
|
169
206
|
}
|
|
170
207
|
}
|
|
208
|
+
/** The scoped inventory row's name — a LISTING, not a setup target id. */
|
|
209
|
+
export const INVENTORY_CHECK = "harnesses";
|
|
210
|
+
/**
|
|
211
|
+
* The `harnesses` row for one scope: what this machine has, and where pragma
|
|
212
|
+
* stands in each.
|
|
213
|
+
*
|
|
214
|
+
* It is the one scoped row that is NOT a target, and it earns that by never
|
|
215
|
+
* competing with the ones that are. Its status is only `pass` or `skip`, so it
|
|
216
|
+
* adds no failure and no `available` to the tally, and it derives no `fix:` —
|
|
217
|
+
* the `mcp` and `skills` rows beside it already name every command a harness
|
|
218
|
+
* needs, and repeating them here would be the same finding seen twice.
|
|
219
|
+
*
|
|
220
|
+
* The registry is the only thing detection could not supply: `detectHarnesses`
|
|
221
|
+
* filters to hits, so "Windsurf is not on this machine" was unrepresentable
|
|
222
|
+
* until the universe came from somewhere. Everything else — which harnesses
|
|
223
|
+
* share which file, and whether each one's own entry in it is current — is read
|
|
224
|
+
* straight off the `mcp` detection this report already ran. The projection to
|
|
225
|
+
* {@link InventoryGroup} is deliberate: `McpDetection` holds
|
|
226
|
+
* `writeMcpConfigTargets`/`removeMcpConfigFrom` as live functions, and a
|
|
227
|
+
* `mutates: false` command should be unable to reach a writer, not merely
|
|
228
|
+
* trusted not to.
|
|
229
|
+
*
|
|
230
|
+
* This is also where the harness↔`mcpKey` association is REJOINED, because it
|
|
231
|
+
* is the one place that holds both halves: `TargetGroup` records the names
|
|
232
|
+
* sharing a file and, separately, one write per distinct `mcpKey`, and the
|
|
233
|
+
* registry is what says which key a given harness writes. Without that join the
|
|
234
|
+
* only state available per harness is the file's aggregate — and a
|
|
235
|
+
* `.vscode/mcp.json` where VS Code's `servers` entry is current while Cline's
|
|
236
|
+
* `mcpServers` is absent aggregates to `drifted`, which would report BOTH
|
|
237
|
+
* harnesses as drifted when neither one is.
|
|
238
|
+
*
|
|
239
|
+
* @param rt - The per-invocation runtime (read for `--verbose`).
|
|
240
|
+
* @param rows - Every detected row, both scopes, as `scopedChecks` has them.
|
|
241
|
+
* @param roots - The roots every path renders relative to.
|
|
242
|
+
* @returns One inventory {@link CheckResult} per scope, global then project.
|
|
243
|
+
* @note Impure — dynamically imports the harness registry.
|
|
244
|
+
*/
|
|
245
|
+
async function inventoryChecks(rt, rows, roots) {
|
|
246
|
+
const { harnesses, isHarnessInBand } = await import("@canonical/harnesses");
|
|
247
|
+
const verbose = rt.globalFlags.verbose;
|
|
248
|
+
const scopes = ["global", "project"];
|
|
249
|
+
// The key each harness NAME writes under — the half of the association
|
|
250
|
+
// `groupConfigTargets` consumed and did not record. Names are the only
|
|
251
|
+
// identity a group carries, and the registry's are unique.
|
|
252
|
+
const keyByName = new Map(harnesses.map((h) => [h.name, h.mcpKey]));
|
|
253
|
+
return scopes.map((scope) => {
|
|
254
|
+
// `isHarnessInBand(harness.scope, scope, scope)` — the scope asked for as
|
|
255
|
+
// its OWN selection ("band" is the harnesses package's name for it) — is
|
|
256
|
+
// exactly "does this harness have a config location here", which is the
|
|
257
|
+
// question `detectMcp` already answers for that scope. Asking it under the
|
|
258
|
+
// `both` selection would instead answer "who writes here when both scopes
|
|
259
|
+
// run", and report every dual-scope harness as having no global location.
|
|
260
|
+
const registry = harnesses.map((harness) => ({
|
|
261
|
+
id: harness.id,
|
|
262
|
+
name: harness.name,
|
|
263
|
+
inScope: isHarnessInBand(harness.scope, scope, scope),
|
|
264
|
+
}));
|
|
265
|
+
const mcpRow = rows.find((row) => row.target.id === "mcp" && row.scope === scope);
|
|
266
|
+
if (mcpRow === undefined || detectionFailure(mcpRow) !== undefined) {
|
|
267
|
+
return {
|
|
268
|
+
name: INVENTORY_CHECK,
|
|
269
|
+
status: "skip",
|
|
270
|
+
detail: "harness detection did not settle — see the `mcp` row",
|
|
271
|
+
scope,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
const detection = mcpRow.detection;
|
|
275
|
+
const groups = detection.groups.map((group) => ({
|
|
276
|
+
path: shortenPath(group.path, roots),
|
|
277
|
+
harnesses: group.harnessNames.map((name) => {
|
|
278
|
+
// The harness's OWN write in this file. A name the registry does not
|
|
279
|
+
// know (or a key no write carries — impossible while the group was
|
|
280
|
+
// built from the same registry) falls back to the file's aggregate:
|
|
281
|
+
// strictly no worse than the state before this join existed.
|
|
282
|
+
const write = group.writes.find((w) => w.mcpKey === keyByName.get(name));
|
|
283
|
+
return {
|
|
284
|
+
name,
|
|
285
|
+
state: write === undefined
|
|
286
|
+
? mcpGroupState(detection, group.path)
|
|
287
|
+
: mcpWriteState(detection, write),
|
|
288
|
+
};
|
|
289
|
+
}),
|
|
290
|
+
}));
|
|
291
|
+
const health = inventoryHealth(harnessInventory(registry, groups, scope), verbose);
|
|
292
|
+
return {
|
|
293
|
+
name: INVENTORY_CHECK,
|
|
294
|
+
status: health.status,
|
|
295
|
+
detail: health.detail,
|
|
296
|
+
scope,
|
|
297
|
+
...(health.items.length === 0 ? {} : { items: health.items }),
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
}
|
|
171
301
|
/**
|
|
172
|
-
* The command that repairs a row — derived from its id and
|
|
302
|
+
* The command that repairs a row — derived from its id and scope, never
|
|
173
303
|
* authored. This is the bijection made mechanical: a row exists because a
|
|
174
304
|
* target exists, and its fix is that target's own invocation.
|
|
175
305
|
*/
|
|
176
|
-
export const fixCommandFor = (id,
|
|
306
|
+
export const fixCommandFor = (id, scope, bin) => `${bin} setup ${id}${scope === "project" ? " --local" : ""}`;
|
|
177
307
|
/**
|
|
178
|
-
* Run every
|
|
308
|
+
* Run every scoped check: the target table, both scopes, in table order, then
|
|
309
|
+
* each scope's harness inventory.
|
|
310
|
+
*
|
|
311
|
+
* The inventory rows come LAST within the array, and the renderer partitions by
|
|
312
|
+
* scope while preserving order, so each scope's section ends with the listing of
|
|
313
|
+
* what that scope actually holds — the targets first, then the machine they were
|
|
314
|
+
* measured against. They ride on the SAME detection pass: no target is probed a
|
|
315
|
+
* second time to produce them.
|
|
179
316
|
*
|
|
180
317
|
* @param rt - The per-invocation runtime.
|
|
181
318
|
* @param bin - The binary name the `fix:` lines are derived from.
|
|
182
|
-
* @returns One {@link CheckResult} per (target,
|
|
319
|
+
* @returns One {@link CheckResult} per (target, scope), plus one per scope.
|
|
183
320
|
* @note Impure — every target's detection reads the real filesystem.
|
|
184
321
|
*/
|
|
185
|
-
export async function
|
|
322
|
+
export async function scopedChecks(rt, bin) {
|
|
186
323
|
const roots = await resolveRoots(rt);
|
|
187
324
|
const detected = await detectTargets(rt, [...TARGET_IDS], "both");
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
:
|
|
202
|
-
|
|
203
|
-
|
|
325
|
+
const [targetRows, inventoryRows] = await Promise.all([
|
|
326
|
+
Promise.all(detected.map(async (row) => {
|
|
327
|
+
const health = await healthOf(row, rt, roots);
|
|
328
|
+
const needsFix = health.status === "fail" || health.status === "available";
|
|
329
|
+
// A `skip` gets no DERIVED fix — re-running the target's own setup command
|
|
330
|
+
// would reproduce the skip. But a skip that AUTHORED a remedy has found a
|
|
331
|
+
// real next step on this machine (fill the scope's skill root, say), and
|
|
332
|
+
// dropping it is what made the skip a dead end on both surfaces.
|
|
333
|
+
const remedy = needsFix
|
|
334
|
+
? (health.remedy ?? fixCommandFor(row.target.id, row.scope, bin))
|
|
335
|
+
: health.remedy;
|
|
336
|
+
return {
|
|
337
|
+
name: row.target.id,
|
|
338
|
+
status: health.status,
|
|
339
|
+
detail: health.detail,
|
|
340
|
+
scope: row.scope,
|
|
341
|
+
...(health.items === undefined ? {} : { items: health.items }),
|
|
342
|
+
...(remedy === undefined ? {} : { remedy }),
|
|
343
|
+
};
|
|
344
|
+
})),
|
|
345
|
+
inventoryChecks(rt, detected, roots),
|
|
346
|
+
]);
|
|
347
|
+
return [...targetRows, ...inventoryRows];
|
|
204
348
|
}
|
|
205
349
|
//# sourceMappingURL=targetHealth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targetHealth.js","sourceRoot":"","sources":["../../../../../src/capabilities/doctor/checks/targetHealth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"targetHealth.js","sourceRoot":"","sources":["../../../../../src/capabilities/doctor/checks/targetHealth.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,47 +9,16 @@
|
|
|
9
9
|
* plain form byte-for-byte instead of leaking ANSI into `doctor --format plain`.
|
|
10
10
|
* Glyphs are plain constants tinted at render time; nothing is baked at load.
|
|
11
11
|
*/
|
|
12
|
-
import chalk from "chalk";
|
|
13
12
|
import { BIN_NAME } from "../../constants.js";
|
|
14
13
|
import { defaultStyle } from "../../kernel/render/style.js";
|
|
15
|
-
import {
|
|
16
|
-
/**
|
|
17
|
-
* Uncolored status glyphs — tinted at render time (never baked at module load).
|
|
18
|
-
* `available` gets its own glyph, distinct from ✗: an opt-in integration that
|
|
19
|
-
* is not set up is not a fault, and rendering it as one would train users to
|
|
20
|
-
* ignore the failure count. The glyph pairs with the word in the tally, so the
|
|
21
|
-
* distinction survives with color stripped.
|
|
22
|
-
*/
|
|
23
|
-
const STATUS_GLYPHS = {
|
|
24
|
-
pass: "✓",
|
|
25
|
-
fail: "✗",
|
|
26
|
-
available: "◇",
|
|
27
|
-
skip: "○",
|
|
28
|
-
};
|
|
29
|
-
const SUB_BULLET = "·";
|
|
30
|
-
const FIX_ARROW = "↳";
|
|
31
|
-
const INDENT = " "; // aligns sub-lines under the check name
|
|
32
|
-
/**
|
|
33
|
-
* Build the doctor styler for this process's stdout: the shared TTY seam, plus a
|
|
34
|
-
* `red` gated on the SAME decision, so a fail tint appears only on a color TTY.
|
|
35
|
-
*
|
|
36
|
-
* @returns A colorizing styler on a color-capable TTY, else the identity styler.
|
|
37
|
-
* @note Impure — {@link defaultStyle} reads `process.stdout.isTTY` + chalk level.
|
|
38
|
-
*/
|
|
39
|
-
function doctorStyle() {
|
|
40
|
-
const style = defaultStyle();
|
|
41
|
-
return {
|
|
42
|
-
...style,
|
|
43
|
-
red: style.enabled ? (text) => chalk.red(text) : (text) => text,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
14
|
+
import { CHECK_GLYPHS, checkRemedyWord, FIX_ARROW, SCOPE_LABELS, SUB_BULLET, SUB_INDENT, } from "../../kernel/render/vocabulary.js";
|
|
46
15
|
/**
|
|
47
16
|
* Tint a status glyph by meaning — green pass, red fail, cyan available
|
|
48
17
|
* (actionable-but-optional, the same tint as the `fix:` arrow it points at),
|
|
49
18
|
* yellow skip.
|
|
50
19
|
*/
|
|
51
20
|
function paintGlyph(status, style) {
|
|
52
|
-
const glyph =
|
|
21
|
+
const glyph = CHECK_GLYPHS[status];
|
|
53
22
|
if (status === "pass")
|
|
54
23
|
return style.green(glyph);
|
|
55
24
|
if (status === "fail")
|
|
@@ -60,8 +29,8 @@ function paintGlyph(status, style) {
|
|
|
60
29
|
}
|
|
61
30
|
/**
|
|
62
31
|
* Render one check as terminal lines: a headline row (icon, aligned name,
|
|
63
|
-
* detail), an optional indented breakdown of sub-items, and —
|
|
64
|
-
* inline
|
|
32
|
+
* detail), an optional indented breakdown of sub-items, and — whenever the
|
|
33
|
+
* check carries one — an inline instruction.
|
|
65
34
|
*/
|
|
66
35
|
function formatCheckPlain(check, nameWidth, style) {
|
|
67
36
|
const name = check.name.padEnd(nameWidth);
|
|
@@ -80,14 +49,20 @@ function formatCheckPlain(check, nameWidth, style) {
|
|
|
80
49
|
: "";
|
|
81
50
|
const itemLabel = item.detail ? item.label.padEnd(itemWidth) : item.label;
|
|
82
51
|
const detail = item.detail ? ` ${style.dim(item.detail)}` : "";
|
|
83
|
-
lines.push(`${
|
|
52
|
+
lines.push(`${SUB_INDENT}${style.dim(SUB_BULLET)} ${icon}${itemLabel}${detail}`);
|
|
84
53
|
}
|
|
85
54
|
}
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
55
|
+
// Every row that HAS an instruction prints it. A fail's remedy is the
|
|
56
|
+
// repair, an available's is the setup command that enables it — and a skip's,
|
|
57
|
+
// when it authored one, is the only thing standing between the reader and a
|
|
58
|
+
// dead end. Skips were dropped here, so `skills` reported "no skills
|
|
59
|
+
// installed" with the next step (`sources update`) computed, carried through
|
|
60
|
+
// the check, published in `--format json`, and then thrown away one line
|
|
61
|
+
// before it reached the person reading. A skip never DERIVES a remedy
|
|
62
|
+
// (`scopedChecks` only passes through an authored one), so this prints
|
|
63
|
+
// nothing that was not deliberately written for this machine.
|
|
64
|
+
if (check.remedy) {
|
|
65
|
+
lines.push(`${SUB_INDENT}${style.cyan(FIX_ARROW)} ${style.cyan(`${checkRemedyWord(check.status)}:`)} ${check.remedy}`);
|
|
91
66
|
}
|
|
92
67
|
return lines;
|
|
93
68
|
}
|
|
@@ -110,23 +85,23 @@ function formatSummary(data, style) {
|
|
|
110
85
|
return ` ${parts.join(style.dim(" · "))}`;
|
|
111
86
|
}
|
|
112
87
|
/**
|
|
113
|
-
* Partition checks into ordered
|
|
114
|
-
* and project
|
|
115
|
-
* report stays deterministic.
|
|
88
|
+
* Partition checks into ordered sections: environment (no scope), then the
|
|
89
|
+
* global and local-project scopes. Declaration order is preserved within each,
|
|
90
|
+
* so the report stays deterministic.
|
|
116
91
|
*/
|
|
117
|
-
function
|
|
92
|
+
function partitionByScope(checks) {
|
|
118
93
|
return {
|
|
119
|
-
environment: checks.filter((c) => c.
|
|
120
|
-
|
|
121
|
-
project: checks.filter((c) => c.
|
|
94
|
+
environment: checks.filter((c) => c.scope === undefined),
|
|
95
|
+
global: checks.filter((c) => c.scope === "global"),
|
|
96
|
+
project: checks.filter((c) => c.scope === "project"),
|
|
122
97
|
};
|
|
123
98
|
}
|
|
124
99
|
export const doctorFormatters = {
|
|
125
100
|
plain(data) {
|
|
126
|
-
const style =
|
|
101
|
+
const style = defaultStyle();
|
|
127
102
|
const nameWidth = Math.max(...data.checks.map((c) => c.name.length), 0);
|
|
128
103
|
const lines = [style.bold(`${BIN_NAME} doctor`), ""];
|
|
129
|
-
const { environment,
|
|
104
|
+
const { environment, global, project } = partitionByScope(data.checks);
|
|
130
105
|
const section = (heading, checks) => {
|
|
131
106
|
if (checks.length === 0)
|
|
132
107
|
return;
|
|
@@ -136,34 +111,38 @@ export const doctorFormatters = {
|
|
|
136
111
|
lines.push(...formatCheckPlain(check, nameWidth, style));
|
|
137
112
|
lines.push("");
|
|
138
113
|
};
|
|
139
|
-
// Environment checks lead (no header);
|
|
140
|
-
// two
|
|
114
|
+
// Environment checks lead (no header); Global then Local project are the
|
|
115
|
+
// two scoped sections before the tally.
|
|
141
116
|
section("", environment);
|
|
142
|
-
section(
|
|
143
|
-
section(
|
|
117
|
+
section(SCOPE_LABELS.global, global);
|
|
118
|
+
section(SCOPE_LABELS.project, project);
|
|
144
119
|
lines.push(formatSummary(data, style));
|
|
145
120
|
return lines.join("\n");
|
|
146
121
|
},
|
|
147
122
|
llm(data) {
|
|
148
123
|
const renderCheck = (check) => {
|
|
149
124
|
const out = [
|
|
150
|
-
`- ${
|
|
125
|
+
`- ${CHECK_GLYPHS[check.status]} **${check.name}**: ${check.detail}`,
|
|
151
126
|
];
|
|
152
127
|
for (const item of check.items ?? []) {
|
|
153
|
-
const itemIcon = item.status ? `${
|
|
128
|
+
const itemIcon = item.status ? `${CHECK_GLYPHS[item.status]} ` : "";
|
|
154
129
|
const detail = item.detail ? `: ${item.detail}` : "";
|
|
155
130
|
out.push(` - ${itemIcon}${item.label}${detail}`);
|
|
156
131
|
}
|
|
157
|
-
// Same rule as the plain path:
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
132
|
+
// Same rule as the plain path: every row that carries an instruction
|
|
133
|
+
// prints it, under the label its status earns. Only a `fix:` is code-set
|
|
134
|
+
// — a derived remedy is a bare command, while a skip's authored `next:`
|
|
135
|
+
// is a sentence that may quote a command of its own, and wrapping that in
|
|
136
|
+
// backticks nests one code span inside another.
|
|
137
|
+
if (check.remedy) {
|
|
138
|
+
out.push(check.status === "skip"
|
|
139
|
+
? ` - _${checkRemedyWord(check.status)}:_ ${check.remedy}`
|
|
140
|
+
: ` - _${checkRemedyWord(check.status)}:_ \`${check.remedy}\``);
|
|
162
141
|
}
|
|
163
142
|
return out;
|
|
164
143
|
};
|
|
165
144
|
const lines = ["## Doctor", ""];
|
|
166
|
-
const { environment,
|
|
145
|
+
const { environment, global, project } = partitionByScope(data.checks);
|
|
167
146
|
const section = (heading, checks) => {
|
|
168
147
|
if (checks.length === 0)
|
|
169
148
|
return;
|
|
@@ -173,8 +152,8 @@ export const doctorFormatters = {
|
|
|
173
152
|
lines.push(...renderCheck(check));
|
|
174
153
|
};
|
|
175
154
|
section("", environment);
|
|
176
|
-
section(
|
|
177
|
-
section(
|
|
155
|
+
section(SCOPE_LABELS.global, global);
|
|
156
|
+
section(SCOPE_LABELS.project, project);
|
|
178
157
|
lines.push("", `_${data.passed} passed, ${data.failed} failed, ${data.available} available, ${data.skipped} skipped_`);
|
|
179
158
|
return lines.join("\n");
|
|
180
159
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.render.js","sourceRoot":"","sources":["../../../../src/capabilities/doctor/doctor.render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.render.js","sourceRoot":"","sources":["../../../../src/capabilities/doctor/doctor.render.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,8 +16,12 @@ import { asVerb } from "../../kernel/spec/asVerb.js";
|
|
|
16
16
|
import { doctorFormatters } from "./doctor.render.js";
|
|
17
17
|
const doctorVerb = {
|
|
18
18
|
path: ["doctor"],
|
|
19
|
-
summary: "Check environment
|
|
20
|
-
|
|
19
|
+
summary: "Check your environment and every setup target, globally and in this project.",
|
|
20
|
+
// Two house rules constrain this string and both are PROTECTED: it may not
|
|
21
|
+
// name the distribution (`identity.test.ts`) and it may not spell a CLI flag
|
|
22
|
+
// (`toolDescriptions.test.ts`), so the inventory's widening is described as
|
|
23
|
+
// "the verbose global flag" rather than by its spelling.
|
|
24
|
+
doc: "Reports the environment checks first, then one row per setup target — once for your home directory, once for this project. Each row is pass, fail, available (an optional integration you have not set up yet), or skip (nothing to do here, and the row says why), with the next step printed inline. Every row is named after the setup target that repairs it, except `harnesses`: a listing, per scope, of the AI harnesses found on this machine and whether this CLI's MCP server is registered in each — the ones actually found, or every harness it knows about under the verbose global flag. Needs no store; the store check boots lazily and never fails the run.",
|
|
21
25
|
params: [],
|
|
22
26
|
output: { formatters: doctorFormatters },
|
|
23
27
|
examples: [
|