@skillcap/gdh 0.4.1 → 0.6.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 +54 -92
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts +74 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +158 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts +51 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.js +80 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts +35 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js +76 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts +28 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js +99 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/index.d.ts +34 -18
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +596 -145
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts +51 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js +155 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js.map +1 -0
- package/node_modules/@gdh/adapters/package.json +8 -8
- package/node_modules/@gdh/authoring/dist/index.d.ts +2 -1
- package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/index.js +2 -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/dist/writePinnedVersion.d.ts +17 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.d.ts.map +1 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.js +50 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.js.map +1 -0
- package/node_modules/@gdh/authoring/package.json +5 -2
- package/node_modules/@gdh/cli/dist/index.d.ts +15 -0
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +292 -40
- 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/self-update.d.ts +3 -0
- package/node_modules/@gdh/cli/dist/self-update.d.ts.map +1 -0
- package/node_modules/@gdh/cli/dist/self-update.js +235 -0
- package/node_modules/@gdh/cli/dist/self-update.js.map +1 -0
- 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/dist/update-banner.d.ts +42 -0
- package/node_modules/@gdh/cli/dist/update-banner.d.ts.map +1 -0
- package/node_modules/@gdh/cli/dist/update-banner.js +49 -0
- package/node_modules/@gdh/cli/dist/update-banner.js.map +1 -0
- package/node_modules/@gdh/cli/package.json +10 -10
- package/node_modules/@gdh/core/dist/dev-mode.d.ts +13 -0
- package/node_modules/@gdh/core/dist/dev-mode.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/dev-mode.js +21 -0
- package/node_modules/@gdh/core/dist/dev-mode.js.map +1 -0
- package/node_modules/@gdh/core/dist/index.d.ts +12 -5
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +10 -2
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/dist/update-cache.d.ts +46 -0
- package/node_modules/@gdh/core/dist/update-cache.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/update-cache.js +90 -0
- package/node_modules/@gdh/core/dist/update-cache.js.map +1 -0
- package/node_modules/@gdh/core/dist/update-probe.d.ts +102 -0
- package/node_modules/@gdh/core/dist/update-probe.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/update-probe.js +195 -0
- package/node_modules/@gdh/core/dist/update-probe.js.map +1 -0
- 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.d.ts +20 -0
- package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/mcp/dist/index.js +45 -4
- 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 +3 -1
- 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,11 @@ 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
|
+
import { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateHook, } from "./claude-update-hook-render.js";
|
|
9
|
+
import { renderClaudeCheckUpdateWorker } from "./claude-update-worker-render.js";
|
|
10
|
+
import { CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, } from "./claude-statusline-render.js";
|
|
11
|
+
import { CLAUDE_SETTINGS_RELATIVE_PATH, patchClaudeSettingsForGdhSessionStart, patchClaudeSettingsForGdhStatusline, } from "./claude-settings-patch.js";
|
|
8
12
|
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
13
|
import { createDefaultGuidanceUnits, getGuidanceStatus, resolveGuidanceQuery, } from "@gdh/docs";
|
|
10
14
|
import { inspectGuidanceAudit } from "@gdh/observability";
|
|
@@ -48,6 +52,18 @@ export const CURSOR_MIGRATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-migrate/SK
|
|
|
48
52
|
export const CURSOR_CHECK_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-check/SKILL.md";
|
|
49
53
|
export const CURSOR_PREPARE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-prepare/SKILL.md";
|
|
50
54
|
export const CURSOR_VERIFY_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-verify/SKILL.md";
|
|
55
|
+
// Phase 13 SELF-01: /gdh-update skill surface path constants. The rendered
|
|
56
|
+
// bodies shell out to `npx -y @skillcap/gdh@latest self-update` (LITERAL
|
|
57
|
+
// @latest, not the pinned version — D-10) so the NEW CLI performs the update,
|
|
58
|
+
// not the (potentially pre-Phase-12) OLD pinned one. These constants are
|
|
59
|
+
// INTENTIONALLY excluded from VERIFY_DRIFT_SCANNED_FILES (D-13) because the
|
|
60
|
+
// rendered bodies are version-agnostic by design.
|
|
61
|
+
export const CLAUDE_UPDATE_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/update.md";
|
|
62
|
+
export const CODEX_UPDATE_SKILL_RELATIVE_PATH = ".codex/skills/gdh-update/SKILL.md";
|
|
63
|
+
export const CURSOR_UPDATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-update/SKILL.md";
|
|
64
|
+
export const CLAUDE_SCAN_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/scan.md";
|
|
65
|
+
export const CODEX_SCAN_SKILL_RELATIVE_PATH = ".codex/skills/gdh-scan/SKILL.md";
|
|
66
|
+
export const CURSOR_SCAN_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-scan/SKILL.md";
|
|
51
67
|
export const LOCAL_PATH_HINTS_RELATIVE_PATH = ".gdh-state/local-paths.json";
|
|
52
68
|
export const MCP_LAUNCHER_RELATIVE_PATH = ".gdh/bin/gdh-mcp.mjs";
|
|
53
69
|
export const GDH_MCP_SERVER_NAME = "gdh";
|
|
@@ -56,16 +72,18 @@ export async function getSupportedAgentAdaptersStatus(targetPath, options = {})
|
|
|
56
72
|
const includeUserLocal = options.includeUserLocal ?? true;
|
|
57
73
|
const integrationRootPath = resolveIntegrationRootPath(targetPath, options.integrationRootPath);
|
|
58
74
|
const guidance = await getGuidanceStatus(targetPath);
|
|
75
|
+
const pinnedVersion = await resolvePinnedVersionOrNull(targetPath);
|
|
59
76
|
const projectMcp = await inspectProjectMcpSupport(targetPath, {
|
|
60
77
|
includeUserLocal,
|
|
61
78
|
integrationRootPath,
|
|
79
|
+
pinnedVersion,
|
|
62
80
|
});
|
|
63
81
|
const [codex, claude, cursor] = await Promise.all([
|
|
64
|
-
inspectCodexAdapter(targetPath, guidance, projectMcp, {
|
|
82
|
+
inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, {
|
|
65
83
|
includeUserLocal,
|
|
66
84
|
}),
|
|
67
|
-
inspectClaudeAdapter(targetPath, guidance, projectMcp),
|
|
68
|
-
inspectCursorAdapter(targetPath, guidance, projectMcp),
|
|
85
|
+
inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVersion),
|
|
86
|
+
inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVersion),
|
|
69
87
|
]);
|
|
70
88
|
return {
|
|
71
89
|
targetPath,
|
|
@@ -80,6 +98,7 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
80
98
|
const status = await getSupportedAgentAdaptersStatus(targetPath, {
|
|
81
99
|
integrationRootPath,
|
|
82
100
|
});
|
|
101
|
+
const pinnedVersion = await resolvePinnedVersion(targetPath);
|
|
83
102
|
if (!hasReadyVisibilityChain(status.guidance) && options.allowBootstrap !== true) {
|
|
84
103
|
return {
|
|
85
104
|
targetPath,
|
|
@@ -96,26 +115,41 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
96
115
|
user: options.user ?? false,
|
|
97
116
|
devRepoPath: options.devRepoPath ?? null,
|
|
98
117
|
integrationRootPath,
|
|
118
|
+
pinnedVersion,
|
|
99
119
|
});
|
|
120
|
+
let appliedActions = actions;
|
|
100
121
|
if (!dryRun) {
|
|
122
|
+
const newActions = [];
|
|
101
123
|
for (const action of actions) {
|
|
102
124
|
if (action.state === "unchanged") {
|
|
125
|
+
newActions.push(action);
|
|
103
126
|
continue;
|
|
104
127
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
128
|
+
try {
|
|
129
|
+
if (action.kind === "ensure_symlink") {
|
|
130
|
+
await applySymlinkAction(action);
|
|
131
|
+
}
|
|
132
|
+
else if (action.kind === "run_command") {
|
|
133
|
+
await applyRunCommandAction(action);
|
|
134
|
+
}
|
|
135
|
+
else if (action.command?.[0] === "write_local_hints") {
|
|
136
|
+
await applyLocalHintsAction(action);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
await applyWriteFileAction(action);
|
|
140
|
+
}
|
|
141
|
+
newActions.push({ ...action, state: "applied" });
|
|
112
142
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
143
|
+
catch (error) {
|
|
144
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
145
|
+
newActions.push({
|
|
146
|
+
...action,
|
|
147
|
+
state: "blocked",
|
|
148
|
+
summary: `${action.summary} (failed: ${errorMessage})`,
|
|
149
|
+
});
|
|
116
150
|
}
|
|
117
|
-
await applyWriteFileAction(action);
|
|
118
151
|
}
|
|
152
|
+
appliedActions = newActions;
|
|
119
153
|
}
|
|
120
154
|
return {
|
|
121
155
|
targetPath,
|
|
@@ -129,7 +163,7 @@ export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
|
129
163
|
requestedAgents,
|
|
130
164
|
guidance: status.guidance,
|
|
131
165
|
adapters: status.adapters,
|
|
132
|
-
actions,
|
|
166
|
+
actions: appliedActions,
|
|
133
167
|
};
|
|
134
168
|
}
|
|
135
169
|
export async function inspectProjectLifecycleCompatibility(targetPath) {
|
|
@@ -285,7 +319,7 @@ export function renderCursorRule() {
|
|
|
285
319
|
"",
|
|
286
320
|
].join("\n");
|
|
287
321
|
}
|
|
288
|
-
export function renderClaudeOnboardCommand() {
|
|
322
|
+
export function renderClaudeOnboardCommand(pinnedVersion) {
|
|
289
323
|
return [
|
|
290
324
|
"---",
|
|
291
325
|
"name: gdh:onboard",
|
|
@@ -298,17 +332,17 @@ export function renderClaudeOnboardCommand() {
|
|
|
298
332
|
" - AskUserQuestion",
|
|
299
333
|
"---",
|
|
300
334
|
"<objective>",
|
|
301
|
-
|
|
335
|
+
`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
336
|
"</objective>",
|
|
303
337
|
"",
|
|
304
338
|
"<process>",
|
|
305
339
|
"Follow this order:",
|
|
306
340
|
"",
|
|
307
|
-
|
|
341
|
+
`1. Confirm the selected target and current GDH state with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
308
342
|
"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
|
-
|
|
343
|
+
`3. Check immediate readiness with \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\` and \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\`.`,
|
|
344
|
+
`4. If authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`; if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\`.`,
|
|
345
|
+
`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
346
|
"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
347
|
"7. Ask the human only for narrow unresolved environment or target facts.",
|
|
314
348
|
"8. End with a concise readiness summary and the exact next development step.",
|
|
@@ -318,11 +352,12 @@ export function renderClaudeOnboardCommand() {
|
|
|
318
352
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
319
353
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
320
354
|
"- Keep the output short, operational, and specific.",
|
|
355
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
321
356
|
"</rules>",
|
|
322
357
|
"",
|
|
323
358
|
].join("\n");
|
|
324
359
|
}
|
|
325
|
-
export function renderCodexOnboardSkill() {
|
|
360
|
+
export function renderCodexOnboardSkill(pinnedVersion) {
|
|
326
361
|
return [
|
|
327
362
|
"---",
|
|
328
363
|
'name: "gdh-onboard"',
|
|
@@ -342,20 +377,20 @@ export function renderCodexOnboardSkill() {
|
|
|
342
377
|
"</codex_skill_adapter>",
|
|
343
378
|
"",
|
|
344
379
|
"<objective>",
|
|
345
|
-
|
|
380
|
+
`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
381
|
"</objective>",
|
|
347
382
|
"",
|
|
348
383
|
"<process>",
|
|
349
384
|
"Follow this order:",
|
|
350
385
|
"",
|
|
351
|
-
|
|
386
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
352
387
|
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
388
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
389
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
390
|
+
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
391
|
+
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
392
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
393
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
359
394
|
"- 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
395
|
"- ask only for narrow unresolved environment or target facts",
|
|
361
396
|
"- finish with a concise readiness summary and the exact next development step",
|
|
@@ -365,11 +400,12 @@ export function renderCodexOnboardSkill() {
|
|
|
365
400
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
366
401
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
367
402
|
"- Keep output short, operational, and specific.",
|
|
403
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
368
404
|
"</rules>",
|
|
369
405
|
"",
|
|
370
406
|
].join("\n");
|
|
371
407
|
}
|
|
372
|
-
export function renderCursorOnboardSkill() {
|
|
408
|
+
export function renderCursorOnboardSkill(pinnedVersion) {
|
|
373
409
|
return [
|
|
374
410
|
"---",
|
|
375
411
|
"name: gdh-onboard",
|
|
@@ -387,20 +423,20 @@ export function renderCursorOnboardSkill() {
|
|
|
387
423
|
"</cursor_skill_adapter>",
|
|
388
424
|
"",
|
|
389
425
|
"<objective>",
|
|
390
|
-
|
|
426
|
+
`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
427
|
"</objective>",
|
|
392
428
|
"",
|
|
393
429
|
"<process>",
|
|
394
430
|
"Follow this order:",
|
|
395
431
|
"",
|
|
396
|
-
|
|
432
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
397
433
|
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
434
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
435
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
436
|
+
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
437
|
+
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
438
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
439
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
404
440
|
"- 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
441
|
"- ask only for narrow unresolved environment or target facts",
|
|
406
442
|
"- finish with a concise readiness summary and the exact next development step",
|
|
@@ -410,12 +446,13 @@ export function renderCursorOnboardSkill() {
|
|
|
410
446
|
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
411
447
|
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
412
448
|
"- Keep output short, operational, and specific.",
|
|
449
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
413
450
|
"</rules>",
|
|
414
451
|
"",
|
|
415
452
|
].join("\n");
|
|
416
453
|
}
|
|
417
454
|
// --- gdh-status skill renders ---
|
|
418
|
-
export function renderClaudeStatusCommand() {
|
|
455
|
+
export function renderClaudeStatusCommand(pinnedVersion) {
|
|
419
456
|
return [
|
|
420
457
|
"---",
|
|
421
458
|
"name: gdh:status",
|
|
@@ -433,8 +470,8 @@ export function renderClaudeStatusCommand() {
|
|
|
433
470
|
"<process>",
|
|
434
471
|
"Follow this order:",
|
|
435
472
|
"",
|
|
436
|
-
|
|
437
|
-
|
|
473
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field.`,
|
|
474
|
+
`2. Check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\`.`,
|
|
438
475
|
"3. Surface any degraded or unavailable capabilities.",
|
|
439
476
|
"4. Suggest the most productive next step based on current state.",
|
|
440
477
|
"</process>",
|
|
@@ -443,11 +480,12 @@ export function renderClaudeStatusCommand() {
|
|
|
443
480
|
"- Do not start editing code.",
|
|
444
481
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
445
482
|
"- Keep output short and operational.",
|
|
483
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
446
484
|
"</rules>",
|
|
447
485
|
"",
|
|
448
486
|
].join("\n");
|
|
449
487
|
}
|
|
450
|
-
export function renderCodexStatusSkill() {
|
|
488
|
+
export function renderCodexStatusSkill(pinnedVersion) {
|
|
451
489
|
return [
|
|
452
490
|
"---",
|
|
453
491
|
'name: "gdh-status"',
|
|
@@ -473,8 +511,8 @@ export function renderCodexStatusSkill() {
|
|
|
473
511
|
"<process>",
|
|
474
512
|
"Follow this order:",
|
|
475
513
|
"",
|
|
476
|
-
|
|
477
|
-
|
|
514
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
515
|
+
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
478
516
|
"- surface any degraded or unavailable capabilities",
|
|
479
517
|
"- suggest the most productive next step based on current state",
|
|
480
518
|
"</process>",
|
|
@@ -483,11 +521,12 @@ export function renderCodexStatusSkill() {
|
|
|
483
521
|
"- Do not start editing code.",
|
|
484
522
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
485
523
|
"- Keep output short and operational.",
|
|
524
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
486
525
|
"</rules>",
|
|
487
526
|
"",
|
|
488
527
|
].join("\n");
|
|
489
528
|
}
|
|
490
|
-
export function renderCursorStatusSkill() {
|
|
529
|
+
export function renderCursorStatusSkill(pinnedVersion) {
|
|
491
530
|
return [
|
|
492
531
|
"---",
|
|
493
532
|
"name: gdh-status",
|
|
@@ -511,8 +550,8 @@ export function renderCursorStatusSkill() {
|
|
|
511
550
|
"<process>",
|
|
512
551
|
"Follow this order:",
|
|
513
552
|
"",
|
|
514
|
-
|
|
515
|
-
|
|
553
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
554
|
+
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
516
555
|
"- surface any degraded or unavailable capabilities",
|
|
517
556
|
"- suggest the most productive next step based on current state",
|
|
518
557
|
"</process>",
|
|
@@ -521,12 +560,123 @@ export function renderCursorStatusSkill() {
|
|
|
521
560
|
"- Do not start editing code.",
|
|
522
561
|
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
523
562
|
"- Keep output short and operational.",
|
|
563
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
564
|
+
"</rules>",
|
|
565
|
+
"",
|
|
566
|
+
].join("\n");
|
|
567
|
+
}
|
|
568
|
+
// --- gdh-scan skill renders ---
|
|
569
|
+
export function renderClaudeScanCommand(pinnedVersion) {
|
|
570
|
+
return [
|
|
571
|
+
"---",
|
|
572
|
+
"name: gdh:scan",
|
|
573
|
+
"description: Refresh inventory cache and explain persistence effect",
|
|
574
|
+
"allowed-tools:",
|
|
575
|
+
" - Read",
|
|
576
|
+
" - Grep",
|
|
577
|
+
" - Glob",
|
|
578
|
+
" - Bash",
|
|
579
|
+
"---",
|
|
580
|
+
"<objective>",
|
|
581
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
582
|
+
"</objective>",
|
|
583
|
+
"",
|
|
584
|
+
"<process>",
|
|
585
|
+
"Follow this order:",
|
|
586
|
+
"",
|
|
587
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} scan\` and parse the \`persisted\` field from the envelope.`,
|
|
588
|
+
"2. Check the `mode` field: `create`, `unchanged`, `overwrite`, or `null`.",
|
|
589
|
+
"3. Explain the persistence effect; if `null`, the target is not onboarded and no disk write occurred.",
|
|
590
|
+
"</process>",
|
|
591
|
+
"",
|
|
592
|
+
"<rules>",
|
|
593
|
+
"- Do not edit the persisted inventory directly.",
|
|
594
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
595
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
596
|
+
"</rules>",
|
|
597
|
+
"",
|
|
598
|
+
].join("\n");
|
|
599
|
+
}
|
|
600
|
+
export function renderCodexScanSkill(pinnedVersion) {
|
|
601
|
+
return [
|
|
602
|
+
"---",
|
|
603
|
+
'name: "gdh-scan"',
|
|
604
|
+
'description: "Refresh inventory cache and explain persistence effect"',
|
|
605
|
+
"metadata:",
|
|
606
|
+
' short-description: "Refresh inventory cache and explain persistence effect"',
|
|
607
|
+
"---",
|
|
608
|
+
"",
|
|
609
|
+
"<codex_skill_adapter>",
|
|
610
|
+
"## Invocation",
|
|
611
|
+
"- This skill is invoked when the user says `/gdh-scan` or mentions `$gdh-scan`.",
|
|
612
|
+
"- Treat any extra user text as additional scan context.",
|
|
613
|
+
"",
|
|
614
|
+
"## User questions",
|
|
615
|
+
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
616
|
+
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
617
|
+
"</codex_skill_adapter>",
|
|
618
|
+
"",
|
|
619
|
+
"<objective>",
|
|
620
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
621
|
+
"</objective>",
|
|
622
|
+
"",
|
|
623
|
+
"<process>",
|
|
624
|
+
"Follow this order:",
|
|
625
|
+
"",
|
|
626
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
627
|
+
"- parse the `persisted` field from the envelope",
|
|
628
|
+
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
629
|
+
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
630
|
+
"</process>",
|
|
631
|
+
"",
|
|
632
|
+
"<rules>",
|
|
633
|
+
"- Do not edit the persisted inventory directly.",
|
|
634
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
635
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
636
|
+
"</rules>",
|
|
637
|
+
"",
|
|
638
|
+
].join("\n");
|
|
639
|
+
}
|
|
640
|
+
export function renderCursorScanSkill(pinnedVersion) {
|
|
641
|
+
return [
|
|
642
|
+
"---",
|
|
643
|
+
"name: gdh-scan",
|
|
644
|
+
'description: "Refresh inventory cache and explain persistence effect"',
|
|
645
|
+
"---",
|
|
646
|
+
"",
|
|
647
|
+
"<cursor_skill_adapter>",
|
|
648
|
+
"## Invocation",
|
|
649
|
+
"- This skill is invoked when the user says `/gdh-scan` or mentions `gdh-scan`.",
|
|
650
|
+
"- Treat any extra user text as additional scan context.",
|
|
651
|
+
"",
|
|
652
|
+
"## User questions",
|
|
653
|
+
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
654
|
+
"- Keep questions conversational and concise.",
|
|
655
|
+
"</cursor_skill_adapter>",
|
|
656
|
+
"",
|
|
657
|
+
"<objective>",
|
|
658
|
+
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
659
|
+
"</objective>",
|
|
660
|
+
"",
|
|
661
|
+
"<process>",
|
|
662
|
+
"Follow this order:",
|
|
663
|
+
"",
|
|
664
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
665
|
+
"- parse the `persisted` field from the envelope",
|
|
666
|
+
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
667
|
+
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
668
|
+
"</process>",
|
|
669
|
+
"",
|
|
670
|
+
"<rules>",
|
|
671
|
+
"- Do not edit the persisted inventory directly.",
|
|
672
|
+
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
673
|
+
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
524
674
|
"</rules>",
|
|
525
675
|
"",
|
|
526
676
|
].join("\n");
|
|
527
677
|
}
|
|
528
678
|
// --- gdh-migrate skill renders ---
|
|
529
|
-
export function renderClaudeMigrateCommand() {
|
|
679
|
+
export function renderClaudeMigrateCommand(pinnedVersion) {
|
|
530
680
|
return [
|
|
531
681
|
"---",
|
|
532
682
|
"name: gdh:migrate",
|
|
@@ -545,10 +695,10 @@ export function renderClaudeMigrateCommand() {
|
|
|
545
695
|
"<process>",
|
|
546
696
|
"Follow this order:",
|
|
547
697
|
"",
|
|
548
|
-
|
|
698
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations.`,
|
|
549
699
|
"2. Explain what each migration step will change and why.",
|
|
550
|
-
|
|
551
|
-
|
|
700
|
+
`3. Offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves.`,
|
|
701
|
+
`4. After apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded.`,
|
|
552
702
|
"</process>",
|
|
553
703
|
"",
|
|
554
704
|
"<rules>",
|
|
@@ -559,7 +709,7 @@ export function renderClaudeMigrateCommand() {
|
|
|
559
709
|
"",
|
|
560
710
|
].join("\n");
|
|
561
711
|
}
|
|
562
|
-
export function renderCodexMigrateSkill() {
|
|
712
|
+
export function renderCodexMigrateSkill(pinnedVersion) {
|
|
563
713
|
return [
|
|
564
714
|
"---",
|
|
565
715
|
'name: "gdh-migrate"',
|
|
@@ -585,10 +735,10 @@ export function renderCodexMigrateSkill() {
|
|
|
585
735
|
"<process>",
|
|
586
736
|
"Follow this order:",
|
|
587
737
|
"",
|
|
588
|
-
|
|
738
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations`,
|
|
589
739
|
"- explain what each migration step will change and why",
|
|
590
|
-
|
|
591
|
-
|
|
740
|
+
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves`,
|
|
741
|
+
`- after apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded`,
|
|
592
742
|
"</process>",
|
|
593
743
|
"",
|
|
594
744
|
"<rules>",
|
|
@@ -599,7 +749,7 @@ export function renderCodexMigrateSkill() {
|
|
|
599
749
|
"",
|
|
600
750
|
].join("\n");
|
|
601
751
|
}
|
|
602
|
-
export function renderCursorMigrateSkill() {
|
|
752
|
+
export function renderCursorMigrateSkill(pinnedVersion) {
|
|
603
753
|
return [
|
|
604
754
|
"---",
|
|
605
755
|
"name: gdh-migrate",
|
|
@@ -623,10 +773,10 @@ export function renderCursorMigrateSkill() {
|
|
|
623
773
|
"<process>",
|
|
624
774
|
"Follow this order:",
|
|
625
775
|
"",
|
|
626
|
-
|
|
776
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations`,
|
|
627
777
|
"- explain what each migration step will change and why",
|
|
628
|
-
|
|
629
|
-
|
|
778
|
+
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves`,
|
|
779
|
+
`- after apply, run \`npx -y @skillcap/gdh@${pinnedVersion} status\` to verify the migration succeeded`,
|
|
630
780
|
"</process>",
|
|
631
781
|
"",
|
|
632
782
|
"<rules>",
|
|
@@ -637,8 +787,135 @@ export function renderCursorMigrateSkill() {
|
|
|
637
787
|
"",
|
|
638
788
|
].join("\n");
|
|
639
789
|
}
|
|
790
|
+
// --- gdh-update skill renders (Phase 13 SELF-01) ---
|
|
791
|
+
//
|
|
792
|
+
// D-10 invariant: every rendered body shells out to the LITERAL string
|
|
793
|
+
// `@skillcap/gdh@latest` in every npx line (dry-run, apply, verify drift).
|
|
794
|
+
// The `pinnedVersion` parameter is accepted for planSkillInstallAction
|
|
795
|
+
// signature symmetry with every other renderer, but MUST NOT be interpolated
|
|
796
|
+
// into the shellout — running the OLD pinned CLI (potentially pre-Phase-12
|
|
797
|
+
// and lacking bumpAndRebakePin entirely) to perform its own update is the
|
|
798
|
+
// failure mode Phase 13 exists to close. Check 44 in scripts/validate-docs.mjs
|
|
799
|
+
// enforces both the @latest presence AND the @${pinnedVersion} absence.
|
|
800
|
+
//
|
|
801
|
+
// D-11: preview-then-apply flow WITHOUT a confirmation gate — the human's
|
|
802
|
+
// original intent ("update GDH") IS the approval. No AskUserQuestion for
|
|
803
|
+
// Claude; no `## User questions` H2 for Codex/Cursor. Differs from /gdh-migrate
|
|
804
|
+
// which DOES gate on explicit approval.
|
|
805
|
+
//
|
|
806
|
+
// D-12: accept an optional positional version forwarded verbatim to the CLI.
|
|
807
|
+
// `/gdh-update` = latest; `/gdh-update 0.6.0` = pin that version.
|
|
808
|
+
//
|
|
809
|
+
// D-13: the three rendered skill files are EXCLUDED from VERIFY_DRIFT_SCANNED_FILES
|
|
810
|
+
// because @latest is not a semver literal — the baked-version scanner would
|
|
811
|
+
// permanently report no_baked_version. See rationale comments adjacent to the
|
|
812
|
+
// VERIFY_DRIFT_SCANNED_FILES declaration in packages/cli/src/index.ts.
|
|
813
|
+
export function renderClaudeUpdateCommand(_pinnedVersion) {
|
|
814
|
+
return [
|
|
815
|
+
"---",
|
|
816
|
+
"name: gdh:update",
|
|
817
|
+
"description: Update GDH to npm latest (bump pinned version + re-bake managed surfaces)",
|
|
818
|
+
"allowed-tools:",
|
|
819
|
+
" - Read",
|
|
820
|
+
" - Bash",
|
|
821
|
+
"---",
|
|
822
|
+
"<objective>",
|
|
823
|
+
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
824
|
+
"Treat any positional argument (e.g., `/gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
825
|
+
"</objective>",
|
|
826
|
+
"",
|
|
827
|
+
"<process>",
|
|
828
|
+
"Follow this order:",
|
|
829
|
+
"",
|
|
830
|
+
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
831
|
+
"2. Surface the planned version delta and re-bake action count to the human conversationally.",
|
|
832
|
+
"3. Apply: run `npx -y @skillcap/gdh@latest self-update [version]` (omit `[version]` to apply against npm latest; forward whatever positional the user passed to `/gdh-update`).",
|
|
833
|
+
"4. Verify: run `npx -y @skillcap/gdh@latest verify drift` to confirm every baked surface matches the new pin.",
|
|
834
|
+
"</process>",
|
|
835
|
+
"",
|
|
836
|
+
"<rules>",
|
|
837
|
+
"- Do NOT ask the user to confirm apply — their original intent (\"update GDH\") IS the approval.",
|
|
838
|
+
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
839
|
+
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
840
|
+
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
841
|
+
"</rules>",
|
|
842
|
+
"",
|
|
843
|
+
].join("\n");
|
|
844
|
+
}
|
|
845
|
+
export function renderCodexUpdateSkill(_pinnedVersion) {
|
|
846
|
+
return [
|
|
847
|
+
"---",
|
|
848
|
+
'name: "gdh-update"',
|
|
849
|
+
'description: "Update GDH to npm latest (bump pinned version + re-bake managed surfaces)"',
|
|
850
|
+
"metadata:",
|
|
851
|
+
' short-description: "Update GDH to npm latest"',
|
|
852
|
+
"---",
|
|
853
|
+
"",
|
|
854
|
+
"<codex_skill_adapter>",
|
|
855
|
+
"## Invocation",
|
|
856
|
+
"- This skill is invoked when the user says `/gdh-update` or mentions `$gdh-update`.",
|
|
857
|
+
"- Treat any positional argument (e.g., `/gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
858
|
+
"</codex_skill_adapter>",
|
|
859
|
+
"",
|
|
860
|
+
"<objective>",
|
|
861
|
+
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
862
|
+
"</objective>",
|
|
863
|
+
"",
|
|
864
|
+
"<process>",
|
|
865
|
+
"Follow this order:",
|
|
866
|
+
"",
|
|
867
|
+
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
868
|
+
"2. Surface the planned version delta and re-bake action count to the human conversationally.",
|
|
869
|
+
"3. Apply: run `npx -y @skillcap/gdh@latest self-update [version]` (omit `[version]` to apply against npm latest; forward whatever positional the user passed to `/gdh-update`).",
|
|
870
|
+
"4. Verify: run `npx -y @skillcap/gdh@latest verify drift` to confirm every baked surface matches the new pin.",
|
|
871
|
+
"</process>",
|
|
872
|
+
"",
|
|
873
|
+
"<rules>",
|
|
874
|
+
"- Do NOT ask the user to confirm apply — their original intent (\"update GDH\") IS the approval.",
|
|
875
|
+
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
876
|
+
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
877
|
+
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
878
|
+
"</rules>",
|
|
879
|
+
"",
|
|
880
|
+
].join("\n");
|
|
881
|
+
}
|
|
882
|
+
export function renderCursorUpdateSkill(_pinnedVersion) {
|
|
883
|
+
return [
|
|
884
|
+
"---",
|
|
885
|
+
"name: gdh-update",
|
|
886
|
+
'description: "Update GDH to npm latest (bump pinned version + re-bake managed surfaces)"',
|
|
887
|
+
"---",
|
|
888
|
+
"",
|
|
889
|
+
"<cursor_skill_adapter>",
|
|
890
|
+
"## Invocation",
|
|
891
|
+
"- This skill is invoked when the user says `/gdh-update` or mentions `gdh-update`.",
|
|
892
|
+
"- Treat any positional argument (e.g., `gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
893
|
+
"</cursor_skill_adapter>",
|
|
894
|
+
"",
|
|
895
|
+
"<objective>",
|
|
896
|
+
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
897
|
+
"</objective>",
|
|
898
|
+
"",
|
|
899
|
+
"<process>",
|
|
900
|
+
"Follow this order:",
|
|
901
|
+
"",
|
|
902
|
+
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
903
|
+
"2. Surface the planned version delta and re-bake action count to the human conversationally.",
|
|
904
|
+
"3. Apply: run `npx -y @skillcap/gdh@latest self-update [version]` (omit `[version]` to apply against npm latest; forward whatever positional the user passed to `/gdh-update`).",
|
|
905
|
+
"4. Verify: run `npx -y @skillcap/gdh@latest verify drift` to confirm every baked surface matches the new pin.",
|
|
906
|
+
"</process>",
|
|
907
|
+
"",
|
|
908
|
+
"<rules>",
|
|
909
|
+
"- Do NOT ask the user to confirm apply — their original intent (\"update GDH\") IS the approval.",
|
|
910
|
+
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
911
|
+
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
912
|
+
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
913
|
+
"</rules>",
|
|
914
|
+
"",
|
|
915
|
+
].join("\n");
|
|
916
|
+
}
|
|
640
917
|
// --- gdh-check skill renders ---
|
|
641
|
-
export function renderClaudeCheckCommand() {
|
|
918
|
+
export function renderClaudeCheckCommand(pinnedVersion) {
|
|
642
919
|
return [
|
|
643
920
|
"---",
|
|
644
921
|
"name: gdh:check",
|
|
@@ -656,7 +933,7 @@ export function renderClaudeCheckCommand() {
|
|
|
656
933
|
"<process>",
|
|
657
934
|
"Follow this order:",
|
|
658
935
|
"",
|
|
659
|
-
|
|
936
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`.`,
|
|
660
937
|
"2. Explain each diagnostic finding with severity and provenance.",
|
|
661
938
|
"3. Surface any import-state caveats or editor-side warnings.",
|
|
662
939
|
"4. If issues found, suggest concrete remediation steps.",
|
|
@@ -670,7 +947,7 @@ export function renderClaudeCheckCommand() {
|
|
|
670
947
|
"",
|
|
671
948
|
].join("\n");
|
|
672
949
|
}
|
|
673
|
-
export function renderCodexCheckSkill() {
|
|
950
|
+
export function renderCodexCheckSkill(pinnedVersion) {
|
|
674
951
|
return [
|
|
675
952
|
"---",
|
|
676
953
|
'name: "gdh-check"',
|
|
@@ -696,7 +973,7 @@ export function renderCodexCheckSkill() {
|
|
|
696
973
|
"<process>",
|
|
697
974
|
"Follow this order:",
|
|
698
975
|
"",
|
|
699
|
-
|
|
976
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
700
977
|
"- explain each diagnostic finding with severity and provenance",
|
|
701
978
|
"- surface any import-state caveats or editor-side warnings",
|
|
702
979
|
"- if issues found, suggest concrete remediation steps",
|
|
@@ -710,7 +987,7 @@ export function renderCodexCheckSkill() {
|
|
|
710
987
|
"",
|
|
711
988
|
].join("\n");
|
|
712
989
|
}
|
|
713
|
-
export function renderCursorCheckSkill() {
|
|
990
|
+
export function renderCursorCheckSkill(pinnedVersion) {
|
|
714
991
|
return [
|
|
715
992
|
"---",
|
|
716
993
|
"name: gdh-check",
|
|
@@ -734,7 +1011,7 @@ export function renderCursorCheckSkill() {
|
|
|
734
1011
|
"<process>",
|
|
735
1012
|
"Follow this order:",
|
|
736
1013
|
"",
|
|
737
|
-
|
|
1014
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
738
1015
|
"- explain each diagnostic finding with severity and provenance",
|
|
739
1016
|
"- surface any import-state caveats or editor-side warnings",
|
|
740
1017
|
"- if issues found, suggest concrete remediation steps",
|
|
@@ -749,7 +1026,7 @@ export function renderCursorCheckSkill() {
|
|
|
749
1026
|
].join("\n");
|
|
750
1027
|
}
|
|
751
1028
|
// --- gdh-prepare skill renders ---
|
|
752
|
-
export function renderClaudePrepareCommand() {
|
|
1029
|
+
export function renderClaudePrepareCommand(pinnedVersion) {
|
|
753
1030
|
return [
|
|
754
1031
|
"---",
|
|
755
1032
|
"name: gdh:prepare",
|
|
@@ -768,11 +1045,11 @@ export function renderClaudePrepareCommand() {
|
|
|
768
1045
|
"<process>",
|
|
769
1046
|
"Follow this order:",
|
|
770
1047
|
"",
|
|
771
|
-
|
|
1048
|
+
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions.`,
|
|
772
1049
|
"2. Explain what hydration and import refresh will do.",
|
|
773
|
-
|
|
1050
|
+
`3. If the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\`.`,
|
|
774
1051
|
"4. If a `--source-target` is relevant, explain when and why to use it.",
|
|
775
|
-
|
|
1052
|
+
`5. Verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
776
1053
|
"</process>",
|
|
777
1054
|
"",
|
|
778
1055
|
"<rules>",
|
|
@@ -783,7 +1060,7 @@ export function renderClaudePrepareCommand() {
|
|
|
783
1060
|
"",
|
|
784
1061
|
].join("\n");
|
|
785
1062
|
}
|
|
786
|
-
export function renderCodexPrepareSkill() {
|
|
1063
|
+
export function renderCodexPrepareSkill(pinnedVersion) {
|
|
787
1064
|
return [
|
|
788
1065
|
"---",
|
|
789
1066
|
'name: "gdh-prepare"',
|
|
@@ -809,11 +1086,11 @@ export function renderCodexPrepareSkill() {
|
|
|
809
1086
|
"<process>",
|
|
810
1087
|
"Follow this order:",
|
|
811
1088
|
"",
|
|
812
|
-
|
|
1089
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
813
1090
|
"- explain what hydration and import refresh will do",
|
|
814
|
-
|
|
1091
|
+
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
815
1092
|
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
816
|
-
|
|
1093
|
+
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
817
1094
|
"</process>",
|
|
818
1095
|
"",
|
|
819
1096
|
"<rules>",
|
|
@@ -824,7 +1101,7 @@ export function renderCodexPrepareSkill() {
|
|
|
824
1101
|
"",
|
|
825
1102
|
].join("\n");
|
|
826
1103
|
}
|
|
827
|
-
export function renderCursorPrepareSkill() {
|
|
1104
|
+
export function renderCursorPrepareSkill(pinnedVersion) {
|
|
828
1105
|
return [
|
|
829
1106
|
"---",
|
|
830
1107
|
"name: gdh-prepare",
|
|
@@ -848,11 +1125,11 @@ export function renderCursorPrepareSkill() {
|
|
|
848
1125
|
"<process>",
|
|
849
1126
|
"Follow this order:",
|
|
850
1127
|
"",
|
|
851
|
-
|
|
1128
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
852
1129
|
"- explain what hydration and import refresh will do",
|
|
853
|
-
|
|
1130
|
+
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
854
1131
|
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
855
|
-
|
|
1132
|
+
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
856
1133
|
"</process>",
|
|
857
1134
|
"",
|
|
858
1135
|
"<rules>",
|
|
@@ -864,7 +1141,7 @@ export function renderCursorPrepareSkill() {
|
|
|
864
1141
|
].join("\n");
|
|
865
1142
|
}
|
|
866
1143
|
// --- gdh-verify skill renders ---
|
|
867
|
-
export function renderClaudeVerifyCommand() {
|
|
1144
|
+
export function renderClaudeVerifyCommand(pinnedVersion) {
|
|
868
1145
|
return [
|
|
869
1146
|
"---",
|
|
870
1147
|
"name: gdh:verify",
|
|
@@ -883,8 +1160,8 @@ export function renderClaudeVerifyCommand() {
|
|
|
883
1160
|
"Follow this order:",
|
|
884
1161
|
"",
|
|
885
1162
|
"1. Identify changed files from git diff or user input.",
|
|
886
|
-
|
|
887
|
-
|
|
1163
|
+
`2. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds.`,
|
|
1164
|
+
`3. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility.`,
|
|
888
1165
|
"4. Summarize gaps between recommended and performed validation.",
|
|
889
1166
|
"5. Suggest specific next verification steps.",
|
|
890
1167
|
"</process>",
|
|
@@ -897,7 +1174,7 @@ export function renderClaudeVerifyCommand() {
|
|
|
897
1174
|
"",
|
|
898
1175
|
].join("\n");
|
|
899
1176
|
}
|
|
900
|
-
export function renderCodexVerifySkill() {
|
|
1177
|
+
export function renderCodexVerifySkill(pinnedVersion) {
|
|
901
1178
|
return [
|
|
902
1179
|
"---",
|
|
903
1180
|
'name: "gdh-verify"',
|
|
@@ -924,8 +1201,8 @@ export function renderCodexVerifySkill() {
|
|
|
924
1201
|
"Follow this order:",
|
|
925
1202
|
"",
|
|
926
1203
|
"- identify changed files from git diff or user input",
|
|
927
|
-
|
|
928
|
-
|
|
1204
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1205
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
929
1206
|
"- summarize gaps between recommended and performed validation",
|
|
930
1207
|
"- suggest specific next verification steps",
|
|
931
1208
|
"</process>",
|
|
@@ -938,7 +1215,7 @@ export function renderCodexVerifySkill() {
|
|
|
938
1215
|
"",
|
|
939
1216
|
].join("\n");
|
|
940
1217
|
}
|
|
941
|
-
export function renderCursorVerifySkill() {
|
|
1218
|
+
export function renderCursorVerifySkill(pinnedVersion) {
|
|
942
1219
|
return [
|
|
943
1220
|
"---",
|
|
944
1221
|
"name: gdh-verify",
|
|
@@ -963,8 +1240,8 @@ export function renderCursorVerifySkill() {
|
|
|
963
1240
|
"Follow this order:",
|
|
964
1241
|
"",
|
|
965
1242
|
"- identify changed files from git diff or user input",
|
|
966
|
-
|
|
967
|
-
|
|
1243
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1244
|
+
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
968
1245
|
"- summarize gaps between recommended and performed validation",
|
|
969
1246
|
"- suggest specific next verification steps",
|
|
970
1247
|
"</process>",
|
|
@@ -980,7 +1257,9 @@ export function renderCursorVerifySkill() {
|
|
|
980
1257
|
async function inspectProjectMcpSupport(targetPath, options) {
|
|
981
1258
|
const projectConfig = await readProjectConfig(targetPath);
|
|
982
1259
|
const enabled = resolveProjectMcpEnabled(projectConfig);
|
|
983
|
-
const launcherContent =
|
|
1260
|
+
const launcherContent = options.pinnedVersion === null
|
|
1261
|
+
? null
|
|
1262
|
+
: renderManagedMcpLauncher(options.pinnedVersion);
|
|
984
1263
|
const managedMcpEntry = buildManagedMcpServerEntry({
|
|
985
1264
|
targetPath,
|
|
986
1265
|
integrationRootPath: options.integrationRootPath,
|
|
@@ -1090,6 +1369,13 @@ function inspectLauncherFile(launcherSource, expectedContent, enabled, bootstrap
|
|
|
1090
1369
|
summary: "The managed GDH MCP launcher is disabled for this target.",
|
|
1091
1370
|
};
|
|
1092
1371
|
}
|
|
1372
|
+
if (expectedContent === null) {
|
|
1373
|
+
return {
|
|
1374
|
+
present: launcherSource !== null,
|
|
1375
|
+
state: "missing",
|
|
1376
|
+
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.",
|
|
1377
|
+
};
|
|
1378
|
+
}
|
|
1093
1379
|
if (launcherSource === null) {
|
|
1094
1380
|
return {
|
|
1095
1381
|
present: false,
|
|
@@ -1182,6 +1468,20 @@ async function inspectCodexRegistration(targetPath, enabled, codexServerName, co
|
|
|
1182
1468
|
};
|
|
1183
1469
|
}
|
|
1184
1470
|
function inspectCodexSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
|
|
1471
|
+
if (expectedContent === null) {
|
|
1472
|
+
return [
|
|
1473
|
+
createSurfaceStatus({
|
|
1474
|
+
kind: "skill_file",
|
|
1475
|
+
scope: "repo",
|
|
1476
|
+
targetPath,
|
|
1477
|
+
relativePath,
|
|
1478
|
+
present: content !== null,
|
|
1479
|
+
state: "missing",
|
|
1480
|
+
summary: `Codex ${skillName} skill cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1481
|
+
version: null,
|
|
1482
|
+
}),
|
|
1483
|
+
];
|
|
1484
|
+
}
|
|
1185
1485
|
return [
|
|
1186
1486
|
createSurfaceStatus({
|
|
1187
1487
|
kind: "skill_file",
|
|
@@ -1204,6 +1504,20 @@ function inspectCodexSkillSurface(targetPath, relativePath, content, expectedCon
|
|
|
1204
1504
|
];
|
|
1205
1505
|
}
|
|
1206
1506
|
function inspectClaudeCommandSurface(targetPath, relativePath, content, expectedContent, commandName) {
|
|
1507
|
+
if (expectedContent === null) {
|
|
1508
|
+
return [
|
|
1509
|
+
createSurfaceStatus({
|
|
1510
|
+
kind: "command_file",
|
|
1511
|
+
scope: "repo",
|
|
1512
|
+
targetPath,
|
|
1513
|
+
relativePath,
|
|
1514
|
+
present: content !== null,
|
|
1515
|
+
state: "missing",
|
|
1516
|
+
summary: `Claude ${commandName} command cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1517
|
+
version: null,
|
|
1518
|
+
}),
|
|
1519
|
+
];
|
|
1520
|
+
}
|
|
1207
1521
|
return [
|
|
1208
1522
|
createSurfaceStatus({
|
|
1209
1523
|
kind: "command_file",
|
|
@@ -1226,6 +1540,20 @@ function inspectClaudeCommandSurface(targetPath, relativePath, content, expected
|
|
|
1226
1540
|
];
|
|
1227
1541
|
}
|
|
1228
1542
|
function inspectCursorSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
|
|
1543
|
+
if (expectedContent === null) {
|
|
1544
|
+
return [
|
|
1545
|
+
createSurfaceStatus({
|
|
1546
|
+
kind: "skill_file",
|
|
1547
|
+
scope: "repo",
|
|
1548
|
+
targetPath,
|
|
1549
|
+
relativePath,
|
|
1550
|
+
present: content !== null,
|
|
1551
|
+
state: "missing",
|
|
1552
|
+
summary: `Cursor ${skillName} skill cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1553
|
+
version: null,
|
|
1554
|
+
}),
|
|
1555
|
+
];
|
|
1556
|
+
}
|
|
1229
1557
|
return [
|
|
1230
1558
|
createSurfaceStatus({
|
|
1231
1559
|
kind: "skill_file",
|
|
@@ -1247,14 +1575,28 @@ function inspectCursorSkillSurface(targetPath, relativePath, content, expectedCo
|
|
|
1247
1575
|
}),
|
|
1248
1576
|
];
|
|
1249
1577
|
}
|
|
1250
|
-
async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
1578
|
+
async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, options) {
|
|
1251
1579
|
const codexSkillPath = path.join(targetPath, CODEX_ONBOARD_SKILL_RELATIVE_PATH);
|
|
1252
1580
|
const codexSkillContent = await fs.readFile(codexSkillPath, "utf8").catch(() => null);
|
|
1253
1581
|
const codexStatusContent = await fs.readFile(path.join(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1254
1582
|
const codexMigrateContent = await fs.readFile(path.join(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1583
|
+
// Phase 13 Plan 13-03 deliverable — /gdh-update skill for Codex. Inspection
|
|
1584
|
+
// wiring is required so planSkillInstallAction can see the surface state;
|
|
1585
|
+
// otherwise the planner returns `unchanged` for a missing file and install
|
|
1586
|
+
// becomes a no-op (Plan 13-05 integration-test Rule 2 fix).
|
|
1587
|
+
const codexUpdateContent = await fs.readFile(path.join(targetPath, CODEX_UPDATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1255
1588
|
const codexCheckContent = await fs.readFile(path.join(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1256
1589
|
const codexPrepareContent = await fs.readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1257
1590
|
const codexVerifyContent = await fs.readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1591
|
+
const codexScanContent = await fs.readFile(path.join(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1592
|
+
const expectedCodexOnboardSkill = pinnedVersion === null ? null : renderCodexOnboardSkill(pinnedVersion);
|
|
1593
|
+
const expectedCodexStatusSkill = pinnedVersion === null ? null : renderCodexStatusSkill(pinnedVersion);
|
|
1594
|
+
const expectedCodexMigrateSkill = pinnedVersion === null ? null : renderCodexMigrateSkill(pinnedVersion);
|
|
1595
|
+
const expectedCodexUpdateSkill = pinnedVersion === null ? null : renderCodexUpdateSkill(pinnedVersion);
|
|
1596
|
+
const expectedCodexCheckSkill = pinnedVersion === null ? null : renderCodexCheckSkill(pinnedVersion);
|
|
1597
|
+
const expectedCodexPrepareSkill = pinnedVersion === null ? null : renderCodexPrepareSkill(pinnedVersion);
|
|
1598
|
+
const expectedCodexVerifySkill = pinnedVersion === null ? null : renderCodexVerifySkill(pinnedVersion);
|
|
1599
|
+
const expectedCodexScanSkill = pinnedVersion === null ? null : renderCodexScanSkill(pinnedVersion);
|
|
1258
1600
|
const surfaces = [
|
|
1259
1601
|
createSurfaceStatus({
|
|
1260
1602
|
kind: "canonical_entrypoint",
|
|
@@ -1282,21 +1624,27 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
|
1282
1624
|
present: codexSkillContent !== null,
|
|
1283
1625
|
state: codexSkillContent === null
|
|
1284
1626
|
? "missing"
|
|
1285
|
-
:
|
|
1286
|
-
? "
|
|
1287
|
-
:
|
|
1627
|
+
: expectedCodexOnboardSkill === null
|
|
1628
|
+
? "missing"
|
|
1629
|
+
: codexSkillContent === expectedCodexOnboardSkill
|
|
1630
|
+
? "ready"
|
|
1631
|
+
: "misconfigured",
|
|
1288
1632
|
summary: codexSkillContent === null
|
|
1289
1633
|
? "Codex onboarding handoff is missing and should install `/gdh-onboard` under .codex/skills/."
|
|
1290
|
-
:
|
|
1291
|
-
? "Codex
|
|
1292
|
-
:
|
|
1634
|
+
: expectedCodexOnboardSkill === null
|
|
1635
|
+
? "Codex onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1636
|
+
: codexSkillContent === expectedCodexOnboardSkill
|
|
1637
|
+
? "Codex can discover the managed `/gdh-onboard` handoff skill."
|
|
1638
|
+
: "Codex onboarding handoff exists but no longer matches the expected managed GDH skill.",
|
|
1293
1639
|
version: null,
|
|
1294
1640
|
}),
|
|
1295
|
-
...inspectCodexSkillSurface(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH, codexStatusContent,
|
|
1296
|
-
...inspectCodexSkillSurface(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH, codexMigrateContent,
|
|
1297
|
-
...inspectCodexSkillSurface(targetPath,
|
|
1298
|
-
...inspectCodexSkillSurface(targetPath,
|
|
1299
|
-
...inspectCodexSkillSurface(targetPath,
|
|
1641
|
+
...inspectCodexSkillSurface(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH, codexStatusContent, expectedCodexStatusSkill, "gdh-status"),
|
|
1642
|
+
...inspectCodexSkillSurface(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH, codexMigrateContent, expectedCodexMigrateSkill, "gdh-migrate"),
|
|
1643
|
+
...inspectCodexSkillSurface(targetPath, CODEX_UPDATE_SKILL_RELATIVE_PATH, codexUpdateContent, expectedCodexUpdateSkill, "gdh-update"),
|
|
1644
|
+
...inspectCodexSkillSurface(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH, codexCheckContent, expectedCodexCheckSkill, "gdh-check"),
|
|
1645
|
+
...inspectCodexSkillSurface(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH, codexPrepareContent, expectedCodexPrepareSkill, "gdh-prepare"),
|
|
1646
|
+
...inspectCodexSkillSurface(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH, codexVerifyContent, expectedCodexVerifySkill, "gdh-verify"),
|
|
1647
|
+
...inspectCodexSkillSurface(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH, codexScanContent, expectedCodexScanSkill, "gdh-scan"),
|
|
1300
1648
|
];
|
|
1301
1649
|
if (projectMcp.enabled) {
|
|
1302
1650
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1325,20 +1673,40 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, options) {
|
|
|
1325
1673
|
}
|
|
1326
1674
|
return createAgentStatus("codex", guidance, surfaces);
|
|
1327
1675
|
}
|
|
1328
|
-
async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
1676
|
+
async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVersion) {
|
|
1329
1677
|
const absolutePath = path.join(targetPath, CLAUDE_SHIM_RELATIVE_PATH);
|
|
1330
1678
|
const onboardCommandPath = path.join(targetPath, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH);
|
|
1331
1679
|
const lstat = await fs.lstat(absolutePath).catch(() => null);
|
|
1332
1680
|
const onboardCommandContent = await fs.readFile(onboardCommandPath, "utf8").catch(() => null);
|
|
1333
1681
|
const claudeStatusContent = await fs.readFile(path.join(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1334
1682
|
const claudeMigrateContent = await fs.readFile(path.join(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1683
|
+
// Phase 13 Plan 13-03 deliverable — /gdh-update slash command for Claude.
|
|
1684
|
+
// Inspection wiring is required so planSkillInstallAction can see the surface
|
|
1685
|
+
// state; otherwise the planner returns `unchanged` for a missing file and
|
|
1686
|
+
// install becomes a no-op (Plan 13-05 integration-test Rule 2 fix).
|
|
1687
|
+
const claudeUpdateContent = await fs.readFile(path.join(targetPath, CLAUDE_UPDATE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1335
1688
|
const claudeCheckContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1336
1689
|
const claudePrepareContent = await fs.readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1337
1690
|
const claudeVerifyContent = await fs.readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1691
|
+
const claudeScanContent = await fs.readFile(path.join(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1692
|
+
const claudeCheckUpdateHookContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1693
|
+
const claudeCheckUpdateWorkerContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1694
|
+
const claudeStatuslineContent = await fs.readFile(path.join(targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1338
1695
|
let detectedTarget = null;
|
|
1339
1696
|
if (lstat?.isSymbolicLink()) {
|
|
1340
1697
|
detectedTarget = await fs.readlink(absolutePath).catch(() => null);
|
|
1341
1698
|
}
|
|
1699
|
+
const expectedClaudeOnboardCommand = pinnedVersion === null ? null : renderClaudeOnboardCommand(pinnedVersion);
|
|
1700
|
+
const expectedClaudeCheckUpdateHook = pinnedVersion === null ? null : renderClaudeCheckUpdateHook(pinnedVersion);
|
|
1701
|
+
const expectedClaudeCheckUpdateWorker = pinnedVersion === null ? null : renderClaudeCheckUpdateWorker(pinnedVersion);
|
|
1702
|
+
const expectedClaudeStatusline = pinnedVersion === null ? null : renderClaudeUpdateStatusline(pinnedVersion);
|
|
1703
|
+
const expectedClaudeStatusCommand = pinnedVersion === null ? null : renderClaudeStatusCommand(pinnedVersion);
|
|
1704
|
+
const expectedClaudeMigrateCommand = pinnedVersion === null ? null : renderClaudeMigrateCommand(pinnedVersion);
|
|
1705
|
+
const expectedClaudeUpdateCommand = pinnedVersion === null ? null : renderClaudeUpdateCommand(pinnedVersion);
|
|
1706
|
+
const expectedClaudeCheckCommand = pinnedVersion === null ? null : renderClaudeCheckCommand(pinnedVersion);
|
|
1707
|
+
const expectedClaudePrepareCommand = pinnedVersion === null ? null : renderClaudePrepareCommand(pinnedVersion);
|
|
1708
|
+
const expectedClaudeVerifyCommand = pinnedVersion === null ? null : renderClaudeVerifyCommand(pinnedVersion);
|
|
1709
|
+
const expectedClaudeScanCommand = pinnedVersion === null ? null : renderClaudeScanCommand(pinnedVersion);
|
|
1342
1710
|
const surfaces = [
|
|
1343
1711
|
createSurfaceStatus({
|
|
1344
1712
|
kind: "symlink",
|
|
@@ -1368,21 +1736,30 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
|
1368
1736
|
present: onboardCommandContent !== null,
|
|
1369
1737
|
state: onboardCommandContent === null
|
|
1370
1738
|
? "missing"
|
|
1371
|
-
:
|
|
1372
|
-
? "
|
|
1373
|
-
:
|
|
1739
|
+
: expectedClaudeOnboardCommand === null
|
|
1740
|
+
? "missing"
|
|
1741
|
+
: onboardCommandContent === expectedClaudeOnboardCommand
|
|
1742
|
+
? "ready"
|
|
1743
|
+
: "misconfigured",
|
|
1374
1744
|
summary: onboardCommandContent === null
|
|
1375
1745
|
? "Claude onboarding handoff is missing and should install `/gdh-onboard` under .claude/commands/."
|
|
1376
|
-
:
|
|
1377
|
-
? "Claude
|
|
1378
|
-
:
|
|
1746
|
+
: expectedClaudeOnboardCommand === null
|
|
1747
|
+
? "Claude onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1748
|
+
: onboardCommandContent === expectedClaudeOnboardCommand
|
|
1749
|
+
? "Claude can discover the managed `/gdh-onboard` handoff command."
|
|
1750
|
+
: "Claude onboarding handoff exists but no longer matches the expected managed GDH command.",
|
|
1379
1751
|
version: null,
|
|
1380
1752
|
}),
|
|
1381
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent,
|
|
1382
|
-
...inspectClaudeCommandSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent,
|
|
1383
|
-
...inspectClaudeCommandSurface(targetPath,
|
|
1384
|
-
...inspectClaudeCommandSurface(targetPath,
|
|
1385
|
-
...inspectClaudeCommandSurface(targetPath,
|
|
1753
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent, expectedClaudeStatusCommand, "gdh-status"),
|
|
1754
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent, expectedClaudeMigrateCommand, "gdh-migrate"),
|
|
1755
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_UPDATE_COMMAND_RELATIVE_PATH, claudeUpdateContent, expectedClaudeUpdateCommand, "gdh-update"),
|
|
1756
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, claudeCheckContent, expectedClaudeCheckCommand, "gdh-check"),
|
|
1757
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, claudePrepareContent, expectedClaudePrepareCommand, "gdh-prepare"),
|
|
1758
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, claudeVerifyContent, expectedClaudeVerifyCommand, "gdh-verify"),
|
|
1759
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH, claudeScanContent, expectedClaudeScanCommand, "gdh-scan"),
|
|
1760
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, claudeCheckUpdateHookContent, expectedClaudeCheckUpdateHook, "gdh-check-update-hook"),
|
|
1761
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, claudeCheckUpdateWorkerContent, expectedClaudeCheckUpdateWorker, "gdh-check-update-worker"),
|
|
1762
|
+
...inspectClaudeCommandSurface(targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH, claudeStatuslineContent, expectedClaudeStatusline, "gdh-statusline"),
|
|
1386
1763
|
];
|
|
1387
1764
|
if (projectMcp.enabled) {
|
|
1388
1765
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1409,18 +1786,32 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp) {
|
|
|
1409
1786
|
}
|
|
1410
1787
|
return createAgentStatus("claude", guidance, surfaces);
|
|
1411
1788
|
}
|
|
1412
|
-
async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
|
|
1789
|
+
async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVersion) {
|
|
1413
1790
|
const absolutePath = path.join(targetPath, CURSOR_RULE_RELATIVE_PATH);
|
|
1414
1791
|
const onboardSkillPath = path.join(targetPath, CURSOR_ONBOARD_SKILL_RELATIVE_PATH);
|
|
1415
1792
|
const content = await fs.readFile(absolutePath, "utf8").catch(() => null);
|
|
1416
1793
|
const onboardSkillContent = await fs.readFile(onboardSkillPath, "utf8").catch(() => null);
|
|
1417
1794
|
const cursorStatusContent = await fs.readFile(path.join(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1418
1795
|
const cursorMigrateContent = await fs.readFile(path.join(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1796
|
+
// Phase 13 Plan 13-03 deliverable — /gdh-update skill for Cursor. Inspection
|
|
1797
|
+
// wiring required so planSkillInstallAction sees the surface state; otherwise
|
|
1798
|
+
// the planner returns `unchanged` for a missing file and install becomes a
|
|
1799
|
+
// no-op (Plan 13-05 integration-test Rule 2 fix).
|
|
1800
|
+
const cursorUpdateContent = await fs.readFile(path.join(targetPath, CURSOR_UPDATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1419
1801
|
const cursorCheckContent = await fs.readFile(path.join(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1420
1802
|
const cursorPrepareContent = await fs.readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1421
1803
|
const cursorVerifyContent = await fs.readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1804
|
+
const cursorScanContent = await fs.readFile(path.join(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
|
|
1422
1805
|
const expectedContent = renderCursorRule();
|
|
1423
1806
|
const version = readCursorRuleVersion(content);
|
|
1807
|
+
const expectedCursorOnboardSkill = pinnedVersion === null ? null : renderCursorOnboardSkill(pinnedVersion);
|
|
1808
|
+
const expectedCursorStatusSkill = pinnedVersion === null ? null : renderCursorStatusSkill(pinnedVersion);
|
|
1809
|
+
const expectedCursorMigrateSkill = pinnedVersion === null ? null : renderCursorMigrateSkill(pinnedVersion);
|
|
1810
|
+
const expectedCursorUpdateSkill = pinnedVersion === null ? null : renderCursorUpdateSkill(pinnedVersion);
|
|
1811
|
+
const expectedCursorCheckSkill = pinnedVersion === null ? null : renderCursorCheckSkill(pinnedVersion);
|
|
1812
|
+
const expectedCursorPrepareSkill = pinnedVersion === null ? null : renderCursorPrepareSkill(pinnedVersion);
|
|
1813
|
+
const expectedCursorVerifySkill = pinnedVersion === null ? null : renderCursorVerifySkill(pinnedVersion);
|
|
1814
|
+
const expectedCursorScanSkill = pinnedVersion === null ? null : renderCursorScanSkill(pinnedVersion);
|
|
1424
1815
|
const surfaces = [
|
|
1425
1816
|
createSurfaceStatus({
|
|
1426
1817
|
kind: "rule_file",
|
|
@@ -1448,21 +1839,27 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp) {
|
|
|
1448
1839
|
present: onboardSkillContent !== null,
|
|
1449
1840
|
state: onboardSkillContent === null
|
|
1450
1841
|
? "missing"
|
|
1451
|
-
:
|
|
1452
|
-
? "
|
|
1453
|
-
:
|
|
1842
|
+
: expectedCursorOnboardSkill === null
|
|
1843
|
+
? "missing"
|
|
1844
|
+
: onboardSkillContent === expectedCursorOnboardSkill
|
|
1845
|
+
? "ready"
|
|
1846
|
+
: "misconfigured",
|
|
1454
1847
|
summary: onboardSkillContent === null
|
|
1455
1848
|
? "Cursor onboarding handoff is missing and should install `/gdh-onboard` under .cursor/skills/."
|
|
1456
|
-
:
|
|
1457
|
-
? "Cursor
|
|
1458
|
-
:
|
|
1849
|
+
: expectedCursorOnboardSkill === null
|
|
1850
|
+
? "Cursor onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1851
|
+
: onboardSkillContent === expectedCursorOnboardSkill
|
|
1852
|
+
? "Cursor can discover the managed `/gdh-onboard` handoff skill."
|
|
1853
|
+
: "Cursor onboarding handoff exists but no longer matches the expected managed GDH skill.",
|
|
1459
1854
|
version: null,
|
|
1460
1855
|
}),
|
|
1461
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH, cursorStatusContent,
|
|
1462
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, cursorMigrateContent,
|
|
1463
|
-
...inspectCursorSkillSurface(targetPath,
|
|
1464
|
-
...inspectCursorSkillSurface(targetPath,
|
|
1465
|
-
...inspectCursorSkillSurface(targetPath,
|
|
1856
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH, cursorStatusContent, expectedCursorStatusSkill, "gdh-status"),
|
|
1857
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, cursorMigrateContent, expectedCursorMigrateSkill, "gdh-migrate"),
|
|
1858
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_UPDATE_SKILL_RELATIVE_PATH, cursorUpdateContent, expectedCursorUpdateSkill, "gdh-update"),
|
|
1859
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH, cursorCheckContent, expectedCursorCheckSkill, "gdh-check"),
|
|
1860
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH, cursorPrepareContent, expectedCursorPrepareSkill, "gdh-prepare"),
|
|
1861
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH, cursorVerifyContent, expectedCursorVerifySkill, "gdh-verify"),
|
|
1862
|
+
...inspectCursorSkillSurface(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH, cursorScanContent, expectedCursorScanSkill, "gdh-scan"),
|
|
1466
1863
|
];
|
|
1467
1864
|
if (projectMcp.enabled) {
|
|
1468
1865
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1552,6 +1949,7 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
1552
1949
|
const projectMcp = await inspectProjectMcpSupport(targetPath, {
|
|
1553
1950
|
includeUserLocal: true,
|
|
1554
1951
|
integrationRootPath: options.integrationRootPath,
|
|
1952
|
+
pinnedVersion: options.pinnedVersion,
|
|
1555
1953
|
});
|
|
1556
1954
|
const actions = [];
|
|
1557
1955
|
const effectiveDevRepoPath = options.devRepoPath ?? resolveCurrentGdhInstall(import.meta.url).defaultDevRepoPath;
|
|
@@ -1567,15 +1965,15 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
1567
1965
|
continue;
|
|
1568
1966
|
}
|
|
1569
1967
|
if (adapter.agent === "codex") {
|
|
1570
|
-
actions.push(...planCodexRepoInstallActions(targetPath, adapter));
|
|
1968
|
+
actions.push(...planCodexRepoInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1571
1969
|
continue;
|
|
1572
1970
|
}
|
|
1573
1971
|
if (adapter.agent === "claude") {
|
|
1574
|
-
actions.push(...planClaudeInstallActions(targetPath, adapter));
|
|
1972
|
+
actions.push(...planClaudeInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1575
1973
|
continue;
|
|
1576
1974
|
}
|
|
1577
1975
|
if (adapter.agent === "cursor") {
|
|
1578
|
-
actions.push(...planCursorInstallActions(targetPath, adapter));
|
|
1976
|
+
actions.push(...planCursorInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
1579
1977
|
}
|
|
1580
1978
|
}
|
|
1581
1979
|
return dedupeInstallActions(actions);
|
|
@@ -1667,7 +2065,7 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1667
2065
|
}
|
|
1668
2066
|
return actions;
|
|
1669
2067
|
}
|
|
1670
|
-
function planSkillInstallAction(agent, targetPath, adapter, relativePath, renderFn, skillName) {
|
|
2068
|
+
function planSkillInstallAction(agent, targetPath, adapter, relativePath, renderFn, skillName, pinnedVersion) {
|
|
1671
2069
|
const surface = adapter.surfaces.find((s) => s.relativePath === relativePath);
|
|
1672
2070
|
if (!surface || surface.state === "ready") {
|
|
1673
2071
|
return createInstallAction({
|
|
@@ -1679,7 +2077,7 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
1679
2077
|
state: "unchanged",
|
|
1680
2078
|
mode: "unchanged",
|
|
1681
2079
|
summary: `The managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} already matches the expected GDH content.`,
|
|
1682
|
-
content: renderFn(),
|
|
2080
|
+
content: renderFn(pinnedVersion),
|
|
1683
2081
|
});
|
|
1684
2082
|
}
|
|
1685
2083
|
return createInstallAction({
|
|
@@ -1693,7 +2091,7 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
1693
2091
|
summary: surface.present
|
|
1694
2092
|
? `Replace the existing ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"} with the managed GDH ${agent === "claude" ? "command" : "skill"}.`
|
|
1695
2093
|
: `Create the managed ${agentLabel(agent)} \`/${skillName}\` ${agent === "claude" ? "command" : "skill"}.`,
|
|
1696
|
-
content: renderFn(),
|
|
2094
|
+
content: renderFn(pinnedVersion),
|
|
1697
2095
|
});
|
|
1698
2096
|
}
|
|
1699
2097
|
function agentLabel(agent) {
|
|
@@ -1706,14 +2104,16 @@ function agentLabel(agent) {
|
|
|
1706
2104
|
return "Cursor";
|
|
1707
2105
|
}
|
|
1708
2106
|
}
|
|
1709
|
-
function planCodexRepoInstallActions(targetPath, adapter) {
|
|
2107
|
+
function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1710
2108
|
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,
|
|
1715
|
-
planSkillInstallAction("codex", targetPath, adapter,
|
|
1716
|
-
planSkillInstallAction("codex", targetPath, adapter,
|
|
2109
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_ONBOARD_SKILL_RELATIVE_PATH, renderCodexOnboardSkill, "gdh-onboard", pinnedVersion),
|
|
2110
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_STATUS_SKILL_RELATIVE_PATH, renderCodexStatusSkill, "gdh-status", pinnedVersion),
|
|
2111
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_MIGRATE_SKILL_RELATIVE_PATH, renderCodexMigrateSkill, "gdh-migrate", pinnedVersion),
|
|
2112
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_UPDATE_SKILL_RELATIVE_PATH, renderCodexUpdateSkill, "gdh-update", pinnedVersion),
|
|
2113
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_CHECK_SKILL_RELATIVE_PATH, renderCodexCheckSkill, "gdh-check", pinnedVersion),
|
|
2114
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_PREPARE_SKILL_RELATIVE_PATH, renderCodexPrepareSkill, "gdh-prepare", pinnedVersion),
|
|
2115
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_VERIFY_SKILL_RELATIVE_PATH, renderCodexVerifySkill, "gdh-verify", pinnedVersion),
|
|
2116
|
+
planSkillInstallAction("codex", targetPath, adapter, CODEX_SCAN_SKILL_RELATIVE_PATH, renderCodexScanSkill, "gdh-scan", pinnedVersion),
|
|
1717
2117
|
];
|
|
1718
2118
|
}
|
|
1719
2119
|
function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath) {
|
|
@@ -1764,7 +2164,7 @@ function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath
|
|
|
1764
2164
|
}));
|
|
1765
2165
|
return actions;
|
|
1766
2166
|
}
|
|
1767
|
-
function planClaudeInstallActions(targetPath, adapter) {
|
|
2167
|
+
function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1768
2168
|
const actions = [];
|
|
1769
2169
|
const claudeSurface = adapter.surfaces.find((surface) => surface.relativePath === CLAUDE_SHIM_RELATIVE_PATH);
|
|
1770
2170
|
if (!claudeSurface || claudeSurface.state === "ready") {
|
|
@@ -1795,10 +2195,58 @@ function planClaudeInstallActions(targetPath, adapter) {
|
|
|
1795
2195
|
expectedTarget: "AGENTS.md",
|
|
1796
2196
|
}));
|
|
1797
2197
|
}
|
|
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"))
|
|
2198
|
+
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_UPDATE_COMMAND_RELATIVE_PATH, renderClaudeUpdateCommand, "gdh-update", 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),
|
|
2199
|
+
// UPD-01 managed hook surfaces baked at the pinned version.
|
|
2200
|
+
planSkillInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, renderClaudeCheckUpdateHook, "gdh-check-update-hook", pinnedVersion), planSkillInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateWorker, "gdh-check-update-worker", pinnedVersion),
|
|
2201
|
+
// UPD-02 managed statusline surface baked at the pinned version. The .js
|
|
2202
|
+
// file is ALWAYS baked, even when settings.json statusLine is not owned
|
|
2203
|
+
// by GDH (write-if-absent below) — users can manually point their config
|
|
2204
|
+
// at gdh-statusline.js later; the baked file is a no-op until wired.
|
|
2205
|
+
planSkillInstallAction("claude", targetPath, adapter, CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, "gdh-statusline", pinnedVersion));
|
|
2206
|
+
// UPD-01 + UPD-02 .claude/settings.json composite patch action.
|
|
2207
|
+
// - Plan 02 (Strategy A, planner-lock #1): patch-merge the SessionStart
|
|
2208
|
+
// hook entry by exact command-literal match, preserving siblings.
|
|
2209
|
+
// - Plan 03 (write-if-absent, planner-lock #2 / D-18): add the statusLine
|
|
2210
|
+
// entry ONLY when no existing statusLine is configured (e.g. GSD-owned
|
|
2211
|
+
// or user-owned). Silent no-op for UPD-02 on targets where another
|
|
2212
|
+
// tool already owns the slot; the universal surface is MCP _meta.
|
|
2213
|
+
//
|
|
2214
|
+
// Synchronous read via fsSync is intentional: planClaudeInstallActions is
|
|
2215
|
+
// called without `await`, and making it async would ripple to every sibling
|
|
2216
|
+
// planner (Codex, Cursor). The composed patches are idempotent and
|
|
2217
|
+
// commutative (proven in Task 1 Test J) so application order is irrelevant.
|
|
2218
|
+
let existingSettingsContent = "";
|
|
2219
|
+
try {
|
|
2220
|
+
existingSettingsContent = fsSync.readFileSync(path.join(targetPath, CLAUDE_SETTINGS_RELATIVE_PATH), "utf8");
|
|
2221
|
+
}
|
|
2222
|
+
catch {
|
|
2223
|
+
existingSettingsContent = "";
|
|
2224
|
+
}
|
|
2225
|
+
const patchedSettings = patchClaudeSettingsForGdhStatusline(patchClaudeSettingsForGdhSessionStart(existingSettingsContent));
|
|
2226
|
+
const settingsIsUnchanged = existingSettingsContent === patchedSettings;
|
|
2227
|
+
const settingsExistedOnDisk = existingSettingsContent.length > 0;
|
|
2228
|
+
actions.push(createInstallAction({
|
|
2229
|
+
agent: "claude",
|
|
2230
|
+
kind: "write_file",
|
|
2231
|
+
scope: "repo",
|
|
2232
|
+
targetPath,
|
|
2233
|
+
relativePath: CLAUDE_SETTINGS_RELATIVE_PATH,
|
|
2234
|
+
state: settingsIsUnchanged ? "unchanged" : "planned",
|
|
2235
|
+
mode: settingsIsUnchanged
|
|
2236
|
+
? "unchanged"
|
|
2237
|
+
: settingsExistedOnDisk
|
|
2238
|
+
? "replace"
|
|
2239
|
+
: "create",
|
|
2240
|
+
summary: settingsIsUnchanged
|
|
2241
|
+
? "GDH SessionStart hook + statusline already registered in .claude/settings.json."
|
|
2242
|
+
: settingsExistedOnDisk
|
|
2243
|
+
? "Register the GDH SessionStart hook and statusline (write-if-absent) in .claude/settings.json while preserving sibling content (patch-merge)."
|
|
2244
|
+
: "Create .claude/settings.json with the GDH SessionStart hook + statusline registration.",
|
|
2245
|
+
content: patchedSettings,
|
|
2246
|
+
}));
|
|
1799
2247
|
return actions;
|
|
1800
2248
|
}
|
|
1801
|
-
function planCursorInstallActions(targetPath, adapter) {
|
|
2249
|
+
function planCursorInstallActions(targetPath, adapter, pinnedVersion) {
|
|
1802
2250
|
const actions = [];
|
|
1803
2251
|
const cursorRuleSurface = adapter.surfaces.find((surface) => surface.relativePath === CURSOR_RULE_RELATIVE_PATH);
|
|
1804
2252
|
if (!cursorRuleSurface || cursorRuleSurface.state === "ready") {
|
|
@@ -1831,7 +2279,7 @@ function planCursorInstallActions(targetPath, adapter) {
|
|
|
1831
2279
|
content: renderCursorRule(),
|
|
1832
2280
|
}));
|
|
1833
2281
|
}
|
|
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"));
|
|
2282
|
+
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_UPDATE_SKILL_RELATIVE_PATH, renderCursorUpdateSkill, "gdh-update", 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
2283
|
return actions;
|
|
1836
2284
|
}
|
|
1837
2285
|
function dedupeInstallActions(actions) {
|
|
@@ -1929,7 +2377,7 @@ function resolveProjectMcpEnabled(projectConfig) {
|
|
|
1929
2377
|
function createCodexServerName(projectKeySeed) {
|
|
1930
2378
|
return `gdh-${projectKeySeed}`;
|
|
1931
2379
|
}
|
|
1932
|
-
function renderManagedMcpLauncher() {
|
|
2380
|
+
export function renderManagedMcpLauncher(pinnedVersion) {
|
|
1933
2381
|
return [
|
|
1934
2382
|
"#!/usr/bin/env node",
|
|
1935
2383
|
`// GDH MCP launcher v${GDH_MCP_LAUNCHER_VERSION}`,
|
|
@@ -1968,9 +2416,9 @@ function renderManagedMcpLauncher() {
|
|
|
1968
2416
|
" }",
|
|
1969
2417
|
"}",
|
|
1970
2418
|
"",
|
|
1971
|
-
|
|
2419
|
+
`const result = spawnSync("npx", ["-y", "@skillcap/gdh@${pinnedVersion}", "mcp", "serve", "--target", targetPath], { stdio: "inherit", cwd: targetPath });`,
|
|
1972
2420
|
'if (result.error && result.error.code === "ENOENT") {',
|
|
1973
|
-
|
|
2421
|
+
` 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
2422
|
" process.exit(1);",
|
|
1975
2423
|
"}",
|
|
1976
2424
|
"process.exit(result.status ?? 1);",
|
|
@@ -3050,4 +3498,7 @@ function deriveRepoState(context) {
|
|
|
3050
3498
|
function normalizeChangedFiles(files) {
|
|
3051
3499
|
return [...new Set(files.map((file) => file.trim()).filter((file) => file.length > 0))];
|
|
3052
3500
|
}
|
|
3501
|
+
export { bumpAndRebakePin, } from "./self-update-mechanics.js";
|
|
3502
|
+
export { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH } from "./claude-update-hook-render.js";
|
|
3503
|
+
export { CLAUDE_STATUSLINE_RELATIVE_PATH } from "./claude-statusline-render.js";
|
|
3053
3504
|
//# sourceMappingURL=index.js.map
|