agents-inc 0.154.0 → 0.156.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/CHANGELOG.md +55 -0
- package/dist/chunk-2H7UWE2G.js +246 -0
- package/dist/chunk-2H7UWE2G.js.map +1 -0
- package/dist/{chunk-LA3JPESW.js → chunk-4A4L3YIW.js} +5 -5
- package/dist/chunk-4G2YHZIM.js +132 -0
- package/dist/chunk-4G2YHZIM.js.map +1 -0
- package/dist/{chunk-BZ4CZBOM.js → chunk-5F2YR5XV.js} +3 -3
- package/dist/{chunk-CHNA5RVS.js → chunk-5OKLCVM4.js} +3 -3
- package/dist/{chunk-ZU6DAR4S.js → chunk-5QZAK6J7.js} +7 -7
- package/dist/{chunk-ZU6DAR4S.js.map → chunk-5QZAK6J7.js.map} +1 -1
- package/dist/{chunk-NFH6SA62.js → chunk-6RLV45HN.js} +10 -10
- package/dist/{chunk-NFH6SA62.js.map → chunk-6RLV45HN.js.map} +1 -1
- package/dist/{chunk-GUDGCFSF.js → chunk-CLFHC2DK.js} +15 -106
- package/dist/chunk-CLFHC2DK.js.map +1 -0
- package/dist/chunk-D2CAV7MG.js +61 -0
- package/dist/chunk-D2CAV7MG.js.map +1 -0
- package/dist/{chunk-UW44KSYL.js → chunk-F2AMBBIA.js} +6 -6
- package/dist/{chunk-UW44KSYL.js.map → chunk-F2AMBBIA.js.map} +1 -1
- package/dist/{chunk-QQTYMW7N.js → chunk-F5T6TV4Z.js} +206 -73
- package/dist/chunk-F5T6TV4Z.js.map +1 -0
- package/dist/{chunk-K3O3YQYG.js → chunk-G47TDUK3.js} +2 -2
- package/dist/{chunk-AURY6RT6.js → chunk-GS2NZ3GD.js} +8 -8
- package/dist/chunk-GS2NZ3GD.js.map +1 -0
- package/dist/{chunk-5MFJ24VM.js → chunk-H6UTKTLK.js} +104 -250
- package/dist/chunk-H6UTKTLK.js.map +1 -0
- package/dist/{chunk-MJFIO5SX.js → chunk-HG4JPXJT.js} +11 -11
- package/dist/chunk-HG4JPXJT.js.map +1 -0
- package/dist/{chunk-IXEDSKMH.js → chunk-HTYH7CKN.js} +3 -3
- package/dist/{chunk-JC7DBPRD.js → chunk-HXKOIWLU.js} +2 -2
- package/dist/chunk-HXKOIWLU.js.map +1 -0
- package/dist/{chunk-NSJ2S7R5.js → chunk-ILUVL7WM.js} +2 -2
- package/dist/{chunk-R54KIGN2.js → chunk-IO5YBKHV.js} +13 -2
- package/dist/chunk-IO5YBKHV.js.map +1 -0
- package/dist/chunk-IXRZAHZF.js +53 -0
- package/dist/chunk-IXRZAHZF.js.map +1 -0
- package/dist/chunk-JCPANDNR.js +35 -0
- package/dist/chunk-JCPANDNR.js.map +1 -0
- package/dist/{chunk-NKCY2ULI.js → chunk-LJCNUP6M.js} +2 -2
- package/dist/{chunk-PRJD5MMQ.js → chunk-MHRC3KRX.js} +5 -5
- package/dist/chunk-MHRC3KRX.js.map +1 -0
- package/dist/chunk-MO5FGLVS.js +142 -0
- package/dist/chunk-MO5FGLVS.js.map +1 -0
- package/dist/{chunk-Q5FLW4JG.js → chunk-OKH64JZE.js} +2 -2
- package/dist/{chunk-WRRP47PY.js → chunk-PCC4LBKB.js} +2 -2
- package/dist/chunk-PMUABBPG.js +258 -0
- package/dist/chunk-PMUABBPG.js.map +1 -0
- package/dist/{chunk-2IMYK4WN.js → chunk-PNMM5HNX.js} +5 -5
- package/dist/{chunk-AKQ5QISO.js → chunk-QWVXOCXO.js} +6 -6
- package/dist/{chunk-IPJOMAWC.js → chunk-RWOYPOMR.js} +12 -2
- package/dist/{chunk-IPJOMAWC.js.map → chunk-RWOYPOMR.js.map} +1 -1
- package/dist/{chunk-ONWEOS77.js → chunk-SY4X2LND.js} +4 -4
- package/dist/{chunk-XGMOXMS4.js → chunk-TBOVYLQJ.js} +2 -2
- package/dist/{chunk-R7JV22QK.js → chunk-TNGMF4UX.js} +20 -20
- package/dist/{chunk-R7JV22QK.js.map → chunk-TNGMF4UX.js.map} +1 -1
- package/dist/{chunk-7VZV4O6B.js → chunk-UMH2YZKG.js} +14 -5
- package/dist/chunk-UMH2YZKG.js.map +1 -0
- package/dist/{chunk-6CNRMCFM.js → chunk-VPASBA7P.js} +2 -2
- package/dist/{chunk-CBF4ZYV3.js → chunk-WCAUUBHO.js} +1376 -741
- package/dist/chunk-WCAUUBHO.js.map +1 -0
- package/dist/{chunk-V3ENMW7G.js → chunk-WFRTHH3A.js} +3 -3
- package/dist/{chunk-DRKSYJZ2.js → chunk-WTJ3AY33.js} +1 -1
- package/dist/{chunk-DRKSYJZ2.js.map → chunk-WTJ3AY33.js.map} +1 -1
- package/dist/{chunk-XMEIVWAS.js → chunk-WUQ3MTPF.js} +11 -5
- package/dist/{chunk-XMEIVWAS.js.map → chunk-WUQ3MTPF.js.map} +1 -1
- package/dist/{chunk-4VCWL2IG.js → chunk-XAXJWXI4.js} +92 -59
- package/dist/chunk-XAXJWXI4.js.map +1 -0
- package/dist/{chunk-B66SC72V.js → chunk-Y5Y7XHVU.js} +4 -4
- package/dist/{chunk-FMYHWKGG.js → chunk-YO2LTXB4.js} +66 -16
- package/dist/chunk-YO2LTXB4.js.map +1 -0
- package/dist/{chunk-TUQF577Z.js → chunk-ZUAZHDKP.js} +40 -41
- package/dist/chunk-ZUAZHDKP.js.map +1 -0
- package/dist/commands/build/marketplace.js +98 -121
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +8 -8
- package/dist/commands/compile.js +19 -24
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +220 -79
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +549 -75
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +26 -21
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +41 -39
- package/dist/commands/list.js +11 -11
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +243 -0
- package/dist/commands/new/marketplace.js.map +1 -0
- package/dist/commands/search.js +16 -14
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +67 -0
- package/dist/commands/share.js.map +1 -0
- package/dist/commands/uninstall.js +61 -74
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -9
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +1 -1
- package/dist/components/common/removal-plan-confirm.js +10 -0
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/wizard/category-grid.js +5 -5
- package/dist/components/wizard/checkbox-grid.js +5 -5
- package/dist/components/wizard/domain-selection.js +11 -11
- package/dist/components/wizard/run-wizard-session.js +29 -28
- package/dist/components/wizard/scroll-affordance.js +2 -2
- package/dist/components/wizard/skill-agent-summary.js +6 -6
- package/dist/components/wizard/source-grid.js +6 -6
- package/dist/components/wizard/stack-selection.js +8 -8
- package/dist/components/wizard/step-agents.js +10 -11
- package/dist/components/wizard/step-build.js +9 -9
- package/dist/components/wizard/step-confirm.js +10 -10
- package/dist/components/wizard/step-sources.js +10 -10
- package/dist/components/wizard/step-stack.js +9 -9
- package/dist/components/wizard/summary-panel.js +9 -9
- package/dist/components/wizard/toast.js +2 -2
- package/dist/components/wizard/wizard-layout.js +14 -14
- package/dist/components/wizard/wizard-tabs.js +2 -2
- package/dist/components/wizard/wizard.js +27 -27
- package/dist/copy-local-skills-NSUTBVLJ.js +14 -0
- package/dist/hooks/init.js +42 -62
- package/dist/hooks/init.js.map +1 -1
- package/dist/load-agent-defs-X4E57I2U.js +15 -0
- package/dist/{loader-JIZDTR4G.js → loader-G6BFG2VA.js} +3 -3
- package/dist/recompile-project-agents-JE4MM72I.js +20 -0
- package/dist/{source-loader-OE6EJFPU.js → source-loader-3DL3NYUX.js} +7 -5
- package/dist/source-loader-3DL3NYUX.js.map +1 -0
- package/dist/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/dist/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/dist/src/agents/developer/ai-developer/identity.md +1 -1
- package/dist/src/agents/developer/ai-developer/playbook.md +1 -1
- package/dist/src/agents/developer/api-developer/identity.md +1 -1
- package/dist/src/agents/developer/cli-developer/identity.md +1 -1
- package/dist/src/agents/developer/web-developer/identity.md +1 -1
- package/dist/src/agents/meta/codex-keeper/identity.md +1 -1
- package/dist/src/agents/meta/convention-keeper/identity.md +1 -1
- package/dist/src/agents/meta/skill-summoner/identity.md +1 -1
- package/dist/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/api-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/dist/src/agents/researcher/web-researcher/identity.md +1 -1
- package/dist/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/dist/src/agents/tester/ai-tester/identity.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/dist/src/agents/tester/api-tester/identity.md +2 -2
- package/dist/src/agents/tester/cli-tester/identity.md +1 -1
- package/dist/src/agents/tester/web-tester/identity.md +3 -3
- package/dist/stores/wizard-store.js +7 -5
- package/package.json +10 -7
- package/src/agents/developer/ai-developer/critical-reminders.md +1 -1
- package/src/agents/developer/ai-developer/critical-requirements.md +1 -1
- package/src/agents/developer/ai-developer/identity.md +1 -1
- package/src/agents/developer/ai-developer/playbook.md +1 -1
- package/src/agents/developer/api-developer/identity.md +1 -1
- package/src/agents/developer/cli-developer/identity.md +1 -1
- package/src/agents/developer/web-developer/identity.md +1 -1
- package/src/agents/meta/codex-keeper/identity.md +1 -1
- package/src/agents/meta/convention-keeper/identity.md +1 -1
- package/src/agents/meta/skill-summoner/identity.md +1 -1
- package/src/agents/researcher/ai-researcher/identity.md +1 -1
- package/src/agents/researcher/api-researcher/identity.md +1 -1
- package/src/agents/researcher/cli-researcher/identity.md +1 -1
- package/src/agents/researcher/web-researcher/identity.md +1 -1
- package/src/agents/reviewer/reviewer/playbook.md +1 -1
- package/src/agents/tester/ai-tester/identity.md +1 -1
- package/src/agents/tester/api-tester/critical-reminders.md +1 -1
- package/src/agents/tester/api-tester/critical-requirements.md +1 -1
- package/src/agents/tester/api-tester/identity.md +2 -2
- package/src/agents/tester/cli-tester/identity.md +1 -1
- package/src/agents/tester/web-tester/identity.md +3 -3
- package/src/schemas/custom-metadata.schema.json +3 -0
- package/src/schemas/metadata.schema.json +3 -0
- package/src/schemas/project-config.schema.json +4 -8
- package/src/schemas/project-source-config.schema.json +2 -2
- package/dist/chunk-4VCWL2IG.js.map +0 -1
- package/dist/chunk-5MFJ24VM.js.map +0 -1
- package/dist/chunk-7VZV4O6B.js.map +0 -1
- package/dist/chunk-AURY6RT6.js.map +0 -1
- package/dist/chunk-CBF4ZYV3.js.map +0 -1
- package/dist/chunk-FMYHWKGG.js.map +0 -1
- package/dist/chunk-GUDGCFSF.js.map +0 -1
- package/dist/chunk-JC7DBPRD.js.map +0 -1
- package/dist/chunk-MJFIO5SX.js.map +0 -1
- package/dist/chunk-OJJLYHM3.js +0 -34
- package/dist/chunk-OJJLYHM3.js.map +0 -1
- package/dist/chunk-PRJD5MMQ.js.map +0 -1
- package/dist/chunk-QQTYMW7N.js.map +0 -1
- package/dist/chunk-QUDQTO3O.js +0 -41
- package/dist/chunk-QUDQTO3O.js.map +0 -1
- package/dist/chunk-R54KIGN2.js.map +0 -1
- package/dist/chunk-TUQF577Z.js.map +0 -1
- package/dist/copy-local-skills-WVHJFRPK.js +0 -14
- package/dist/load-agent-defs-5OT54J5M.js +0 -15
- package/dist/recompile-project-agents-VREEPBDV.js +0 -20
- /package/dist/{chunk-LA3JPESW.js.map → chunk-4A4L3YIW.js.map} +0 -0
- /package/dist/{chunk-BZ4CZBOM.js.map → chunk-5F2YR5XV.js.map} +0 -0
- /package/dist/{chunk-CHNA5RVS.js.map → chunk-5OKLCVM4.js.map} +0 -0
- /package/dist/{chunk-K3O3YQYG.js.map → chunk-G47TDUK3.js.map} +0 -0
- /package/dist/{chunk-IXEDSKMH.js.map → chunk-HTYH7CKN.js.map} +0 -0
- /package/dist/{chunk-NSJ2S7R5.js.map → chunk-ILUVL7WM.js.map} +0 -0
- /package/dist/{chunk-NKCY2ULI.js.map → chunk-LJCNUP6M.js.map} +0 -0
- /package/dist/{chunk-Q5FLW4JG.js.map → chunk-OKH64JZE.js.map} +0 -0
- /package/dist/{chunk-WRRP47PY.js.map → chunk-PCC4LBKB.js.map} +0 -0
- /package/dist/{chunk-2IMYK4WN.js.map → chunk-PNMM5HNX.js.map} +0 -0
- /package/dist/{chunk-AKQ5QISO.js.map → chunk-QWVXOCXO.js.map} +0 -0
- /package/dist/{chunk-ONWEOS77.js.map → chunk-SY4X2LND.js.map} +0 -0
- /package/dist/{chunk-XGMOXMS4.js.map → chunk-TBOVYLQJ.js.map} +0 -0
- /package/dist/{chunk-6CNRMCFM.js.map → chunk-VPASBA7P.js.map} +0 -0
- /package/dist/{chunk-V3ENMW7G.js.map → chunk-WFRTHH3A.js.map} +0 -0
- /package/dist/{chunk-B66SC72V.js.map → chunk-Y5Y7XHVU.js.map} +0 -0
- /package/dist/{copy-local-skills-WVHJFRPK.js.map → components/common/removal-plan-confirm.js.map} +0 -0
- /package/dist/{load-agent-defs-5OT54J5M.js.map → copy-local-skills-NSUTBVLJ.js.map} +0 -0
- /package/dist/{loader-JIZDTR4G.js.map → load-agent-defs-X4E57I2U.js.map} +0 -0
- /package/dist/{recompile-project-agents-VREEPBDV.js.map → loader-G6BFG2VA.js.map} +0 -0
- /package/dist/{source-loader-OE6EJFPU.js.map → recompile-project-agents-JE4MM72I.js.map} +0 -0
package/dist/commands/doctor.js
CHANGED
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
import {
|
|
3
3
|
detectProject,
|
|
4
4
|
loadSource
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-WUQ3MTPF.js";
|
|
6
|
+
import "../chunk-5QZAK6J7.js";
|
|
7
|
+
import "../chunk-MHRC3KRX.js";
|
|
8
|
+
import "../chunk-F2AMBBIA.js";
|
|
9
9
|
import {
|
|
10
10
|
filterExcludedEntries,
|
|
11
|
-
listAgentMdFiles
|
|
12
|
-
|
|
11
|
+
listAgentMdFiles,
|
|
12
|
+
splitAgentsByProvenance
|
|
13
|
+
} from "../chunk-ZUAZHDKP.js";
|
|
13
14
|
import {
|
|
14
15
|
BaseCommand,
|
|
15
16
|
EXIT_CODES
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
17
|
+
} from "../chunk-YO2LTXB4.js";
|
|
18
|
+
import "../chunk-UMH2YZKG.js";
|
|
19
|
+
import "../chunk-G47TDUK3.js";
|
|
19
20
|
import {
|
|
21
|
+
ConfigDefaultExportError,
|
|
20
22
|
checkMatrixHealth,
|
|
21
23
|
configDirsInPlay,
|
|
22
24
|
declaresNoContent,
|
|
@@ -32,13 +34,13 @@ import {
|
|
|
32
34
|
installBaseDir,
|
|
33
35
|
isHomeDirectory,
|
|
34
36
|
isLocalSource,
|
|
35
|
-
isRecord,
|
|
36
37
|
listRegisteredPluginInstalls,
|
|
37
38
|
loadConfig,
|
|
38
39
|
loadProjectConfigFromDir,
|
|
39
40
|
loadProjectSourceConfig,
|
|
40
41
|
loadSkillsMatrixFromSource,
|
|
41
42
|
parseMarketplacePluginRef,
|
|
43
|
+
readForkedFromMetadata,
|
|
42
44
|
resolveInstallPaths,
|
|
43
45
|
resolvePrimarySourceEntry,
|
|
44
46
|
validateAgentFrontmatter,
|
|
@@ -46,7 +48,7 @@ import {
|
|
|
46
48
|
validatePlugin,
|
|
47
49
|
validateProjectConfig,
|
|
48
50
|
validateSkillFrontmatter
|
|
49
|
-
} from "../chunk-
|
|
51
|
+
} from "../chunk-WCAUUBHO.js";
|
|
50
52
|
import {
|
|
51
53
|
agentYamlGenerationSchema,
|
|
52
54
|
directoryExists,
|
|
@@ -54,6 +56,7 @@ import {
|
|
|
54
56
|
formatZodErrors,
|
|
55
57
|
getErrorMessage,
|
|
56
58
|
glob,
|
|
59
|
+
isRecord,
|
|
57
60
|
listDirectories,
|
|
58
61
|
metadataValidationSchema,
|
|
59
62
|
parseFrontmatter,
|
|
@@ -66,10 +69,10 @@ import {
|
|
|
66
69
|
stackConfigValidationSchema,
|
|
67
70
|
stacksConfigSchema,
|
|
68
71
|
validateSkillMetadata
|
|
69
|
-
} from "../chunk-
|
|
72
|
+
} from "../chunk-XAXJWXI4.js";
|
|
70
73
|
import {
|
|
71
74
|
matrix
|
|
72
|
-
} from "../chunk-
|
|
75
|
+
} from "../chunk-RWOYPOMR.js";
|
|
73
76
|
import "../chunk-VASLW636.js";
|
|
74
77
|
import {
|
|
75
78
|
CLAUDE_SRC_DIR,
|
|
@@ -85,7 +88,7 @@ import {
|
|
|
85
88
|
STACKS_FILE_PATH,
|
|
86
89
|
STANDARD_FILES,
|
|
87
90
|
UI_SYMBOLS
|
|
88
|
-
} from "../chunk-
|
|
91
|
+
} from "../chunk-IO5YBKHV.js";
|
|
89
92
|
import "../chunk-VZRO7RYT.js";
|
|
90
93
|
|
|
91
94
|
// src/cli/commands/doctor.ts
|
|
@@ -160,14 +163,14 @@ function validateSkillFilePairs(skillMdDirs, metadataDirs, skillsDir) {
|
|
|
160
163
|
}));
|
|
161
164
|
return [...missingMetadata, ...missingSkillMd];
|
|
162
165
|
}
|
|
163
|
-
async function validateSource(sourcePath) {
|
|
166
|
+
async function validateSource(sourcePath, reader = "author") {
|
|
164
167
|
const issues = [];
|
|
165
168
|
const resolvedPath = path.isAbsolute(sourcePath) ? sourcePath : path.resolve(sourcePath);
|
|
166
169
|
if (!await directoryExists(resolvedPath)) {
|
|
167
170
|
issues.push({
|
|
168
171
|
severity: "error",
|
|
169
172
|
file: resolvedPath,
|
|
170
|
-
message: "
|
|
173
|
+
message: "Marketplace directory does not exist"
|
|
171
174
|
});
|
|
172
175
|
return buildResult(issues, 0);
|
|
173
176
|
}
|
|
@@ -191,7 +194,7 @@ async function validateSource(sourcePath) {
|
|
|
191
194
|
for (const metadataFile of validMetadataFiles) {
|
|
192
195
|
issues.push(...await validateOneSkill(skillsDir, skillsDirRelPath, metadataFile));
|
|
193
196
|
}
|
|
194
|
-
issues.push(...await checkCrossReferences(resolvedPath));
|
|
197
|
+
issues.push(...await checkCrossReferences(resolvedPath, reader));
|
|
195
198
|
const extraIssues = await Promise.all([
|
|
196
199
|
validateStacks(resolvedPath),
|
|
197
200
|
validateAgents(resolvedPath),
|
|
@@ -200,19 +203,16 @@ async function validateSource(sourcePath) {
|
|
|
200
203
|
issues.push(...extraIssues.flat());
|
|
201
204
|
return buildResult(issues, validMetadataFiles.length);
|
|
202
205
|
}
|
|
206
|
+
function yamlParseFailure(error) {
|
|
207
|
+
return `Failed to parse YAML: ${getErrorMessage(error)}`;
|
|
208
|
+
}
|
|
203
209
|
async function validateOneSkill(skillsDir, skillsDirRelPath, metadataFile) {
|
|
204
210
|
const relPath = path.join(skillsDirRelPath, metadataFile);
|
|
205
211
|
let rawMetadata;
|
|
206
212
|
try {
|
|
207
213
|
rawMetadata = parseYaml(await readFile(path.join(skillsDir, metadataFile)));
|
|
208
214
|
} catch (error) {
|
|
209
|
-
return [
|
|
210
|
-
{
|
|
211
|
-
severity: "error",
|
|
212
|
-
file: relPath,
|
|
213
|
-
message: `Failed to parse YAML: ${getErrorMessage(error)}`
|
|
214
|
-
}
|
|
215
|
-
];
|
|
215
|
+
return [{ severity: "error", file: relPath, message: yamlParseFailure(error) }];
|
|
216
216
|
}
|
|
217
217
|
return [
|
|
218
218
|
...checkSnakeCaseKeys(rawMetadata, relPath),
|
|
@@ -230,14 +230,12 @@ function checkMetadataSchema(rawMetadata, relPath) {
|
|
|
230
230
|
...warnings.map((message) => ({ severity: "warning", file: relPath, message }))
|
|
231
231
|
];
|
|
232
232
|
}
|
|
233
|
-
async function checkCrossReferences(resolvedPath) {
|
|
233
|
+
async function checkCrossReferences(resolvedPath, reader) {
|
|
234
234
|
try {
|
|
235
235
|
await loadSkillsMatrixFromSource({ sourceFlag: resolvedPath, skipExtraSources: true });
|
|
236
|
-
return checkMatrixHealth(matrix).map(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
message: healthIssue.details
|
|
240
|
-
}));
|
|
236
|
+
return checkMatrixHealth(matrix).map(
|
|
237
|
+
(healthIssue) => toSourceIssue(healthIssue, resolvedPath, reader)
|
|
238
|
+
);
|
|
241
239
|
} catch (error) {
|
|
242
240
|
return [
|
|
243
241
|
{
|
|
@@ -248,6 +246,42 @@ async function checkCrossReferences(resolvedPath) {
|
|
|
248
246
|
];
|
|
249
247
|
}
|
|
250
248
|
}
|
|
249
|
+
var SKILL_AUDIT_PATH = "src/cli/lib/configuration/skill-audit.ts";
|
|
250
|
+
function fileHoldingDefect(finding) {
|
|
251
|
+
switch (finding) {
|
|
252
|
+
case "category-missing-domain":
|
|
253
|
+
case "skill-unknown-category":
|
|
254
|
+
return SKILL_CATEGORIES_PATH;
|
|
255
|
+
case "skill-unresolved-relation-ref":
|
|
256
|
+
case "rule-unresolved-slug":
|
|
257
|
+
return SKILL_RULES_PATH;
|
|
258
|
+
case "audit-verdict-contradiction":
|
|
259
|
+
case "skill-unaudited":
|
|
260
|
+
return SKILL_AUDIT_PATH;
|
|
261
|
+
default: {
|
|
262
|
+
const exhaustive = finding;
|
|
263
|
+
return exhaustive;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function toSourceIssue(healthIssue, marketplacePath, reader) {
|
|
268
|
+
const file = fileHoldingDefect(healthIssue.finding);
|
|
269
|
+
if (reader === "consumer" && healthIssue.finding === "rule-unresolved-slug") {
|
|
270
|
+
return {
|
|
271
|
+
severity: "warning",
|
|
272
|
+
file,
|
|
273
|
+
message: consumedMarketplaceMessage(marketplacePath, healthIssue.details)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
severity: healthIssue.severity,
|
|
278
|
+
file,
|
|
279
|
+
message: healthIssue.details
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function consumedMarketplaceMessage(marketplacePath, details) {
|
|
283
|
+
return `Marketplace '${marketplacePath}': ${details}. Nothing to fix here \u2014 the rule is that marketplace's, not this project's`;
|
|
284
|
+
}
|
|
251
285
|
async function validateStacks(resolvedPath) {
|
|
252
286
|
const stacksDir = path.join(resolvedPath, DIRS.stacks);
|
|
253
287
|
if (!await directoryExists(stacksDir)) return [];
|
|
@@ -294,8 +328,8 @@ async function validateYamlFiles(opts) {
|
|
|
294
328
|
let parsed;
|
|
295
329
|
try {
|
|
296
330
|
parsed = parseYaml(await readFile(absPath));
|
|
297
|
-
} catch {
|
|
298
|
-
issues.push({ severity: "error", file: displayPath, message:
|
|
331
|
+
} catch (error) {
|
|
332
|
+
issues.push({ severity: "error", file: displayPath, message: yamlParseFailure(error) });
|
|
299
333
|
continue;
|
|
300
334
|
}
|
|
301
335
|
const result = opts.schema.safeParse(parsed);
|
|
@@ -316,10 +350,13 @@ async function validateTsConfig(resolvedPath, relConfigPath, schema) {
|
|
|
316
350
|
try {
|
|
317
351
|
const loaded = await loadConfig(absPath, schema);
|
|
318
352
|
if (loaded === null) {
|
|
319
|
-
return [{ severity: "error", file: relConfigPath, message: "Config
|
|
353
|
+
return [{ severity: "error", file: relConfigPath, message: "Config is empty" }];
|
|
320
354
|
}
|
|
321
355
|
return [];
|
|
322
356
|
} catch (error) {
|
|
357
|
+
if (error instanceof ConfigDefaultExportError) {
|
|
358
|
+
return [{ severity: "error", file: relConfigPath, message: "Config has no default export" }];
|
|
359
|
+
}
|
|
323
360
|
return [
|
|
324
361
|
{ severity: "error", file: relConfigPath, message: formatLoadError(relConfigPath, error) }
|
|
325
362
|
];
|
|
@@ -339,7 +376,9 @@ function buildResult(issues, skillCount) {
|
|
|
339
376
|
// src/cli/lib/content-validator.ts
|
|
340
377
|
import os from "os";
|
|
341
378
|
import path2 from "path";
|
|
379
|
+
import { partition } from "remeda";
|
|
342
380
|
var CWD_SOURCE_NAME = "current directory";
|
|
381
|
+
var AGENT_FILE_EXTENSION = ".md";
|
|
343
382
|
var NOTHING_VALIDATED = { count: 0, issues: [], notes: [] };
|
|
344
383
|
function mergeValidations(parts) {
|
|
345
384
|
return parts.reduce(
|
|
@@ -391,28 +430,34 @@ async function validateRegisteredSources(projectDir) {
|
|
|
391
430
|
const registered = [primary];
|
|
392
431
|
const remote = registered.filter((source) => !isLocalSource(source.url));
|
|
393
432
|
const local = await localSourcesToValidate(projectDir, registered);
|
|
394
|
-
const outcomes = await Promise.all(
|
|
433
|
+
const outcomes = await Promise.all(
|
|
434
|
+
local.map((source) => validateOneSource(source, readerFor(projectDir, source)))
|
|
435
|
+
);
|
|
395
436
|
return {
|
|
396
437
|
count: local.length,
|
|
397
438
|
issues: outcomes.flatMap((outcome) => outcome.issues),
|
|
398
439
|
notes: [
|
|
399
440
|
...outcomes.map((outcome) => outcome.note),
|
|
400
|
-
...remote.map((source) => `${source.name} (${source.url}) \u2014 skipped (remote
|
|
441
|
+
...remote.map((source) => `${source.name} (${source.url}) \u2014 skipped (remote)`)
|
|
401
442
|
]
|
|
402
443
|
};
|
|
403
444
|
}
|
|
404
445
|
async function localSourcesToValidate(projectDir, registered) {
|
|
405
446
|
const local = registered.filter((source) => isLocalSource(source.url));
|
|
406
|
-
const alreadyCovered = local.some(
|
|
407
|
-
(source) => path2.resolve(projectDir, source.url) === projectDir
|
|
408
|
-
);
|
|
447
|
+
const alreadyCovered = local.some((source) => isCwdMarketplace(projectDir, source));
|
|
409
448
|
if (alreadyCovered || !await isSourceRepo(projectDir)) return local;
|
|
410
449
|
return [...local, { name: CWD_SOURCE_NAME, url: projectDir }];
|
|
411
450
|
}
|
|
412
|
-
|
|
451
|
+
function isCwdMarketplace(projectDir, source) {
|
|
452
|
+
return path2.resolve(projectDir, source.url) === projectDir;
|
|
453
|
+
}
|
|
454
|
+
function readerFor(projectDir, source) {
|
|
455
|
+
return isCwdMarketplace(projectDir, source) ? "author" : "consumer";
|
|
456
|
+
}
|
|
457
|
+
async function validateOneSource(source, reader) {
|
|
413
458
|
const label = `${source.name} (${source.url})`;
|
|
414
459
|
try {
|
|
415
|
-
const result = await validateSource(source.url);
|
|
460
|
+
const result = await validateSource(source.url, reader);
|
|
416
461
|
return { note: `${label} \u2014 ${result.skillCount} skills`, issues: result.issues };
|
|
417
462
|
} catch (error) {
|
|
418
463
|
return {
|
|
@@ -479,10 +524,23 @@ async function findPluginDirectories(pluginsDir) {
|
|
|
479
524
|
return checks.filter((check) => check.isPlugin).map((check) => check.name);
|
|
480
525
|
}
|
|
481
526
|
async function validateInstalledSkills(projectDir) {
|
|
527
|
+
const configuredIds = await configuredSkillIds(projectDir);
|
|
482
528
|
return mergeValidations(
|
|
483
|
-
await Promise.all(
|
|
529
|
+
await Promise.all(
|
|
530
|
+
installedDirs(projectDir, "skillsDir").map(
|
|
531
|
+
(dir) => validateSkillsDirectory(dir, configuredIds)
|
|
532
|
+
)
|
|
533
|
+
)
|
|
484
534
|
);
|
|
485
535
|
}
|
|
536
|
+
async function configuredSkillIds(projectDir) {
|
|
537
|
+
const loaded = await Promise.all(configDirsInPlay(projectDir).map(loadProjectConfigFromDir));
|
|
538
|
+
return new Set(loaded.flatMap(configuredIdsOf));
|
|
539
|
+
}
|
|
540
|
+
function configuredIdsOf(loaded) {
|
|
541
|
+
if (!loaded) return [];
|
|
542
|
+
return loaded.config.skills.map((skill) => skill.id);
|
|
543
|
+
}
|
|
486
544
|
async function validateInstalledAgents(projectDir) {
|
|
487
545
|
return mergeValidations(
|
|
488
546
|
await Promise.all(installedDirs(projectDir, "agentsDir").map(validateAgentsDirectory))
|
|
@@ -495,11 +553,22 @@ function installedDirs(projectDir, key) {
|
|
|
495
553
|
}
|
|
496
554
|
async function listInstalledArtifacts(projectDir) {
|
|
497
555
|
const [skills, agents] = await Promise.all([
|
|
498
|
-
listAcrossScopes(installedDirs(projectDir, "skillsDir"),
|
|
499
|
-
listAcrossScopes(installedDirs(projectDir, "agentsDir"),
|
|
556
|
+
listAcrossScopes(installedDirs(projectDir, "skillsDir"), listSkillDirsWithOurProvenance),
|
|
557
|
+
listAcrossScopes(installedDirs(projectDir, "agentsDir"), listAgentFilesWithOurProvenance)
|
|
500
558
|
]);
|
|
501
559
|
return { skills, agents };
|
|
502
560
|
}
|
|
561
|
+
async function listAgentFilesWithOurProvenance(agentsDir) {
|
|
562
|
+
const { marked } = await splitAgentsByProvenance(agentsDir);
|
|
563
|
+
return marked.map((name) => `${name}${AGENT_FILE_EXTENSION}`);
|
|
564
|
+
}
|
|
565
|
+
async function listSkillDirsWithOurProvenance(skillsDir) {
|
|
566
|
+
const names = await listDirectories(skillsDir);
|
|
567
|
+
const judged = await Promise.all(
|
|
568
|
+
names.map(async (name) => ({ name, ours: await carriesOurProvenance(skillsDir, name) }))
|
|
569
|
+
);
|
|
570
|
+
return judged.filter((entry) => entry.ours).map((entry) => entry.name);
|
|
571
|
+
}
|
|
503
572
|
async function listAcrossScopes(dirs, listEntries) {
|
|
504
573
|
const perDir = await Promise.all(dirs.map((dir) => listDisplayPaths(dir, listEntries)));
|
|
505
574
|
return perDir.flat();
|
|
@@ -509,17 +578,38 @@ async function listDisplayPaths(dir, listEntries) {
|
|
|
509
578
|
const entries = await listEntries(dir);
|
|
510
579
|
return entries.map((entry) => displayDir(path2.join(dir, entry)));
|
|
511
580
|
}
|
|
512
|
-
async function validateSkillsDirectory(skillsDir) {
|
|
581
|
+
async function validateSkillsDirectory(skillsDir, configuredIds) {
|
|
513
582
|
if (!await directoryExists(skillsDir)) return NOTHING_VALIDATED;
|
|
514
583
|
const skillDirs = await listDirectories(skillsDir);
|
|
515
584
|
if (skillDirs.length === 0) return NOTHING_VALIDATED;
|
|
585
|
+
const judged = await Promise.all(
|
|
586
|
+
skillDirs.map(async (name) => ({
|
|
587
|
+
name,
|
|
588
|
+
ours: await isOurSkillDirectory(skillsDir, name, configuredIds)
|
|
589
|
+
}))
|
|
590
|
+
);
|
|
591
|
+
const [ours, foreign] = partition(judged, (entry) => entry.ours);
|
|
516
592
|
const results = await Promise.all(
|
|
517
|
-
|
|
593
|
+
ours.map(async ({ name }) => {
|
|
518
594
|
const skillDir = path2.join(skillsDir, name);
|
|
519
595
|
return toIssues(displayDir(skillDir), await validateInstalledSkill(skillDir));
|
|
520
596
|
})
|
|
521
597
|
);
|
|
522
|
-
return {
|
|
598
|
+
return {
|
|
599
|
+
count: ours.length,
|
|
600
|
+
issues: results.flat(),
|
|
601
|
+
notes: foreign.map(({ name }) => foreignSkillNote(skillsDir, name))
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
async function isOurSkillDirectory(skillsDir, name, configuredIds) {
|
|
605
|
+
if (configuredIds.has(name)) return true;
|
|
606
|
+
return carriesOurProvenance(skillsDir, name);
|
|
607
|
+
}
|
|
608
|
+
async function carriesOurProvenance(skillsDir, name) {
|
|
609
|
+
return await readForkedFromMetadata(path2.join(skillsDir, name)) !== null;
|
|
610
|
+
}
|
|
611
|
+
function foreignSkillNote(skillsDir, name) {
|
|
612
|
+
return `${displayDir(path2.join(skillsDir, name))} \u2014 not installed by this CLI and named by no configuration here: not validated`;
|
|
523
613
|
}
|
|
524
614
|
async function validateAgentsDirectory(agentsDir) {
|
|
525
615
|
if (!await directoryExists(agentsDir)) return NOTHING_VALIDATED;
|
|
@@ -776,7 +866,7 @@ function countedArtifacts(skills, agents) {
|
|
|
776
866
|
}
|
|
777
867
|
async function checkSkillsInstalled(config, projectDir) {
|
|
778
868
|
const skills = config.skills;
|
|
779
|
-
const ejectSkills = skills.filter((s) => s.
|
|
869
|
+
const ejectSkills = skills.filter((s) => s.origin === EJECT_SOURCE);
|
|
780
870
|
if (ejectSkills.length === 0) {
|
|
781
871
|
return {
|
|
782
872
|
kind: "installed",
|
|
@@ -807,7 +897,7 @@ async function checkSkillsInstalled(config, projectDir) {
|
|
|
807
897
|
};
|
|
808
898
|
}
|
|
809
899
|
async function checkPluginSkillsInstalled(config, projectDir) {
|
|
810
|
-
const pluginSkills = config.skills.filter((s) => s.
|
|
900
|
+
const pluginSkills = config.skills.filter((s) => s.origin !== EJECT_SOURCE);
|
|
811
901
|
if (pluginSkills.length === 0) {
|
|
812
902
|
return {
|
|
813
903
|
kind: "plugins",
|
|
@@ -859,7 +949,7 @@ async function checkSourceReachable(projectDir) {
|
|
|
859
949
|
return {
|
|
860
950
|
kind: "source",
|
|
861
951
|
status: "fail",
|
|
862
|
-
message: "Failed to load
|
|
952
|
+
message: "Failed to load marketplace",
|
|
863
953
|
details: [message]
|
|
864
954
|
};
|
|
865
955
|
}
|
|
@@ -873,10 +963,14 @@ var CONFIG_CHECK = {
|
|
|
873
963
|
var CONTENT_CHECKS = [
|
|
874
964
|
{
|
|
875
965
|
kind: "content-sources",
|
|
876
|
-
name: "
|
|
877
|
-
noun: "
|
|
878
|
-
// The registered
|
|
966
|
+
name: "Marketplaces",
|
|
967
|
+
noun: "marketplace",
|
|
968
|
+
// The registered marketplaces are the ones config.ts names.
|
|
879
969
|
readsConfig: true,
|
|
970
|
+
// A marketplace whose content is broken is missing skills from the matrix every configured
|
|
971
|
+
// id is resolved against, so the skills row would call ids "not found" that this row has
|
|
972
|
+
// already accounted for.
|
|
973
|
+
blocks: ["skills"],
|
|
880
974
|
run: validateRegisteredSources
|
|
881
975
|
},
|
|
882
976
|
{
|
|
@@ -884,13 +978,23 @@ var CONTENT_CHECKS = [
|
|
|
884
978
|
name: "Plugins",
|
|
885
979
|
noun: "plugin",
|
|
886
980
|
readsConfig: false,
|
|
981
|
+
// `resolvePluginInstallPaths` swallows a registry it cannot parse and returns none, so every
|
|
982
|
+
// plugin-mode skill would read "no enabled plugin found" — the registry's finding, once per
|
|
983
|
+
// configured skill, wearing the row's words.
|
|
984
|
+
blocks: ["plugins"],
|
|
887
985
|
run: validateInstalledPlugins
|
|
888
986
|
},
|
|
889
987
|
{
|
|
890
988
|
kind: "content-skills",
|
|
891
989
|
name: "Skills",
|
|
892
990
|
noun: "skill",
|
|
893
|
-
|
|
991
|
+
// `~/.claude/skills/` is shared with everything else that installs a skill there, so which of
|
|
992
|
+
// its directories are this installation's is a question only the config can answer for the
|
|
993
|
+
// ones carrying no provenance marker. A config nobody can read leaves that unanswerable.
|
|
994
|
+
readsConfig: true,
|
|
995
|
+
// `extractLocalSkill` DROPS a skill whose metadata.yaml is missing or unusable, so a "not
|
|
996
|
+
// found" from the skills row would be this finding re-worded.
|
|
997
|
+
blocks: ["skills"],
|
|
894
998
|
run: validateInstalledSkills
|
|
895
999
|
},
|
|
896
1000
|
{
|
|
@@ -898,6 +1002,9 @@ var CONTENT_CHECKS = [
|
|
|
898
1002
|
name: "Agents",
|
|
899
1003
|
noun: "agent",
|
|
900
1004
|
readsConfig: false,
|
|
1005
|
+
// Nothing downstream opens an agent .md. `Agents Compiled` asks whether the file is there and
|
|
1006
|
+
// `No Orphans` reads the names of the files that are — broken frontmatter changes neither.
|
|
1007
|
+
blocks: [],
|
|
901
1008
|
run: validateInstalledAgents
|
|
902
1009
|
}
|
|
903
1010
|
];
|
|
@@ -929,14 +1036,17 @@ function toContentResult(check, validation) {
|
|
|
929
1036
|
]
|
|
930
1037
|
};
|
|
931
1038
|
}
|
|
932
|
-
var CHECK_WIDTH =
|
|
1039
|
+
var CHECK_WIDTH = 24;
|
|
933
1040
|
var SECTION_INDENT = " ";
|
|
934
1041
|
var ROW_INDENT = " ";
|
|
935
1042
|
var SECTION_CONTENT = "Content checks";
|
|
936
1043
|
var SECTION_OPERATIONAL = "Operational checks";
|
|
937
|
-
var
|
|
938
|
-
var SKIP_NO_INSTALLATION = "Skipped \u2014 no installation here (skills source repository)";
|
|
1044
|
+
var SKIP_NO_INSTALLATION = "Skipped \u2014 no installation here (marketplace repository)";
|
|
939
1045
|
var SKIP_CONFIG_UNREADABLE = "Skipped \u2014 the configuration that names them cannot be read";
|
|
1046
|
+
var SKIP_AFTER_CONFIG_ERROR = "Skipped \u2014 fix the content errors above first";
|
|
1047
|
+
function skipRestatingContent(nouns) {
|
|
1048
|
+
return `Skipped \u2014 this row would only restate the ${nouns.join(" and ")} errors above`;
|
|
1049
|
+
}
|
|
940
1050
|
function plural(count, word) {
|
|
941
1051
|
return `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
942
1052
|
}
|
|
@@ -1005,11 +1115,12 @@ var TIPS = [
|
|
|
1005
1115
|
{
|
|
1006
1116
|
// Printed beside the config tip above, which says how to get a configuration back and
|
|
1007
1117
|
// nothing about the files that outlived the old one. Both halves are named with what they
|
|
1008
|
-
// actually do: `uninstall` matches skill directories by their own `forked-from` metadata
|
|
1009
|
-
//
|
|
1118
|
+
// actually do: `uninstall` matches skill directories by their own `forked-from` metadata and
|
|
1119
|
+
// compiled agents by the marker each one carries, so neither needs the configuration that is
|
|
1120
|
+
// gone — which is why the row can name both and this tip can promise both.
|
|
1010
1121
|
kind: "orphans-unowned",
|
|
1011
1122
|
status: "fail",
|
|
1012
|
-
tip: ` Tip: Nothing declares the files above \u2014 '${CLI_INVOKE_COMMAND} init' writes a configuration that can own them again, or '${CLI_INVOKE_COMMAND} uninstall' removes
|
|
1123
|
+
tip: ` Tip: Nothing declares the files above \u2014 '${CLI_INVOKE_COMMAND} init' writes a configuration that can own them again, or '${CLI_INVOKE_COMMAND} uninstall' removes them, the compiled agents included: each file listed carries this CLI's own provenance, which is what that command reads when there is no configuration left`
|
|
1013
1124
|
},
|
|
1014
1125
|
{
|
|
1015
1126
|
kind: "skills",
|
|
@@ -1020,9 +1131,9 @@ var TIPS = [
|
|
|
1020
1131
|
kind: "installed",
|
|
1021
1132
|
status: "warn",
|
|
1022
1133
|
// No command is named on purpose: 'eject skills --force' re-copies every skill in the
|
|
1023
|
-
//
|
|
1024
|
-
// and it litters a plugin-mode project with local skill directories.
|
|
1025
|
-
tip: " Tip: Re-eject the missing skills from the
|
|
1134
|
+
// marketplace and always targets project scope, so it cannot repair a global-scoped
|
|
1135
|
+
// skill and it litters a plugin-mode project with local skill directories.
|
|
1136
|
+
tip: " Tip: Re-eject the missing skills from the marketplace to restore their files"
|
|
1026
1137
|
}
|
|
1027
1138
|
];
|
|
1028
1139
|
function formatTips(results) {
|
|
@@ -1034,11 +1145,19 @@ function skippedResult(kind) {
|
|
|
1034
1145
|
return { kind, status: "skip", message: "Skipped (config invalid)" };
|
|
1035
1146
|
}
|
|
1036
1147
|
function sourceUnreachableSkillsResult() {
|
|
1037
|
-
return { kind: "skills", status: "skip", message: "Skipped (
|
|
1148
|
+
return { kind: "skills", status: "skip", message: "Skipped (marketplace unreachable)" };
|
|
1038
1149
|
}
|
|
1039
1150
|
function skippedContentResult(kind) {
|
|
1040
1151
|
return { kind, status: "skip", message: SKIP_CONFIG_UNREADABLE };
|
|
1041
1152
|
}
|
|
1153
|
+
function failedContentKinds(contentResults) {
|
|
1154
|
+
return new Set(contentResults.filter((r) => r.status === "fail").map((r) => r.kind));
|
|
1155
|
+
}
|
|
1156
|
+
function contentBlockedResult(row, failedContent) {
|
|
1157
|
+
const blockingNouns = CONTENT_CHECKS.filter((check) => failedContent.has(check.kind)).filter((check) => check.blocks.includes(row)).map((check) => check.noun);
|
|
1158
|
+
if (blockingNouns.length === 0) return null;
|
|
1159
|
+
return { kind: row, status: "skip", message: skipRestatingContent(blockingNouns) };
|
|
1160
|
+
}
|
|
1042
1161
|
function runContentCheck(check, projectDir) {
|
|
1043
1162
|
return safeCheck(check.kind, async () => toContentResult(check, await check.run(projectDir)));
|
|
1044
1163
|
}
|
|
@@ -1051,7 +1170,7 @@ async function safeCheck(kind, fn) {
|
|
|
1051
1170
|
}
|
|
1052
1171
|
var Doctor = class _Doctor extends BaseCommand {
|
|
1053
1172
|
static summary = "Diagnose common configuration issues";
|
|
1054
|
-
static description = `Run diagnostic checks on your ${DEFAULT_BRANDING.NAME} configuration to identify issues with config validity, skill resolution, agent compilation, and
|
|
1173
|
+
static description = `Run diagnostic checks on your ${DEFAULT_BRANDING.NAME} configuration to identify issues with config validity, skill resolution, agent compilation, and marketplace connectivity.`;
|
|
1055
1174
|
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
1056
1175
|
static flags = {};
|
|
1057
1176
|
async run() {
|
|
@@ -1097,16 +1216,18 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1097
1216
|
return allRows.map((row) => row.result);
|
|
1098
1217
|
}
|
|
1099
1218
|
/**
|
|
1100
|
-
* The
|
|
1101
|
-
*
|
|
1102
|
-
*
|
|
1103
|
-
* for
|
|
1219
|
+
* The whole layer stands down for the two findings that leave every row with nothing to say: a
|
|
1220
|
+
* config nobody can read — every row is read out of it, so all of them would be cascades of that
|
|
1221
|
+
* one file — and a marketplace repository with nothing installed, where a marketplace author has
|
|
1222
|
+
* no install for the layer to describe. Every other content error is scoped to the rows that
|
|
1223
|
+
* read what it is about; {@link GatedContentCheck} says which those are, per pass.
|
|
1104
1224
|
*/
|
|
1105
1225
|
async runOperationalChecks(projectDir, contentResults) {
|
|
1106
1226
|
this.log("");
|
|
1107
1227
|
this.log(`${SECTION_INDENT}${SECTION_OPERATIONAL}`);
|
|
1108
|
-
|
|
1109
|
-
|
|
1228
|
+
const failedContent = failedContentKinds(contentResults);
|
|
1229
|
+
if (failedContent.has(CONFIG_CHECK.kind)) {
|
|
1230
|
+
this.log(`${ROW_INDENT}${SKIP_AFTER_CONFIG_ERROR}`);
|
|
1110
1231
|
return [];
|
|
1111
1232
|
}
|
|
1112
1233
|
const detected = await detectProject(projectDir);
|
|
@@ -1114,7 +1235,8 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1114
1235
|
this.log(`${ROW_INDENT}${SKIP_NO_INSTALLATION}`);
|
|
1115
1236
|
return [];
|
|
1116
1237
|
}
|
|
1117
|
-
|
|
1238
|
+
const configState = await resolveConfigState(detected, projectDir);
|
|
1239
|
+
return this.runAllChecks(projectDir, configState, failedContent);
|
|
1118
1240
|
}
|
|
1119
1241
|
/**
|
|
1120
1242
|
* A config file that exists but failed to load also detects as "no project", and
|
|
@@ -1125,12 +1247,17 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1125
1247
|
if (await fileExists(getProjectConfigPath(projectDir))) return false;
|
|
1126
1248
|
return isSourceRepo(projectDir);
|
|
1127
1249
|
}
|
|
1128
|
-
async runAllChecks(projectDir, configState) {
|
|
1250
|
+
async runAllChecks(projectDir, configState, failedContent) {
|
|
1129
1251
|
const { result: configResult, config } = checkConfigValid(configState);
|
|
1130
1252
|
this.logCheck("Config Valid", configResult);
|
|
1131
1253
|
const sourceResult = await safeCheck("source", () => checkSourceReachable(projectDir));
|
|
1132
1254
|
const filteredConfig = config ? filterExcludedEntries(config) : null;
|
|
1133
|
-
const skillsResult = await this.resolveSkillsCheck(
|
|
1255
|
+
const skillsResult = await this.resolveSkillsCheck(
|
|
1256
|
+
config,
|
|
1257
|
+
sourceResult,
|
|
1258
|
+
projectDir,
|
|
1259
|
+
failedContent
|
|
1260
|
+
);
|
|
1134
1261
|
this.logCheck("Skills Resolved", skillsResult);
|
|
1135
1262
|
const agentsResult = filteredConfig ? await safeCheck("agents", () => checkAgentsCompiled(filteredConfig, projectDir)) : skippedResult("agents");
|
|
1136
1263
|
this.logCheck("Agents Compiled", agentsResult);
|
|
@@ -1138,9 +1265,9 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1138
1265
|
this.logCheck("No Orphans", orphansResult);
|
|
1139
1266
|
const installedResult = filteredConfig ? await safeCheck("installed", () => checkSkillsInstalled(filteredConfig, projectDir)) : skippedResult("installed");
|
|
1140
1267
|
this.logCheck("Skills Installed", installedResult);
|
|
1141
|
-
const pluginsResult =
|
|
1268
|
+
const pluginsResult = await this.resolvePluginsCheck(filteredConfig, projectDir, failedContent);
|
|
1142
1269
|
this.logCheck("Plugins Installed", pluginsResult);
|
|
1143
|
-
this.logCheck("
|
|
1270
|
+
this.logCheck("Marketplace Reachable", sourceResult);
|
|
1144
1271
|
return [
|
|
1145
1272
|
configResult,
|
|
1146
1273
|
skillsResult,
|
|
@@ -1166,15 +1293,29 @@ var Doctor = class _Doctor extends BaseCommand {
|
|
|
1166
1293
|
return skippedResult("orphans");
|
|
1167
1294
|
}
|
|
1168
1295
|
/**
|
|
1169
|
-
* The skills row, and the
|
|
1170
|
-
* skills out of,
|
|
1171
|
-
*
|
|
1296
|
+
* The skills row, and the three states in which it cannot be computed: no config to read the
|
|
1297
|
+
* skills out of, content it resolves against that the layer above has already reported broken,
|
|
1298
|
+
* and a marketplace that never loaded — so there is no populated matrix to resolve them
|
|
1299
|
+
* against, and every configured skill would be reported "not found".
|
|
1172
1300
|
*/
|
|
1173
|
-
async resolveSkillsCheck(config, sourceResult, projectDir) {
|
|
1301
|
+
async resolveSkillsCheck(config, sourceResult, projectDir, failedContent) {
|
|
1174
1302
|
if (!config) return skippedResult("skills");
|
|
1303
|
+
const blocked = contentBlockedResult("skills", failedContent);
|
|
1304
|
+
if (blocked) return blocked;
|
|
1175
1305
|
if (sourceResult.status === "fail") return sourceUnreachableSkillsResult();
|
|
1176
1306
|
return safeCheck("skills", () => checkSkillsResolved(config, matrix, projectDir));
|
|
1177
1307
|
}
|
|
1308
|
+
/**
|
|
1309
|
+
* The plugin row, and the two states in which it cannot be computed: no config to read the
|
|
1310
|
+
* plugin-mode skills out of, and a plugin registry the layer above could not parse — which
|
|
1311
|
+
* resolves as no installs at all, so every configured skill would be reported missing.
|
|
1312
|
+
*/
|
|
1313
|
+
async resolvePluginsCheck(config, projectDir, failedContent) {
|
|
1314
|
+
if (!config) return skippedResult("plugins");
|
|
1315
|
+
const blocked = contentBlockedResult("plugins", failedContent);
|
|
1316
|
+
if (blocked) return blocked;
|
|
1317
|
+
return safeCheck("plugins", () => checkPluginSkillsInstalled(config, projectDir));
|
|
1318
|
+
}
|
|
1178
1319
|
logCheck(name, result) {
|
|
1179
1320
|
for (const line of formatCheckLine(name, result)) {
|
|
1180
1321
|
this.log(line);
|