@skillcap/gdh 0.4.0 → 0.5.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/INSTALL-BUNDLE.json +1 -1
- package/README.md +9 -10
- package/node_modules/@gdh/adapters/dist/index.d.ts +25 -18
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +378 -149
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/package.json +8 -8
- package/node_modules/@gdh/authoring/dist/index.d.ts +1 -1
- package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/index.js +1 -1
- package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
- package/node_modules/@gdh/authoring/dist/project.d.ts +24 -0
- package/node_modules/@gdh/authoring/dist/project.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/project.js +51 -1
- package/node_modules/@gdh/authoring/dist/project.js.map +1 -1
- package/node_modules/@gdh/authoring/package.json +2 -2
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +226 -34
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts +1 -0
- package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.js +180 -72
- package/node_modules/@gdh/cli/dist/migrate.js.map +1 -1
- package/node_modules/@gdh/cli/dist/setup.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/setup.js +49 -1
- package/node_modules/@gdh/cli/dist/setup.js.map +1 -1
- package/node_modules/@gdh/cli/package.json +10 -10
- package/node_modules/@gdh/core/dist/index.d.ts +5 -4
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +2 -2
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/dist/guidance.d.ts.map +1 -1
- package/node_modules/@gdh/docs/dist/guidance.js +47 -0
- package/node_modules/@gdh/docs/dist/guidance.js.map +1 -1
- package/node_modules/@gdh/docs/package.json +2 -2
- package/node_modules/@gdh/mcp/dist/index.js +6 -2
- package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
- package/node_modules/@gdh/mcp/package.json +8 -8
- package/node_modules/@gdh/observability/dist/guidance-audit.js +1 -0
- package/node_modules/@gdh/observability/dist/guidance-audit.js.map +1 -1
- package/node_modules/@gdh/observability/package.json +2 -2
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/dist/index.d.ts +2 -0
- package/node_modules/@gdh/scan/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/scan/dist/index.js +1 -0
- package/node_modules/@gdh/scan/dist/index.js.map +1 -1
- package/node_modules/@gdh/scan/dist/inventory-cache.d.ts +15 -0
- package/node_modules/@gdh/scan/dist/inventory-cache.d.ts.map +1 -0
- package/node_modules/@gdh/scan/dist/inventory-cache.js +53 -0
- package/node_modules/@gdh/scan/dist/inventory-cache.js.map +1 -0
- package/node_modules/@gdh/scan/dist/onboard.d.ts +7 -0
- package/node_modules/@gdh/scan/dist/onboard.d.ts.map +1 -1
- package/node_modules/@gdh/scan/dist/onboard.js +7 -1
- package/node_modules/@gdh/scan/dist/onboard.js.map +1 -1
- package/node_modules/@gdh/scan/package.json +3 -3
- package/node_modules/@gdh/verify/package.json +7 -7
- package/package.json +11 -11
|
@@ -4,7 +4,7 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
|
-
import { readProjectConfig, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, } from "@gdh/authoring";
|
|
7
|
+
import { readProjectConfig, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, } from "@gdh/authoring";
|
|
8
8
|
import { GDH_AGENT_CONTRACT_VERSION, GDH_CURSOR_RULE_VERSION, GDH_GUIDANCE_INDEX_VERSION, GDH_GUIDANCE_UNIT_VERSION, GDH_MCP_LAUNCHER_VERSION, GDH_PROJECT_CONFIG_VERSION, GDH_RECIPE_SCHEMA_VERSION, GDH_RULES_SCHEMA_VERSION, GDH_SCENARIO_SCHEMA_VERSION, definePackageBoundary, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
|
|
9
9
|
import { createDefaultGuidanceUnits, getGuidanceStatus, resolveGuidanceQuery, } from "@gdh/docs";
|
|
10
10
|
import { inspectGuidanceAudit } from "@gdh/observability";
|
|
@@ -48,6 +48,9 @@ export const CURSOR_MIGRATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-migrate/SK
|
|
|
48
48
|
export const CURSOR_CHECK_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-check/SKILL.md";
|
|
49
49
|
export const CURSOR_PREPARE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-prepare/SKILL.md";
|
|
50
50
|
export const CURSOR_VERIFY_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-verify/SKILL.md";
|
|
51
|
+
export const CLAUDE_SCAN_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/scan.md";
|
|
52
|
+
export const CODEX_SCAN_SKILL_RELATIVE_PATH = ".codex/skills/gdh-scan/SKILL.md";
|
|
53
|
+
export const CURSOR_SCAN_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-scan/SKILL.md";
|
|
51
54
|
export const LOCAL_PATH_HINTS_RELATIVE_PATH = ".gdh-state/local-paths.json";
|
|
52
55
|
export const MCP_LAUNCHER_RELATIVE_PATH = ".gdh/bin/gdh-mcp.mjs";
|
|
53
56
|
export const GDH_MCP_SERVER_NAME = "gdh";
|
|
@@ -56,16 +59,18 @@ export async function getSupportedAgentAdaptersStatus(targetPath, options = {})
|
|
|
56
59
|
const includeUserLocal = options.includeUserLocal ?? true;
|
|
57
60
|
const integrationRootPath = resolveIntegrationRootPath(targetPath, options.integrationRootPath);
|
|
58
61
|
const guidance = await getGuidanceStatus(targetPath);
|
|
62
|
+
const pinnedVersion = await resolvePinnedVersionOrNull(targetPath);
|
|
59
63
|
const projectMcp = await inspectProjectMcpSupport(targetPath, {
|
|
60
64
|
includeUserLocal,
|
|
61
65
|
integrationRootPath,
|
|
66
|
+
pinnedVersion,
|
|
62
67
|
});
|
|
63
68
|
const [codex, claude, cursor] = await Promise.all([
|
|
64
|
-
inspectCodexAdapter(targetPath, guidance, projectMcp, {
|
|
69
|
+
inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, {
|
|
65
70
|
includeUserLocal,
|
|
66
71
|
}),
|
|
67
|
-
inspectClaudeAdapter(targetPath, guidance, projectMcp),
|
|
68
|
-
inspectCursorAdapter(targetPath, guidance, projectMcp),
|
|
72
|
+
inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVersion),
|
|
73
|
+
inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVersion),
|
|
69
74
|
]);
|
|
70
75
|
return {
|
|
71
76
|
targetPath,
|
|
@@ -80,6 +85,7 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
80
85
|
const status = await getSupportedAgentAdaptersStatus(targetPath, {
|
|
81
86
|
integrationRootPath,
|
|
82
87
|
});
|
|
88
|
+
const pinnedVersion = await resolvePinnedVersion(targetPath);
|
|
83
89
|
if (!hasReadyVisibilityChain(status.guidance) && options.allowBootstrap !== true) {
|
|
84
90
|
return {
|
|
85
91
|
targetPath,
|
|
@@ -96,26 +102,41 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
96
102
|
user: options.user ?? false,
|
|
97
103
|
devRepoPath: options.devRepoPath ?? null,
|
|
98
104
|
integrationRootPath,
|
|
105
|
+
pinnedVersion,
|
|
99
106
|
});
|
|
107
|
+
let appliedActions = actions;
|
|
100
108
|
if (!dryRun) {
|
|
109
|
+
const newActions = [];
|
|
101
110
|
for (const action of actions) {
|
|
102
111
|
if (action.state === "unchanged") {
|
|
112
|
+
newActions.push(action);
|
|
103
113
|
continue;
|
|
104
114
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
try {
|
|
116
|
+
if (action.kind === "ensure_symlink") {
|
|
117
|
+
await applySymlinkAction(action);
|
|
118
|
+
}
|
|
119
|
+
else if (action.kind === "run_command") {
|
|
120
|
+
await applyRunCommandAction(action);
|
|
121
|
+
}
|
|
122
|
+
else if (action.command?.[0] === "write_local_hints") {
|
|
123
|
+
await applyLocalHintsAction(action);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
await applyWriteFileAction(action);
|
|
127
|
+
}
|
|
128
|
+
newActions.push({ ...action, state: "applied" });
|
|
112
129
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
130
|
+
catch (error) {
|
|
131
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
132
|
+
newActions.push({
|
|
133
|
+
...action,
|
|
134
|
+
state: "blocked",
|
|
135
|
+
summary: `${action.summary} (failed: ${errorMessage})`,
|
|
136
|
+
});
|
|
116
137
|
}
|
|
117
|
-
await applyWriteFileAction(action);
|
|
118
138
|
}
|
|
139
|
+
appliedActions = newActions;
|
|
119
140
|
}
|
|
120
141
|
return {
|
|
121
142
|
targetPath,
|
|
@@ -129,7 +150,7 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
129
150
|
requestedAgents,
|
|
130
151
|
guidance: status.guidance,
|
|
131
152
|
adapters: status.adapters,
|
|
132
|
-
actions,
|
|
153
|
+
actions: appliedActions,
|
|
133
154
|
};
|
|
134
155
|
}
|
|
135
156
|
export async function inspectProjectLifecycleCompatibility(targetPath) {
|
|
@@ -285,7 +306,7 @@ export function renderCursorRule() {
|
|
|
285
306
|
"",
|
|
286
307
|
].join("\n");
|
|
287
308
|
}
|
|
288
|
-
export function renderClaudeOnboardCommand() {
|
|
309
|
+
export function renderClaudeOnboardCommand(pinnedVersion) {
|
|
289
310
|
return [
|
|
290
311
|
"---",
|
|
291
312
|
"name: gdh:onboard",
|
|
@@ -298,17 +319,17 @@ export function renderClaudeOnboardCommand() {
|
|
|
298
319
|
" - AskUserQuestion",
|
|
299
320
|
"---",
|
|
300
321
|
"<objective>",
|
|
301
|
-
|
|
322
|
+
`Finish the first-time GDH handoff after \`npx -y @skillcap/gdh@${pinnedVersion} setup\` and turn the generated GDH surface into a trustworthy starting point for real work.`,
|
|
302
323
|
"</objective>",
|
|
303
324
|
"",
|
|
304
325
|
"<process>",
|
|
305
326
|
"Follow this order:",
|
|
306
327
|
"",
|
|
307
|
-
|
|
328
|
+
`1. Confirm the selected target and current GDH state with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
308
329
|
"2. Read `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md` before asking for facts GDH already knows.",
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
330
|
+
`3. Check immediate readiness with \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\` and \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\`.`,
|
|
331
|
+
`4. If authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`; if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\`.`,
|
|
332
|
+
`5. Inspect \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\` and \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\` and call out anything draft, missing, or blocked.`,
|
|
312
333
|
"6. If GDH reports `godot_editor_not_configured`, explain that the Godot binary path is machine-local and offer to record `.gdh-state/local-paths.json` `godotEditorBinPath` once the human provides the local path.",
|
|
313
334
|
"7. Ask the human only for narrow unresolved environment or target facts.",
|
|
314
335
|
"8. End with a concise readiness summary and the exact next development step.",
|
|
@@ -318,11 +339,12 @@ export function renderClaudeOnboardCommand() {
|
|
|
318
339
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
319
340
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
320
341
|
"- Keep the output short, operational, and specific.",
|
|
342
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
321
343
|
"</rules>",
|
|
322
344
|
"",
|
|
323
345
|
].join("\n");
|
|
324
346
|
}
|
|
325
|
-
export function renderCodexOnboardSkill() {
|
|
347
|
+
export function renderCodexOnboardSkill(pinnedVersion) {
|
|
326
348
|
return [
|
|
327
349
|
"---",
|
|
328
350
|
'name: "gdh-onboard"',
|
|
@@ -342,20 +364,20 @@ export function renderCodexOnboardSkill() {
|
|
|
342
364
|
"</codex_skill_adapter>",
|
|
343
365
|
"",
|
|
344
366
|
"<objective>",
|
|
345
|
-
|
|
367
|
+
`Finish the first-time GDH handoff after \`npx -y @skillcap/gdh@${pinnedVersion} setup\` and turn the generated GDH surface into a trustworthy starting point for real work.`,
|
|
346
368
|
"</objective>",
|
|
347
369
|
"",
|
|
348
370
|
"<process>",
|
|
349
371
|
"Follow this order:",
|
|
350
372
|
"",
|
|
351
|
-
|
|
373
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
352
374
|
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
375
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
376
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
377
|
+
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
378
|
+
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
379
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
380
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
359
381
|
"- if GDH reports `godot_editor_not_configured`, explain that the Godot binary path is machine-local and offer to record `.gdh-state/local-paths.json` `godotEditorBinPath` once the user provides it",
|
|
360
382
|
"- ask only for narrow unresolved environment or target facts",
|
|
361
383
|
"- finish with a concise readiness summary and the exact next development step",
|
|
@@ -365,11 +387,12 @@ export function renderCodexOnboardSkill() {
|
|
|
365
387
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
366
388
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
367
389
|
"- Keep output short, operational, and specific.",
|
|
390
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
368
391
|
"</rules>",
|
|
369
392
|
"",
|
|
370
393
|
].join("\n");
|
|
371
394
|
}
|
|
372
|
-
export function renderCursorOnboardSkill() {
|
|
395
|
+
export function renderCursorOnboardSkill(pinnedVersion) {
|
|
373
396
|
return [
|
|
374
397
|
"---",
|
|
375
398
|
"name: gdh-onboard",
|
|
@@ -387,20 +410,20 @@ export function renderCursorOnboardSkill() {
|
|
|
387
410
|
"</cursor_skill_adapter>",
|
|
388
411
|
"",
|
|
389
412
|
"<objective>",
|
|
390
|
-
|
|
413
|
+
`Finish the first-time GDH handoff after \`npx -y @skillcap/gdh@${pinnedVersion} setup\` and turn the generated GDH surface into a trustworthy starting point for real work.`,
|
|
391
414
|
"</objective>",
|
|
392
415
|
"",
|
|
393
416
|
"<process>",
|
|
394
417
|
"Follow this order:",
|
|
395
418
|
"",
|
|
396
|
-
|
|
419
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
397
420
|
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
421
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
422
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
423
|
+
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
424
|
+
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
425
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
426
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
404
427
|
"- if GDH reports `godot_editor_not_configured`, explain that the Godot binary path is machine-local and offer to record `.gdh-state/local-paths.json` `godotEditorBinPath` once the user provides it",
|
|
405
428
|
"- ask only for narrow unresolved environment or target facts",
|
|
406
429
|
"- finish with a concise readiness summary and the exact next development step",
|
|
@@ -410,12 +433,13 @@ export function renderCursorOnboardSkill() {
|
|
|
410
433
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
411
434
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
412
435
|
"- Keep output short, operational, and specific.",
|
|
436
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
413
437
|
"</rules>",
|
|
414
438
|
"",
|
|
415
439
|
].join("\n");
|
|
416
440
|
}
|
|
417
441
|
// --- gdh-status skill renders ---
|
|
418
|
-
export function renderClaudeStatusCommand() {
|
|
442
|
+
export function renderClaudeStatusCommand(pinnedVersion) {
|
|
419
443
|
return [
|
|
420
444
|
"---",
|
|
421
445
|
"name: gdh:status",
|
|
@@ -433,8 +457,8 @@ export function renderClaudeStatusCommand() {
|
|
|
433
457
|
"<process>",
|
|
434
458
|
"Follow this order:",
|
|
435
459
|
"",
|
|
436
|
-
|
|
437
|
-
|
|
460
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field.`,
|
|
461
|
+
`2. Check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\`.`,
|
|
438
462
|
"3. Surface any degraded or unavailable capabilities.",
|
|
439
463
|
"4. Suggest the most productive next step based on current state.",
|
|
440
464
|
"</process>",
|
|
@@ -443,11 +467,12 @@ export function renderClaudeStatusCommand() {
|
|
|
443
467
|
"- Do not start editing code.",
|
|
444
468
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
445
469
|
"- Keep output short and operational.",
|
|
470
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
446
471
|
"</rules>",
|
|
447
472
|
"",
|
|
448
473
|
].join("\n");
|
|
449
474
|
}
|
|
450
|
-
export function renderCodexStatusSkill() {
|
|
475
|
+
export function renderCodexStatusSkill(pinnedVersion) {
|
|
451
476
|
return [
|
|
452
477
|
"---",
|
|
453
478
|
'name: "gdh-status"',
|
|
@@ -473,8 +498,8 @@ export function renderCodexStatusSkill() {
|
|
|
473
498
|
"<process>",
|
|
474
499
|
"Follow this order:",
|
|
475
500
|
"",
|
|
476
|
-
|
|
477
|
-
|
|
501
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
502
|
+
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
478
503
|
"- surface any degraded or unavailable capabilities",
|
|
479
504
|
"- suggest the most productive next step based on current state",
|
|
480
505
|
"</process>",
|
|
@@ -483,11 +508,12 @@ export function renderCodexStatusSkill() {
|
|
|
483
508
|
"- Do not start editing code.",
|
|
484
509
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
485
510
|
"- Keep output short and operational.",
|
|
511
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
486
512
|
"</rules>",
|
|
487
513
|
"",
|
|
488
514
|
].join("\n");
|
|
489
515
|
}
|
|
490
|
-
export function renderCursorStatusSkill() {
|
|
516
|
+
export function renderCursorStatusSkill(pinnedVersion) {
|
|
491
517
|
return [
|
|
492
518
|
"---",
|
|
493
519
|
"name: gdh-status",
|
|
@@ -511,8 +537,8 @@ export function renderCursorStatusSkill() {
|
|
|
511
537
|
"<process>",
|
|
512
538
|
"Follow this order:",
|
|
513
539
|
"",
|
|
514
|
-
|
|
515
|
-
|
|
540
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
541
|
+
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
516
542
|
"- surface any degraded or unavailable capabilities",
|
|
517
543
|
"- suggest the most productive next step based on current state",
|
|
518
544
|
"</process>",
|
|
@@ -521,12 +547,123 @@ export function renderCursorStatusSkill() {
|
|
|
521
547
|
"- Do not start editing code.",
|
|
522
548
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
523
549
|
"- Keep output short and operational.",
|
|
550
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
551
|
+
"</rules>",
|
|
552
|
+
"",
|
|
553
|
+
].join("\n");
|
|
554
|
+
}
|
|
555
|
+
// --- gdh-scan skill renders ---
|
|
556
|
+
export function renderClaudeScanCommand(pinnedVersion) {
|
|
557
|
+
return [
|
|
558
|
+
"---",
|
|
559
|
+
"name: gdh:scan",
|
|
560
|
+
"description: Refresh inventory cache and explain persistence effect",
|
|
561
|
+
"allowed-tools:",
|
|
562
|
+
" - Read",
|
|
563
|
+
" - Grep",
|
|
564
|
+
" - Glob",
|
|
565
|
+
" - Bash",
|
|
566
|
+
"---",
|
|
567
|
+
"<objective>",
|
|
568
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
569
|
+
"</objective>",
|
|
570
|
+
"",
|
|
571
|
+
"<process>",
|
|
572
|
+
"Follow this order:",
|
|
573
|
+
"",
|
|
574
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} scan\` and parse the \`persisted\` field from the envelope.`,
|
|
575
|
+
"2. Check the `mode` field: `create`, `unchanged`, `overwrite`, or `null`.",
|
|
576
|
+
"3. Explain the persistence effect; if `null`, the target is not onboarded and no disk write occurred.",
|
|
577
|
+
"</process>",
|
|
578
|
+
"",
|
|
579
|
+
"<rules>",
|
|
580
|
+
"- Do not edit the persisted inventory directly.",
|
|
581
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
582
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
583
|
+
"</rules>",
|
|
584
|
+
"",
|
|
585
|
+
].join("\n");
|
|
586
|
+
}
|
|
587
|
+
export function renderCodexScanSkill(pinnedVersion) {
|
|
588
|
+
return [
|
|
589
|
+
"---",
|
|
590
|
+
'name: "gdh-scan"',
|
|
591
|
+
'description: "Refresh inventory cache and explain persistence effect"',
|
|
592
|
+
"metadata:",
|
|
593
|
+
' short-description: "Refresh inventory cache and explain persistence effect"',
|
|
594
|
+
"---",
|
|
595
|
+
"",
|
|
596
|
+
"<codex_skill_adapter>",
|
|
597
|
+
"## Invocation",
|
|
598
|
+
"- This skill is invoked when the user says `/gdh-scan` or mentions `$gdh-scan`.",
|
|
599
|
+
"- Treat any extra user text as additional scan context.",
|
|
600
|
+
"",
|
|
601
|
+
"## User questions",
|
|
602
|
+
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
603
|
+
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
604
|
+
"</codex_skill_adapter>",
|
|
605
|
+
"",
|
|
606
|
+
"<objective>",
|
|
607
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
608
|
+
"</objective>",
|
|
609
|
+
"",
|
|
610
|
+
"<process>",
|
|
611
|
+
"Follow this order:",
|
|
612
|
+
"",
|
|
613
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
614
|
+
"- parse the `persisted` field from the envelope",
|
|
615
|
+
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
616
|
+
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
617
|
+
"</process>",
|
|
618
|
+
"",
|
|
619
|
+
"<rules>",
|
|
620
|
+
"- Do not edit the persisted inventory directly.",
|
|
621
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
622
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
623
|
+
"</rules>",
|
|
624
|
+
"",
|
|
625
|
+
].join("\n");
|
|
626
|
+
}
|
|
627
|
+
export function renderCursorScanSkill(pinnedVersion) {
|
|
628
|
+
return [
|
|
629
|
+
"---",
|
|
630
|
+
"name: gdh-scan",
|
|
631
|
+
'description: "Refresh inventory cache and explain persistence effect"',
|
|
632
|
+
"---",
|
|
633
|
+
"",
|
|
634
|
+
"<cursor_skill_adapter>",
|
|
635
|
+
"## Invocation",
|
|
636
|
+
"- This skill is invoked when the user says `/gdh-scan` or mentions `gdh-scan`.",
|
|
637
|
+
"- Treat any extra user text as additional scan context.",
|
|
638
|
+
"",
|
|
639
|
+
"## User questions",
|
|
640
|
+
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
641
|
+
"- Keep questions conversational and concise.",
|
|
642
|
+
"</cursor_skill_adapter>",
|
|
643
|
+
"",
|
|
644
|
+
"<objective>",
|
|
645
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
646
|
+
"</objective>",
|
|
647
|
+
"",
|
|
648
|
+
"<process>",
|
|
649
|
+
"Follow this order:",
|
|
650
|
+
"",
|
|
651
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
652
|
+
"- parse the `persisted` field from the envelope",
|
|
653
|
+
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
654
|
+
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
655
|
+
"</process>",
|
|
656
|
+
"",
|
|
657
|
+
"<rules>",
|
|
658
|
+
"- Do not edit the persisted inventory directly.",
|
|
659
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
660
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
524
661
|
"</rules>",
|
|
525
662
|
"",
|
|
526
663
|
].join("\n");
|
|
527
664
|
}
|
|
528
665
|
// --- gdh-migrate skill renders ---
|
|
529
|
-
export function renderClaudeMigrateCommand() {
|
|
666
|
+
export function renderClaudeMigrateCommand(pinnedVersion) {
|
|
530
667
|
return [
|
|
531
668
|
"---",
|
|
532
669
|
"name: gdh:migrate",
|
|
@@ -545,10 +682,10 @@ export function renderClaudeMigrateCommand() {
|
|
|
545
682
|
"<process>",
|
|
546
683
|
"Follow this order:",
|
|
547
684
|
"",
|
|
548
|
-
|
|
685
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations.`,
|
|
549
686
|
"2. Explain what each migration step will change and why.",
|
|
550
|
-
|
|
551
|
-
|
|
687
|
+
`3. Offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves.`,
|
|
688
|
+
`4. After apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded.`,
|
|
552
689
|
"</process>",
|
|
553
690
|
"",
|
|
554
691
|
"<rules>",
|
|
@@ -559,7 +696,7 @@ export function renderClaudeMigrateCommand() {
|
|
|
559
696
|
"",
|
|
560
697
|
].join("\n");
|
|
561
698
|
}
|
|
562
|
-
export function renderCodexMigrateSkill() {
|
|
699
|
+
export function renderCodexMigrateSkill(pinnedVersion) {
|
|
563
700
|
return [
|
|
564
701
|
"---",
|
|
565
702
|
'name: "gdh-migrate"',
|
|
@@ -585,10 +722,10 @@ export function renderCodexMigrateSkill() {
|
|
|
585
722
|
"<process>",
|
|
586
723
|
"Follow this order:",
|
|
587
724
|
"",
|
|
588
|
-
|
|
725
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations`,
|
|
589
726
|
"- explain what each migration step will change and why",
|
|
590
|
-
|
|
591
|
-
|
|
727
|
+
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves`,
|
|
728
|
+
`- after apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded`,
|
|
592
729
|
"</process>",
|
|
593
730
|
"",
|
|
594
731
|
"<rules>",
|
|
@@ -599,7 +736,7 @@ export function renderCodexMigrateSkill() {
|
|
|
599
736
|
"",
|
|
600
737
|
].join("\n");
|
|
601
738
|
}
|
|
602
|
-
export function renderCursorMigrateSkill() {
|
|
739
|
+
export function renderCursorMigrateSkill(pinnedVersion) {
|
|
603
740
|
return [
|
|
604
741
|
"---",
|
|
605
742
|
"name: gdh-migrate",
|
|
@@ -623,10 +760,10 @@ export function renderCursorMigrateSkill() {
|
|
|
623
760
|
"<process>",
|
|
624
761
|
"Follow this order:",
|
|
625
762
|
"",
|
|
626
|
-
|
|
763
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations`,
|
|
627
764
|
"- explain what each migration step will change and why",
|
|
628
|
-
|
|
629
|
-
|
|
765
|
+
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves`,
|
|
766
|
+
`- after apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded`,
|
|
630
767
|
"</process>",
|
|
631
768
|
"",
|
|
632
769
|
"<rules>",
|
|
@@ -638,7 +775,7 @@ export function renderCursorMigrateSkill() {
|
|
|
638
775
|
].join("\n");
|
|
639
776
|
}
|
|
640
777
|
// --- gdh-check skill renders ---
|
|
641
|
-
export function renderClaudeCheckCommand() {
|
|
778
|
+
export function renderClaudeCheckCommand(pinnedVersion) {
|
|
642
779
|
return [
|
|
643
780
|
"---",
|
|
644
781
|
"name: gdh:check",
|
|
@@ -656,7 +793,7 @@ export function renderClaudeCheckCommand() {
|
|
|
656
793
|
"<process>",
|
|
657
794
|
"Follow this order:",
|
|
658
795
|
"",
|
|
659
|
-
|
|
796
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`.`,
|
|
660
797
|
"2. Explain each diagnostic finding with severity and provenance.",
|
|
661
798
|
"3. Surface any import-state caveats or editor-side warnings.",
|
|
662
799
|
"4. If issues found, suggest concrete remediation steps.",
|
|
@@ -670,7 +807,7 @@ export function renderClaudeCheckCommand() {
|
|
|
670
807
|
"",
|
|
671
808
|
].join("\n");
|
|
672
809
|
}
|
|
673
|
-
export function renderCodexCheckSkill() {
|
|
810
|
+
export function renderCodexCheckSkill(pinnedVersion) {
|
|
674
811
|
return [
|
|
675
812
|
"---",
|
|
676
813
|
'name: "gdh-check"',
|
|
@@ -696,7 +833,7 @@ export function renderCodexCheckSkill() {
|
|
|
696
833
|
"<process>",
|
|
697
834
|
"Follow this order:",
|
|
698
835
|
"",
|
|
699
|
-
|
|
836
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
700
837
|
"- explain each diagnostic finding with severity and provenance",
|
|
701
838
|
"- surface any import-state caveats or editor-side warnings",
|
|
702
839
|
"- if issues found, suggest concrete remediation steps",
|
|
@@ -710,7 +847,7 @@ export function renderCodexCheckSkill() {
|
|
|
710
847
|
"",
|
|
711
848
|
].join("\n");
|
|
712
849
|
}
|
|
713
|
-
export function renderCursorCheckSkill() {
|
|
850
|
+
export function renderCursorCheckSkill(pinnedVersion) {
|
|
714
851
|
return [
|
|
715
852
|
"---",
|
|
716
853
|
"name: gdh-check",
|
|
@@ -734,7 +871,7 @@ export function renderCursorCheckSkill() {
|
|
|
734
871
|
"<process>",
|
|
735
872
|
"Follow this order:",
|
|
736
873
|
"",
|
|
737
|
-
|
|
874
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
738
875
|
"- explain each diagnostic finding with severity and provenance",
|
|
739
876
|
"- surface any import-state caveats or editor-side warnings",
|
|
740
877
|
"- if issues found, suggest concrete remediation steps",
|
|
@@ -749,7 +886,7 @@ export function renderCursorCheckSkill() {
|
|
|
749
886
|
].join("\n");
|
|
750
887
|
}
|
|
751
888
|
// --- gdh-prepare skill renders ---
|
|
752
|
-
export function renderClaudePrepareCommand() {
|
|
889
|
+
export function renderClaudePrepareCommand(pinnedVersion) {
|
|
753
890
|
return [
|
|
754
891
|
"---",
|
|
755
892
|
"name: gdh:prepare",
|
|
@@ -768,11 +905,11 @@ export function renderClaudePrepareCommand() {
|
|
|
768
905
|
"<process>",
|
|
769
906
|
"Follow this order:",
|
|
770
907
|
"",
|
|
771
|
-
|
|
908
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions.`,
|
|
772
909
|
"2. Explain what hydration and import refresh will do.",
|
|
773
|
-
|
|
910
|
+
`3. If the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\`.`,
|
|
774
911
|
"4. If a `--source-target` is relevant, explain when and why to use it.",
|
|
775
|
-
|
|
912
|
+
`5. Verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
776
913
|
"</process>",
|
|
777
914
|
"",
|
|
778
915
|
"<rules>",
|
|
@@ -783,7 +920,7 @@ export function renderClaudePrepareCommand() {
|
|
|
783
920
|
"",
|
|
784
921
|
].join("\n");
|
|
785
922
|
}
|
|
786
|
-
export function renderCodexPrepareSkill() {
|
|
923
|
+
export function renderCodexPrepareSkill(pinnedVersion) {
|
|
787
924
|
return [
|
|
788
925
|
"---",
|
|
789
926
|
'name: "gdh-prepare"',
|
|
@@ -809,11 +946,11 @@ export function renderCodexPrepareSkill() {
|
|
|
809
946
|
"<process>",
|
|
810
947
|
"Follow this order:",
|
|
811
948
|
"",
|
|
812
|
-
|
|
949
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
813
950
|
"- explain what hydration and import refresh will do",
|
|
814
|
-
|
|
951
|
+
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
815
952
|
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
816
|
-
|
|
953
|
+
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
817
954
|
"</process>",
|
|
818
955
|
"",
|
|
819
956
|
"<rules>",
|
|
@@ -824,7 +961,7 @@ export function renderCodexPrepareSkill() {
|
|
|
824
961
|
"",
|
|
825
962
|
].join("\n");
|
|
826
963
|
}
|
|
827
|
-
export function renderCursorPrepareSkill() {
|
|
964
|
+
export function renderCursorPrepareSkill(pinnedVersion) {
|
|
828
965
|
return [
|
|
829
966
|
"---",
|
|
830
967
|
"name: gdh-prepare",
|
|
@@ -848,11 +985,11 @@ export function renderCursorPrepareSkill() {
|
|
|
848
985
|
"<process>",
|
|
849
986
|
"Follow this order:",
|
|
850
987
|
"",
|
|
851
|
-
|
|
988
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
852
989
|
"- explain what hydration and import refresh will do",
|
|
853
|
-
|
|
990
|
+
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
854
991
|
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
855
|
-
|
|
992
|
+
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
856
993
|
"</process>",
|
|
857
994
|
"",
|
|
858
995
|
"<rules>",
|
|
@@ -864,7 +1001,7 @@ export function renderCursorPrepareSkill() {
|
|
|
864
1001
|
].join("\n");
|
|
865
1002
|
}
|
|
866
1003
|
// --- gdh-verify skill renders ---
|
|
867
|
-
export function renderClaudeVerifyCommand() {
|
|
1004
|
+
export function renderClaudeVerifyCommand(pinnedVersion) {
|
|
868
1005
|
return [
|
|
869
1006
|
"---",
|
|
870
1007
|
"name: gdh:verify",
|
|
@@ -883,8 +1020,8 @@ export function renderClaudeVerifyCommand() {
|
|
|
883
1020
|
"Follow this order:",
|
|
884
1021
|
"",
|
|
885
1022
|
"1. Identify changed files from git diff or user input.",
|
|
886
|
-
|
|
887
|
-
|
|
1023
|
+
`2. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds.`,
|
|
1024
|
+
`3. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility.`,
|
|
888
1025
|
"4. Summarize gaps between recommended and performed validation.",
|
|
889
1026
|
"5. Suggest specific next verification steps.",
|
|
890
1027
|
"</process>",
|
|
@@ -897,7 +1034,7 @@ export function renderClaudeVerifyCommand() {
|
|
|
897
1034
|
"",
|
|
898
1035
|
].join("\n");
|
|
899
1036
|
}
|
|
900
|
-
export function renderCodexVerifySkill() {
|
|
1037
|
+
export function renderCodexVerifySkill(pinnedVersion) {
|
|
901
1038
|
return [
|
|
902
1039
|
"---",
|
|
903
1040
|
'name: "gdh-verify"',
|
|
@@ -924,8 +1061,8 @@ export function renderCodexVerifySkill() {
|
|
|
924
1061
|
"Follow this order:",
|
|
925
1062
|
"",
|
|
926
1063
|
"- identify changed files from git diff or user input",
|
|
927
|
-
|
|
928
|
-
|
|
1064
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1065
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
929
1066
|
"- summarize gaps between recommended and performed validation",
|
|
930
1067
|
"- suggest specific next verification steps",
|
|
931
1068
|
"</process>",
|
|
@@ -938,7 +1075,7 @@ export function renderCodexVerifySkill() {
|
|
|
938
1075
|
"",
|
|
939
1076
|
].join("\n");
|
|
940
1077
|
}
|
|
941
|
-
export function renderCursorVerifySkill() {
|
|
1078
|
+
export function renderCursorVerifySkill(pinnedVersion) {
|
|
942
1079
|
return [
|
|
943
1080
|
"---",
|
|
944
1081
|
"name: gdh-verify",
|
|
@@ -963,8 +1100,8 @@ export function renderCursorVerifySkill() {
|
|
|
963
1100
|
"Follow this order:",
|
|
964
1101
|
"",
|
|
965
1102
|
"- identify changed files from git diff or user input",
|
|
966
|
-
|
|
967
|
-
|
|
1103
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1104
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
968
1105
|
"- summarize gaps between recommended and performed validation",
|
|
969
1106
|
"- suggest specific next verification steps",
|
|
970
1107
|
"</process>",
|
|
@@ -980,11 +1117,13 @@ export function renderCursorVerifySkill() {
|
|
|
980
1117
|
async function inspectProjectMcpSupport(targetPath, options) {
|
|
981
1118
|
const projectConfig = await readProjectConfig(targetPath);
|
|
982
1119
|
const enabled = resolveProjectMcpEnabled(projectConfig);
|
|
983
|
-
const launcherContent =
|
|
1120
|
+
const launcherContent = options.pinnedVersion === null
|
|
1121
|
+
? null
|
|
1122
|
+
: renderManagedMcpLauncher(options.pinnedVersion);
|
|
984
1123
|
const managedMcpEntry = buildManagedMcpServerEntry({
|
|
985
1124
|
targetPath,
|
|
986
1125
|
integrationRootPath: options.integrationRootPath,
|
|
987
|
-
launcherPathForConfig:
|
|
1126
|
+
launcherPathForConfig: path.resolve(options.integrationRootPath, MCP_LAUNCHER_RELATIVE_PATH),
|
|
988
1127
|
});
|
|
989
1128
|
const [projectFile, cursorFile, launcherSource, localPathHints] = await Promise.all([
|
|
990
1129
|
inspectJsonFile(path.join(options.integrationRootPath, PROJECT_MCP_RELATIVE_PATH)),
|
|
@@ -1090,6 +1229,13 @@ function inspectLauncherFile(launcherSource, expectedContent, enabled, bootstrap
|
|
|
1090
1229
|
summary: "The managed GDH MCP launcher is disabled for this target.",
|
|
1091
1230
|
};
|
|
1092
1231
|
}
|
|
1232
|
+
if (expectedContent === null) {
|
|
1233
|
+
return {
|
|
1234
|
+
present: launcherSource !== null,
|
|
1235
|
+
state: "missing",
|
|
1236
|
+
summary: "The managed GDH MCP launcher is pending project onboard: no `gdh_version` is pinned yet, so there is no expected launcher content to compare against.",
|
|
1237
|
+
};
|
|
1238
|
+
}
|
|
1093
1239
|
if (launcherSource === null) {
|
|
1094
1240
|
return {
|
|
1095
1241
|
present: false,
|
|
@@ -1182,6 +1328,20 @@ async function inspectCodexRegistration(targetPath, enabled, codexServerName, co
|
|
|
1182
1328
|
};
|
|
1183
1329
|
}
|
|
1184
1330
|
function inspectCodexSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
|
|
1331
|
+
if (expectedContent === null) {
|
|
1332
|
+
return [
|
|
1333
|
+
createSurfaceStatus({
|
|
1334
|
+
kind: "skill_file",
|
|
1335
|
+
scope: "repo",
|
|
1336
|
+
targetPath,
|
|
1337
|
+
relativePath,
|
|
1338
|
+
present: content !== null,
|
|
1339
|
+
state: "missing",
|
|
1340
|
+
summary: `Codex ${skillName} skill cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1341
|
+
version: null,
|
|
1342
|
+
}),
|
|
1343
|
+
];
|
|
1344
|
+
}
|
|
1185
1345
|
return [
|
|
1186
1346
|
createSurfaceStatus({
|
|
1187
1347
|
kind: "skill_file",
|
|
@@ -1204,6 +1364,20 @@ function inspectCodexSkillSurface(targetPath, relativePath, content, expectedCon
|
|
|
1204
1364
|
];
|
|
1205
1365
|
}
|
|
1206
1366
|
function inspectClaudeCommandSurface(targetPath, relativePath, content, expectedContent, commandName) {
|
|
1367
|
+
if (expectedContent === null) {
|
|
1368
|
+
return [
|
|
1369
|
+
createSurfaceStatus({
|
|
1370
|
+
kind: "command_file",
|
|
1371
|
+
scope: "repo",
|
|
1372
|
+
targetPath,
|
|
1373
|
+
relativePath,
|
|
1374
|
+
present: content !== null,
|
|
1375
|
+
state: "missing",
|
|
1376
|
+
summary: `Claude ${commandName} command cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1377
|
+
version: null,
|
|
1378
|
+
}),
|
|
1379
|
+
];
|
|
1380
|
+
}
|
|
1207
1381
|
return [
|
|
1208
1382
|
createSurfaceStatus({
|
|
1209
1383
|
kind: "command_file",
|
|
@@ -1226,6 +1400,20 @@ function inspectClaudeCommandSurface(targetPath, relativePath, content, expected
|
|
|
1226
1400
|
];
|
|
1227
1401
|
}
|
|
1228
1402
|
function inspectCursorSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
|
|
1403
|
+
if (expectedContent === null) {
|
|
1404
|
+
return [
|
|
1405
|
+
createSurfaceStatus({
|
|
1406
|
+
kind: "skill_file",
|
|
1407
|
+
scope: "repo",
|
|
1408
|
+
targetPath,
|
|
1409
|
+
relativePath,
|
|
1410
|
+
present: content !== null,
|
|
1411
|
+
state: "missing",
|
|
1412
|
+
summary: `Cursor ${skillName} skill cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1413
|
+
version: null,
|
|
1414
|
+
}),
|
|
1415
|
+
];
|
|
1416
|
+
}
|
|
1229
1417
|
return [
|
|
1230
1418
|
createSurfaceStatus({
|
|
1231
1419
|
kind: "skill_file",
|
|
@@ -1247,7 +1435,7 @@ function inspectCursorSkillSurface(targetPath, relativePath, content, expectedCo
|
|
|
1247
1435
|
}),
|
|
1248
1436
|
];
|
|
1249
1437
|
}
|
|
1250
|
-
async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
1438
|
+
async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, options) {
|
|
1251
1439
|
const codexSkillPath = path.join(targetPath, CODEX_ONBOARD_SKILL_RELATIVE_PATH);
|
|
1252
1440
|
const codexSkillContent = await fs.readFile(codexSkillPath, "utf8").catch(() => null);
|
|
1253
1441
|
const codexStatusContent = await fs.readFile(path.join(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
@@ -1255,6 +1443,14 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
|
1255
1443
|
const codexCheckContent = await fs.readFile(path.join(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1256
1444
|
const codexPrepareContent = await fs.readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1257
1445
|
const codexVerifyContent = await fs.readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1446
|
+
const codexScanContent = await fs.readFile(path.join(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1447
|
+
const expectedCodexOnboardSkill = pinnedVersion === null ? null : renderCodexOnboardSkill(pinnedVersion);
|
|
1448
|
+
const expectedCodexStatusSkill = pinnedVersion === null ? null : renderCodexStatusSkill(pinnedVersion);
|
|
1449
|
+
const expectedCodexMigrateSkill = pinnedVersion === null ? null : renderCodexMigrateSkill(pinnedVersion);
|
|
1450
|
+
const expectedCodexCheckSkill = pinnedVersion === null ? null : renderCodexCheckSkill(pinnedVersion);
|
|
1451
|
+
const expectedCodexPrepareSkill = pinnedVersion === null ? null : renderCodexPrepareSkill(pinnedVersion);
|
|
1452
|
+
const expectedCodexVerifySkill = pinnedVersion === null ? null : renderCodexVerifySkill(pinnedVersion);
|
|
1453
|
+
const expectedCodexScanSkill = pinnedVersion === null ? null : renderCodexScanSkill(pinnedVersion);
|
|
1258
1454
|
const surfaces = [
|
|
1259
1455
|
createSurfaceStatus({
|
|
1260
1456
|
kind: "canonical_entrypoint",
|
|
@@ -1282,21 +1478,26 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
|
1282
1478
|
present: codexSkillContent !== null,
|
|
1283
1479
|
state: codexSkillContent === null
|
|
1284
1480
|
? "missing"
|
|
1285
|
-
:
|
|
1286
|
-
? "
|
|
1287
|
-
:
|
|
1481
|
+
: expectedCodexOnboardSkill === null
|
|
1482
|
+
? "missing"
|
|
1483
|
+
: codexSkillContent === expectedCodexOnboardSkill
|
|
1484
|
+
? "ready"
|
|
1485
|
+
: "misconfigured",
|
|
1288
1486
|
summary: codexSkillContent === null
|
|
1289
1487
|
? "Codex onboarding handoff is missing and should install `/gdh-onboard` under .codex/skills/."
|
|
1290
|
-
:
|
|
1291
|
-
? "Codex
|
|
1292
|
-
:
|
|
1488
|
+
: expectedCodexOnboardSkill === null
|
|
1489
|
+
? "Codex onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1490
|
+
: codexSkillContent === expectedCodexOnboardSkill
|
|
1491
|
+
? "Codex can discover the managed `/gdh-onboard` handoff skill."
|
|
1492
|
+
: "Codex onboarding handoff exists but no longer matches the expected managed GDH skill.",
|
|
1293
1493
|
version: null,
|
|
1294
1494
|
}),
|
|
1295
|
-
...inspectCodexSkillSurface(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH, codexStatusContent,
|
|
1296
|
-
...inspectCodexSkillSurface(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH, codexMigrateContent,
|
|
1297
|
-
...inspectCodexSkillSurface(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH, codexCheckContent,
|
|
1298
|
-
...inspectCodexSkillSurface(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH, codexPrepareContent,
|
|
1299
|
-
...inspectCodexSkillSurface(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH, codexVerifyContent,
|
|
1495
|
+
...inspectCodexSkillSurface(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH, codexStatusContent, expectedCodexStatusSkill, "gdh-status"),
|
|
1496
|
+
...inspectCodexSkillSurface(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH, codexMigrateContent, expectedCodexMigrateSkill, "gdh-migrate"),
|
|
1497
|
+
...inspectCodexSkillSurface(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH, codexCheckContent, expectedCodexCheckSkill, "gdh-check"),
|
|
1498
|
+
...inspectCodexSkillSurface(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH, codexPrepareContent, expectedCodexPrepareSkill, "gdh-prepare"),
|
|
1499
|
+
...inspectCodexSkillSurface(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH, codexVerifyContent, expectedCodexVerifySkill, "gdh-verify"),
|
|
1500
|
+
...inspectCodexSkillSurface(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH, codexScanContent, expectedCodexScanSkill, "gdh-scan"),
|
|
1300
1501
|
];
|
|
1301
1502
|
if (projectMcp.enabled) {
|
|
1302
1503
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1325,7 +1526,7 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
|
1325
1526
|
}
|
|
1326
1527
|
return createAgentStatus("codex", guidance, surfaces);
|
|
1327
1528
|
}
|
|
1328
|
-
async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
1529
|
+
async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVersion) {
|
|
1329
1530
|
const absolutePath = path.join(targetPath, CLAUDE_SHIM_RELATIVE_PATH);
|
|
1330
1531
|
const onboardCommandPath = path.join(targetPath, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH);
|
|
1331
1532
|
const lstat = await fs.lstat(absolutePath).catch(() => null);
|
|
@@ -1335,10 +1536,18 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
|
1335
1536
|
const claudeCheckContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1336
1537
|
const claudePrepareContent = await fs.readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1337
1538
|
const claudeVerifyContent = await fs.readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1539
|
+
const claudeScanContent = await fs.readFile(path.join(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1338
1540
|
let detectedTarget = null;
|
|
1339
1541
|
if (lstat?.isSymbolicLink()) {
|
|
1340
1542
|
detectedTarget = await fs.readlink(absolutePath).catch(() => null);
|
|
1341
1543
|
}
|
|
1544
|
+
const expectedClaudeOnboardCommand = pinnedVersion === null ? null : renderClaudeOnboardCommand(pinnedVersion);
|
|
1545
|
+
const expectedClaudeStatusCommand = pinnedVersion === null ? null : renderClaudeStatusCommand(pinnedVersion);
|
|
1546
|
+
const expectedClaudeMigrateCommand = pinnedVersion === null ? null : renderClaudeMigrateCommand(pinnedVersion);
|
|
1547
|
+
const expectedClaudeCheckCommand = pinnedVersion === null ? null : renderClaudeCheckCommand(pinnedVersion);
|
|
1548
|
+
const expectedClaudePrepareCommand = pinnedVersion === null ? null : renderClaudePrepareCommand(pinnedVersion);
|
|
1549
|
+
const expectedClaudeVerifyCommand = pinnedVersion === null ? null : renderClaudeVerifyCommand(pinnedVersion);
|
|
1550
|
+
const expectedClaudeScanCommand = pinnedVersion === null ? null : renderClaudeScanCommand(pinnedVersion);
|
|
1342
1551
|
const surfaces = [
|
|
1343
1552
|
createSurfaceStatus({
|
|
1344
1553
|
kind: "symlink",
|
|
@@ -1368,21 +1577,26 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
|
1368
1577
|
present: onboardCommandContent !== null,
|
|
1369
1578
|
state: onboardCommandContent === null
|
|
1370
1579
|
? "missing"
|
|
1371
|
-
:
|
|
1372
|
-
? "
|
|
1373
|
-
:
|
|
1580
|
+
: expectedClaudeOnboardCommand === null
|
|
1581
|
+
? "missing"
|
|
1582
|
+
: onboardCommandContent === expectedClaudeOnboardCommand
|
|
1583
|
+
? "ready"
|
|
1584
|
+
: "misconfigured",
|
|
1374
1585
|
summary: onboardCommandContent === null
|
|
1375
1586
|
? "Claude onboarding handoff is missing and should install `/gdh-onboard` under .claude/commands/."
|
|
1376
|
-
:
|
|
1377
|
-
? "Claude
|
|
1378
|
-
:
|
|
1587
|
+
: expectedClaudeOnboardCommand === null
|
|
1588
|
+
? "Claude onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1589
|
+
: onboardCommandContent === expectedClaudeOnboardCommand
|
|
1590
|
+
? "Claude can discover the managed `/gdh-onboard` handoff command."
|
|
1591
|
+
: "Claude onboarding handoff exists but no longer matches the expected managed GDH command.",
|
|
1379
1592
|
version: null,
|
|
1380
1593
|
}),
|
|
1381
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent,
|
|
1382
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent,
|
|
1383
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, claudeCheckContent,
|
|
1384
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, claudePrepareContent,
|
|
1385
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, claudeVerifyContent,
|
|
1594
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent, expectedClaudeStatusCommand, "gdh-status"),
|
|
1595
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent, expectedClaudeMigrateCommand, "gdh-migrate"),
|
|
1596
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, claudeCheckContent, expectedClaudeCheckCommand, "gdh-check"),
|
|
1597
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, claudePrepareContent, expectedClaudePrepareCommand, "gdh-prepare"),
|
|
1598
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, claudeVerifyContent, expectedClaudeVerifyCommand, "gdh-verify"),
|
|
1599
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH, claudeScanContent, expectedClaudeScanCommand, "gdh-scan"),
|
|
1386
1600
|
];
|
|
1387
1601
|
if (projectMcp.enabled) {
|
|
1388
1602
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1409,7 +1623,7 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
|
1409
1623
|
}
|
|
1410
1624
|
return createAgentStatus("claude", guidance, surfaces);
|
|
1411
1625
|
}
|
|
1412
|
-
async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
|
|
1626
|
+
async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVersion) {
|
|
1413
1627
|
const absolutePath = path.join(targetPath, CURSOR_RULE_RELATIVE_PATH);
|
|
1414
1628
|
const onboardSkillPath = path.join(targetPath, CURSOR_ONBOARD_SKILL_RELATIVE_PATH);
|
|
1415
1629
|
const content = await fs.readFile(absolutePath, "utf8").catch(() => null);
|
|
@@ -1419,8 +1633,16 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
|
|
|
1419
1633
|
const cursorCheckContent = await fs.readFile(path.join(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1420
1634
|
const cursorPrepareContent = await fs.readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1421
1635
|
const cursorVerifyContent = await fs.readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1636
|
+
const cursorScanContent = await fs.readFile(path.join(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1422
1637
|
const expectedContent = renderCursorRule();
|
|
1423
1638
|
const version = readCursorRuleVersion(content);
|
|
1639
|
+
const expectedCursorOnboardSkill = pinnedVersion === null ? null : renderCursorOnboardSkill(pinnedVersion);
|
|
1640
|
+
const expectedCursorStatusSkill = pinnedVersion === null ? null : renderCursorStatusSkill(pinnedVersion);
|
|
1641
|
+
const expectedCursorMigrateSkill = pinnedVersion === null ? null : renderCursorMigrateSkill(pinnedVersion);
|
|
1642
|
+
const expectedCursorCheckSkill = pinnedVersion === null ? null : renderCursorCheckSkill(pinnedVersion);
|
|
1643
|
+
const expectedCursorPrepareSkill = pinnedVersion === null ? null : renderCursorPrepareSkill(pinnedVersion);
|
|
1644
|
+
const expectedCursorVerifySkill = pinnedVersion === null ? null : renderCursorVerifySkill(pinnedVersion);
|
|
1645
|
+
const expectedCursorScanSkill = pinnedVersion === null ? null : renderCursorScanSkill(pinnedVersion);
|
|
1424
1646
|
const surfaces = [
|
|
1425
1647
|
createSurfaceStatus({
|
|
1426
1648
|
kind: "rule_file",
|
|
@@ -1448,21 +1670,26 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
|
|
|
1448
1670
|
present: onboardSkillContent !== null,
|
|
1449
1671
|
state: onboardSkillContent === null
|
|
1450
1672
|
? "missing"
|
|
1451
|
-
:
|
|
1452
|
-
? "
|
|
1453
|
-
:
|
|
1673
|
+
: expectedCursorOnboardSkill === null
|
|
1674
|
+
? "missing"
|
|
1675
|
+
: onboardSkillContent === expectedCursorOnboardSkill
|
|
1676
|
+
? "ready"
|
|
1677
|
+
: "misconfigured",
|
|
1454
1678
|
summary: onboardSkillContent === null
|
|
1455
1679
|
? "Cursor onboarding handoff is missing and should install `/gdh-onboard` under .cursor/skills/."
|
|
1456
|
-
:
|
|
1457
|
-
? "Cursor
|
|
1458
|
-
:
|
|
1680
|
+
: expectedCursorOnboardSkill === null
|
|
1681
|
+
? "Cursor onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1682
|
+
: onboardSkillContent === expectedCursorOnboardSkill
|
|
1683
|
+
? "Cursor can discover the managed `/gdh-onboard` handoff skill."
|
|
1684
|
+
: "Cursor onboarding handoff exists but no longer matches the expected managed GDH skill.",
|
|
1459
1685
|
version: null,
|
|
1460
1686
|
}),
|
|
1461
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH, cursorStatusContent,
|
|
1462
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, cursorMigrateContent,
|
|
1463
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH, cursorCheckContent,
|
|
1464
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH, cursorPrepareContent,
|
|
1465
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH, cursorVerifyContent,
|
|
1687
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH, cursorStatusContent, expectedCursorStatusSkill, "gdh-status"),
|
|
1688
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, cursorMigrateContent, expectedCursorMigrateSkill, "gdh-migrate"),
|
|
1689
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH, cursorCheckContent, expectedCursorCheckSkill, "gdh-check"),
|
|
1690
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH, cursorPrepareContent, expectedCursorPrepareSkill, "gdh-prepare"),
|
|
1691
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH, cursorVerifyContent, expectedCursorVerifySkill, "gdh-verify"),
|
|
1692
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH, cursorScanContent, expectedCursorScanSkill, "gdh-scan"),
|
|
1466
1693
|
];
|
|
1467
1694
|
if (projectMcp.enabled) {
|
|
1468
1695
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1552,6 +1779,7 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
1552
1779
|
const projectMcp = await inspectProjectMcpSupport(targetPath, {
|
|
1553
1780
|
includeUserLocal: true,
|
|
1554
1781
|
integrationRootPath: options.integrationRootPath,
|
|
1782
|
+
pinnedVersion: options.pinnedVersion,
|
|
1555
1783
|
});
|
|
1556
1784
|
const actions = [];
|
|
1557
1785
|
const effectiveDevRepoPath = options.devRepoPath ?? resolveCurrentGdhInstall(import.meta.url).defaultDevRepoPath;
|
|
@@ -1567,15 +1795,15 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
1567
1795
|
continue;
|
|
1568
1796
|
}
|
|
1569
1797
|
if (adapter.agent === "codex") {
|
|
1570
|
-
actions.push(...planCodexRepoInstallActions(targetPath, adapter));
|
|
1798
|
+
actions.push(...planCodexRepoInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1571
1799
|
continue;
|
|
1572
1800
|
}
|
|
1573
1801
|
if (adapter.agent === "claude") {
|
|
1574
|
-
actions.push(...planClaudeInstallActions(targetPath, adapter));
|
|
1802
|
+
actions.push(...planClaudeInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1575
1803
|
continue;
|
|
1576
1804
|
}
|
|
1577
1805
|
if (adapter.agent === "cursor") {
|
|
1578
|
-
actions.push(...planCursorInstallActions(targetPath, adapter));
|
|
1806
|
+
actions.push(...planCursorInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1579
1807
|
}
|
|
1580
1808
|
}
|
|
1581
1809
|
return dedupeInstallActions(actions);
|
|
@@ -1616,7 +1844,7 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1616
1844
|
content: renderManagedMcpConfig(path.join(integrationRootPath, PROJECT_MCP_RELATIVE_PATH), buildManagedMcpServerEntry({
|
|
1617
1845
|
targetPath,
|
|
1618
1846
|
integrationRootPath,
|
|
1619
|
-
launcherPathForConfig:
|
|
1847
|
+
launcherPathForConfig: path.resolve(integrationRootPath, MCP_LAUNCHER_RELATIVE_PATH),
|
|
1620
1848
|
})),
|
|
1621
1849
|
}));
|
|
1622
1850
|
}
|
|
@@ -1635,7 +1863,7 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1635
1863
|
content: renderManagedMcpConfig(path.join(integrationRootPath, CURSOR_MCP_RELATIVE_PATH), buildManagedMcpServerEntry({
|
|
1636
1864
|
targetPath,
|
|
1637
1865
|
integrationRootPath,
|
|
1638
|
-
launcherPathForConfig:
|
|
1866
|
+
launcherPathForConfig: path.resolve(integrationRootPath, MCP_LAUNCHER_RELATIVE_PATH),
|
|
1639
1867
|
})),
|
|
1640
1868
|
}));
|
|
1641
1869
|
}
|
|
@@ -1667,7 +1895,7 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1667
1895
|
}
|
|
1668
1896
|
return actions;
|
|
1669
1897
|
}
|
|
1670
|
-
function planSkillInstallAction(agent, targetPath, adapter, relativePath, renderFn, skillName) {
|
|
1898
|
+
function planSkillInstallAction(agent, targetPath, adapter, relativePath, renderFn, skillName, pinnedVersion) {
|
|
1671
1899
|
const surface = adapter.surfaces.find((s) => s.relativePath === relativePath);
|
|
1672
1900
|
if (!surface || surface.state === "ready") {
|
|
1673
1901
|
return createInstallAction({
|
|
@@ -1679,7 +1907,7 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
1679
1907
|
state: "unchanged",
|
|
1680
1908
|
mode: "unchanged",
|
|
1681
1909
|
summary: `The managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} already matches the expected GDH content.`,
|
|
1682
|
-
content: renderFn(),
|
|
1910
|
+
content: renderFn(pinnedVersion),
|
|
1683
1911
|
});
|
|
1684
1912
|
}
|
|
1685
1913
|
return createInstallAction({
|
|
@@ -1693,7 +1921,7 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
1693
1921
|
summary: surface.present
|
|
1694
1922
|
? `Replace the existing ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} with the managed GDH ${agent === "claude" ? "command" : "skill"}.`
|
|
1695
1923
|
: `Create the managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"}.`,
|
|
1696
|
-
content: renderFn(),
|
|
1924
|
+
content: renderFn(pinnedVersion),
|
|
1697
1925
|
});
|
|
1698
1926
|
}
|
|
1699
1927
|
function agentLabel(agent) {
|
|
@@ -1706,14 +1934,15 @@ function agentLabel(agent) {
|
|
|
1706
1934
|
return "Cursor";
|
|
1707
1935
|
}
|
|
1708
1936
|
}
|
|
1709
|
-
function planCodexRepoInstallActions(targetPath, adapter) {
|
|
1937
|
+
function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1710
1938
|
return [
|
|
1711
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_ONBOARD_SKILL_RELATIVE_PATH, renderCodexOnboardSkill, "gdh-onboard"),
|
|
1712
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_STATUS_SKILL_RELATIVE_PATH, renderCodexStatusSkill, "gdh-status"),
|
|
1713
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_MIGRATE_SKILL_RELATIVE_PATH, renderCodexMigrateSkill, "gdh-migrate"),
|
|
1714
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_CHECK_SKILL_RELATIVE_PATH, renderCodexCheckSkill, "gdh-check"),
|
|
1715
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_PREPARE_SKILL_RELATIVE_PATH, renderCodexPrepareSkill, "gdh-prepare"),
|
|
1716
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_VERIFY_SKILL_RELATIVE_PATH, renderCodexVerifySkill, "gdh-verify"),
|
|
1939
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_ONBOARD_SKILL_RELATIVE_PATH, renderCodexOnboardSkill, "gdh-onboard", pinnedVersion),
|
|
1940
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_STATUS_SKILL_RELATIVE_PATH, renderCodexStatusSkill, "gdh-status", pinnedVersion),
|
|
1941
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_MIGRATE_SKILL_RELATIVE_PATH, renderCodexMigrateSkill, "gdh-migrate", pinnedVersion),
|
|
1942
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_CHECK_SKILL_RELATIVE_PATH, renderCodexCheckSkill, "gdh-check", pinnedVersion),
|
|
1943
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_PREPARE_SKILL_RELATIVE_PATH, renderCodexPrepareSkill, "gdh-prepare", pinnedVersion),
|
|
1944
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_VERIFY_SKILL_RELATIVE_PATH, renderCodexVerifySkill, "gdh-verify", pinnedVersion),
|
|
1945
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_SCAN_SKILL_RELATIVE_PATH, renderCodexScanSkill, "gdh-scan", pinnedVersion),
|
|
1717
1946
|
];
|
|
1718
1947
|
}
|
|
1719
1948
|
function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath) {
|
|
@@ -1764,7 +1993,7 @@ function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath
|
|
|
1764
1993
|
}));
|
|
1765
1994
|
return actions;
|
|
1766
1995
|
}
|
|
1767
|
-
function planClaudeInstallActions(targetPath, adapter) {
|
|
1996
|
+
function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1768
1997
|
const actions = [];
|
|
1769
1998
|
const claudeSurface = adapter.surfaces.find((surface) => surface.relativePath === CLAUDE_SHIM_RELATIVE_PATH);
|
|
1770
1999
|
if (!claudeSurface || claudeSurface.state === "ready") {
|
|
@@ -1795,10 +2024,10 @@ function planClaudeInstallActions(targetPath, adapter) {
|
|
|
1795
2024
|
expectedTarget: "AGENTS.md",
|
|
1796
2025
|
}));
|
|
1797
2026
|
}
|
|
1798
|
-
actions.push(planSkillInstallAction("claude", targetPath, adapter, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, renderClaudeOnboardCommand, "gdh-onboard"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, renderClaudeStatusCommand, "gdh-status"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, renderClaudeMigrateCommand, "gdh-migrate"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, renderClaudeCheckCommand, "gdh-check"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, renderClaudePrepareCommand, "gdh-prepare"), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, renderClaudeVerifyCommand, "gdh-verify"));
|
|
2027
|
+
actions.push(planSkillInstallAction("claude", targetPath, adapter, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, renderClaudeOnboardCommand, "gdh-onboard", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, renderClaudeStatusCommand, "gdh-status", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, renderClaudeMigrateCommand, "gdh-migrate", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, renderClaudeCheckCommand, "gdh-check", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, renderClaudePrepareCommand, "gdh-prepare", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, renderClaudeVerifyCommand, "gdh-verify", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_SCAN_COMMAND_RELATIVE_PATH, renderClaudeScanCommand, "gdh-scan", pinnedVersion));
|
|
1799
2028
|
return actions;
|
|
1800
2029
|
}
|
|
1801
|
-
function planCursorInstallActions(targetPath, adapter) {
|
|
2030
|
+
function planCursorInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1802
2031
|
const actions = [];
|
|
1803
2032
|
const cursorRuleSurface = adapter.surfaces.find((surface) => surface.relativePath === CURSOR_RULE_RELATIVE_PATH);
|
|
1804
2033
|
if (!cursorRuleSurface || cursorRuleSurface.state === "ready") {
|
|
@@ -1831,7 +2060,7 @@ function planCursorInstallActions(targetPath, adapter) {
|
|
|
1831
2060
|
content: renderCursorRule(),
|
|
1832
2061
|
}));
|
|
1833
2062
|
}
|
|
1834
|
-
actions.push(planSkillInstallAction("cursor", targetPath, adapter, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, renderCursorOnboardSkill, "gdh-onboard"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_STATUS_SKILL_RELATIVE_PATH, renderCursorStatusSkill, "gdh-status"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, renderCursorMigrateSkill, "gdh-migrate"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_CHECK_SKILL_RELATIVE_PATH, renderCursorCheckSkill, "gdh-check"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_PREPARE_SKILL_RELATIVE_PATH, renderCursorPrepareSkill, "gdh-prepare"), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_VERIFY_SKILL_RELATIVE_PATH, renderCursorVerifySkill, "gdh-verify"));
|
|
2063
|
+
actions.push(planSkillInstallAction("cursor", targetPath, adapter, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, renderCursorOnboardSkill, "gdh-onboard", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_STATUS_SKILL_RELATIVE_PATH, renderCursorStatusSkill, "gdh-status", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, renderCursorMigrateSkill, "gdh-migrate", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_CHECK_SKILL_RELATIVE_PATH, renderCursorCheckSkill, "gdh-check", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_PREPARE_SKILL_RELATIVE_PATH, renderCursorPrepareSkill, "gdh-prepare", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_VERIFY_SKILL_RELATIVE_PATH, renderCursorVerifySkill, "gdh-verify", pinnedVersion), planSkillInstallAction("cursor", targetPath, adapter, CURSOR_SCAN_SKILL_RELATIVE_PATH, renderCursorScanSkill, "gdh-scan", pinnedVersion));
|
|
1835
2064
|
return actions;
|
|
1836
2065
|
}
|
|
1837
2066
|
function dedupeInstallActions(actions) {
|
|
@@ -1929,7 +2158,7 @@ function resolveProjectMcpEnabled(projectConfig) {
|
|
|
1929
2158
|
function createCodexServerName(projectKeySeed) {
|
|
1930
2159
|
return `gdh-${projectKeySeed}`;
|
|
1931
2160
|
}
|
|
1932
|
-
function renderManagedMcpLauncher() {
|
|
2161
|
+
export function renderManagedMcpLauncher(pinnedVersion) {
|
|
1933
2162
|
return [
|
|
1934
2163
|
"#!/usr/bin/env node",
|
|
1935
2164
|
`// GDH MCP launcher v${GDH_MCP_LAUNCHER_VERSION}`,
|
|
@@ -1968,9 +2197,9 @@ function renderManagedMcpLauncher() {
|
|
|
1968
2197
|
" }",
|
|
1969
2198
|
"}",
|
|
1970
2199
|
"",
|
|
1971
|
-
|
|
2200
|
+
`const result = spawnSync("npx", ["-y", "@skillcap/gdh@${pinnedVersion}", "mcp", "serve", "--target", targetPath], { stdio: "inherit", cwd: targetPath });`,
|
|
1972
2201
|
'if (result.error && result.error.code === "ENOENT") {',
|
|
1973
|
-
|
|
2202
|
+
` console.error("GDH MCP launcher could not launch npx for @skillcap/gdh@${pinnedVersion}. Ensure Node.js 20+ is installed (npx ships with Node), or configure the contributor dev escape hatch via the GDH_DEV_REPO env var or .gdh-state/local-paths.json gdhDevRepoPath.");`,
|
|
1974
2203
|
" process.exit(1);",
|
|
1975
2204
|
"}",
|
|
1976
2205
|
"process.exit(result.status ?? 1);",
|
|
@@ -1985,7 +2214,7 @@ function buildManagedMcpServerEntry(input) {
|
|
|
1985
2214
|
targetPath: input.targetPath,
|
|
1986
2215
|
integrationRootPath: input.integrationRootPath,
|
|
1987
2216
|
launcherPath: input.launcherPathForConfig,
|
|
1988
|
-
useAbsoluteTargetPath:
|
|
2217
|
+
useAbsoluteTargetPath: true,
|
|
1989
2218
|
}),
|
|
1990
2219
|
};
|
|
1991
2220
|
}
|