@skillcap/gdh 0.26.9 → 1.0.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 +1 -1
- package/RELEASE-SPAN-UPDATE-CONTRACTS.json +126 -0
- package/node_modules/@gdh/adapters/dist/codex-authoring-hook-block.d.ts +16 -0
- package/node_modules/@gdh/adapters/dist/codex-authoring-hook-block.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/codex-authoring-hook-block.js +40 -0
- package/node_modules/@gdh/adapters/dist/codex-authoring-hook-block.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/index.d.ts +2 -26
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +120 -432
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts +2 -9
- package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/skill-rendering.js +20 -49
- package/node_modules/@gdh/adapters/dist/skill-rendering.js.map +1 -1
- package/node_modules/@gdh/adapters/package.json +8 -8
- 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 +10 -18
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.js +1 -4
- 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 +6 -12
- 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 +8 -5
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +5 -6
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts +15 -51
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js +9 -64
- package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.d.ts +6 -17
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js +6 -22
- package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js.map +1 -1
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/dist/recovery-hints.d.ts +18 -4
- package/node_modules/@gdh/docs/dist/recovery-hints.d.ts.map +1 -1
- package/node_modules/@gdh/docs/dist/recovery-hints.js +32 -34
- package/node_modules/@gdh/docs/dist/recovery-hints.js.map +1 -1
- package/node_modules/@gdh/docs/package.json +2 -2
- package/node_modules/@gdh/mcp/package.json +8 -8
- package/node_modules/@gdh/observability/package.json +2 -2
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/dist/onboard.js +2 -2
- 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
|
@@ -5,22 +5,22 @@ import os from "node:os";
|
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { readProjectConfig, readWorktreeState, resolveAuthoringStatus, resolveEffectiveTargetPath, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, } from "@gdh/authoring";
|
|
8
|
-
import { assertClassRegistered, assertProjectLifecycleCompatibilityInvariant, definePackageBoundary, GDH_AGENT_CONTRACT_VERSION,
|
|
8
|
+
import { assertClassRegistered, assertProjectLifecycleCompatibilityInvariant, definePackageBoundary, GDH_AGENT_CONTRACT_VERSION, GDH_GUIDANCE_INDEX_VERSION, GDH_GUIDANCE_UNIT_VERSION, GDH_PROJECT_CONFIG_VERSION, GDH_RECIPE_SCHEMA_VERSION, GDH_RULES_SCHEMA_VERSION, GDH_SCENARIO_SCHEMA_VERSION, resolveConfiguredGodotEditorBin, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
|
|
9
9
|
import { GDH_GUIDANCE_DIRECTORY_RELATIVE_PATH, GUIDANCE_INDEX_RELATIVE_PATH, createDefaultGuidanceUnits, createDefaultRulesDocument, getGuidanceStatus, readRulesDocument, renderRulesYaml, resolveGuidanceQuery, resolveRecoveryHints, } from "@gdh/docs";
|
|
10
10
|
import { inspectGuidanceAudit } from "@gdh/observability";
|
|
11
11
|
import { inspectRuntimeBridgeBroker, inspectRuntimeBridgeSurface, inspectRuntimeKnowledgeSurface, } from "@gdh/runtime";
|
|
12
12
|
import { readInventoryCacheOrScan } from "@gdh/scan";
|
|
13
13
|
import { CLAUDE_SETTINGS_RELATIVE_PATH, patchClaudeSettingsForGdhAuthoringHooks, patchClaudeSettingsForGdhSessionStart, patchClaudeSettingsForGdhStatusline, } from "./claude-settings-patch.js";
|
|
14
14
|
import { computeDeferredActionsAdvisory, } from "./deferred-actions-advisory.js";
|
|
15
|
-
import { CLAUDE_AUTHORING_HOOK_RELATIVE_PATH,
|
|
15
|
+
import { CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, CODEX_AUTHORING_HOOK_RELATIVE_PATH, renderGdhAuthoringHook, } from "./authoring-hook-render.js";
|
|
16
16
|
import { computeStateRelativePathFromHook } from "./authoring-hook-state-path.js";
|
|
17
|
+
import { removeManagedCodexAuthoringHookBlock, renderManagedCodexAuthoringHookBlock, } from "./codex-authoring-hook-block.js";
|
|
17
18
|
import { CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, } from "./claude-statusline-render.js";
|
|
18
19
|
import { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateHook, } from "./claude-update-hook-render.js";
|
|
19
20
|
import { renderClaudeCheckUpdateWorker } from "./claude-update-worker-render.js";
|
|
20
|
-
import { GDH_MANAGED_AGENT_SKILL_MARKER, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeRunGameSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexRunGameSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill,
|
|
21
|
-
export { GDH_MANAGED_AGENT_SKILL_MARKER, GDH_SKILL_DEFINITIONS, GDH_SKILL_IDS, renderGdhSkill, renderManagedSkillMarker, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeRunGameSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexRunGameSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill,
|
|
21
|
+
import { GDH_MANAGED_AGENT_SKILL_MARKER, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeRunGameSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexRunGameSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill, } from "./skill-rendering.js";
|
|
22
|
+
export { GDH_MANAGED_AGENT_SKILL_MARKER, GDH_SKILL_DEFINITIONS, GDH_SKILL_IDS, renderGdhSkill, renderManagedSkillMarker, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeRunGameSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexRunGameSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill, } from "./skill-rendering.js";
|
|
22
23
|
// Module-load drift guard. See packages/core/src/migrations/managed-surface-classes.ts.
|
|
23
|
-
assertClassRegistered("cursor_rule", "deterministic");
|
|
24
24
|
assertClassRegistered("claude_onboard_command", "deterministic");
|
|
25
25
|
assertClassRegistered("claude_status_command", "deterministic");
|
|
26
26
|
assertClassRegistered("claude_scan_command", "deterministic");
|
|
@@ -48,14 +48,10 @@ export const adaptersPackage = definePackageBoundary({
|
|
|
48
48
|
export const SUPPORTED_AGENTS = [
|
|
49
49
|
"codex",
|
|
50
50
|
"claude",
|
|
51
|
-
"cursor",
|
|
52
51
|
];
|
|
53
52
|
export const CLAUDE_SHIM_RELATIVE_PATH = "CLAUDE.md";
|
|
54
53
|
export const CLAUDE_ONBOARD_SKILL_RELATIVE_PATH = ".claude/skills/gdh-onboard/SKILL.md";
|
|
55
54
|
export const PROJECT_MCP_RELATIVE_PATH = ".mcp.json";
|
|
56
|
-
export const CURSOR_MCP_RELATIVE_PATH = ".cursor/mcp.json";
|
|
57
|
-
export const CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/gdh-agent.mdc";
|
|
58
|
-
export const CURSOR_ONBOARD_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-onboard.md";
|
|
59
55
|
export const CODEX_ONBOARD_SKILL_RELATIVE_PATH = ".agents/skills/gdh-onboard/SKILL.md";
|
|
60
56
|
export const CLAUDE_STATUS_SKILL_RELATIVE_PATH = ".claude/skills/gdh-status/SKILL.md";
|
|
61
57
|
export const CLAUDE_MIGRATE_SKILL_RELATIVE_PATH = ".claude/skills/gdh-migrate/SKILL.md";
|
|
@@ -67,10 +63,6 @@ export const CODEX_MIGRATE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-migrate/SKI
|
|
|
67
63
|
export const CODEX_CHECK_SKILL_RELATIVE_PATH = ".agents/skills/gdh-check/SKILL.md";
|
|
68
64
|
export const CODEX_PREPARE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-prepare/SKILL.md";
|
|
69
65
|
export const CODEX_RUN_GAME_SKILL_RELATIVE_PATH = ".agents/skills/gdh-run-game/SKILL.md";
|
|
70
|
-
export const CURSOR_STATUS_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-status.md";
|
|
71
|
-
export const CURSOR_MIGRATE_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-migrate.md";
|
|
72
|
-
export const CURSOR_PREPARE_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-prepare.md";
|
|
73
|
-
export const CURSOR_RUN_GAME_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-run-game.md";
|
|
74
66
|
// Phase 13 SELF-01: /gdh-update skill surface path constants. The rendered
|
|
75
67
|
// bodies shell out to `npx -y @skillcap/gdh@latest self-update` (LITERAL
|
|
76
68
|
// @latest, not the pinned version — D-10) so the NEW CLI performs the update,
|
|
@@ -79,7 +71,6 @@ export const CURSOR_RUN_GAME_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-run-g
|
|
|
79
71
|
// rendered bodies are version-agnostic by design.
|
|
80
72
|
export const CLAUDE_UPDATE_SKILL_RELATIVE_PATH = ".claude/skills/gdh-update/SKILL.md";
|
|
81
73
|
export const CODEX_UPDATE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-update/SKILL.md";
|
|
82
|
-
export const CURSOR_UPDATE_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-update.md";
|
|
83
74
|
export const CLAUDE_SCAN_SKILL_RELATIVE_PATH = ".claude/skills/gdh-scan/SKILL.md";
|
|
84
75
|
export const CODEX_SCAN_SKILL_RELATIVE_PATH = ".agents/skills/gdh-scan/SKILL.md";
|
|
85
76
|
export const CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH = CLAUDE_ONBOARD_SKILL_RELATIVE_PATH;
|
|
@@ -111,18 +102,6 @@ const LEGACY_CODEX_SKILL_RELATIVE_PATHS = [
|
|
|
111
102
|
[".codex/skills/gdh-verify/SKILL.md", "gdh-verify"],
|
|
112
103
|
[".codex/skills/gdh-scan/SKILL.md", "gdh-scan"],
|
|
113
104
|
];
|
|
114
|
-
const LEGACY_CURSOR_SKILL_RELATIVE_PATHS = [
|
|
115
|
-
[".cursor/skills/gdh-onboard/SKILL.md", "gdh-onboard"],
|
|
116
|
-
[".cursor/skills/gdh-status/SKILL.md", "gdh-status"],
|
|
117
|
-
[".cursor/skills/gdh-migrate/SKILL.md", "gdh-migrate"],
|
|
118
|
-
[".cursor/skills/gdh-update/SKILL.md", "gdh-update"],
|
|
119
|
-
[".cursor/skills/gdh-check/SKILL.md", "gdh-check"],
|
|
120
|
-
[".cursor/skills/gdh-prepare/SKILL.md", "gdh-prepare"],
|
|
121
|
-
[".cursor/skills/gdh-run-game/SKILL.md", "gdh-run-game"],
|
|
122
|
-
[".cursor/skills/gdh-verify/SKILL.md", "gdh-verify"],
|
|
123
|
-
[".cursor/skills/gdh-scan/SKILL.md", "gdh-scan"],
|
|
124
|
-
];
|
|
125
|
-
export const CURSOR_SCAN_COMMAND_RELATIVE_PATH = ".cursor/commands/gdh-scan.md";
|
|
126
105
|
const CODEX_SKILL_RELATIVE_PATHS = [
|
|
127
106
|
path.dirname(CODEX_ONBOARD_SKILL_RELATIVE_PATH),
|
|
128
107
|
path.dirname(CODEX_STATUS_SKILL_RELATIVE_PATH),
|
|
@@ -132,14 +111,14 @@ const CODEX_SKILL_RELATIVE_PATHS = [
|
|
|
132
111
|
path.dirname(CODEX_RUN_GAME_SKILL_RELATIVE_PATH),
|
|
133
112
|
path.dirname(CODEX_SCAN_SKILL_RELATIVE_PATH),
|
|
134
113
|
];
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
114
|
+
const CLAUDE_SKILL_RELATIVE_PATHS = [
|
|
115
|
+
path.dirname(CLAUDE_ONBOARD_SKILL_RELATIVE_PATH),
|
|
116
|
+
path.dirname(CLAUDE_STATUS_SKILL_RELATIVE_PATH),
|
|
117
|
+
path.dirname(CLAUDE_MIGRATE_SKILL_RELATIVE_PATH),
|
|
118
|
+
path.dirname(CLAUDE_UPDATE_SKILL_RELATIVE_PATH),
|
|
119
|
+
path.dirname(CLAUDE_PREPARE_SKILL_RELATIVE_PATH),
|
|
120
|
+
path.dirname(CLAUDE_RUN_GAME_SKILL_RELATIVE_PATH),
|
|
121
|
+
path.dirname(CLAUDE_SCAN_SKILL_RELATIVE_PATH),
|
|
143
122
|
];
|
|
144
123
|
export const LOCAL_PATH_HINTS_RELATIVE_PATH = ".gdh-state/local-paths.json";
|
|
145
124
|
export const CODEX_PROJECT_CONFIG_RELATIVE_PATH = ".codex/config.toml";
|
|
@@ -159,17 +138,16 @@ export async function getSupportedAgentAdaptersStatus(targetPath, options = {})
|
|
|
159
138
|
integrationRootPath: context.integrationRootPath,
|
|
160
139
|
pinnedVersion,
|
|
161
140
|
});
|
|
162
|
-
const [codex, claude
|
|
141
|
+
const [codex, claude] = await Promise.all([
|
|
163
142
|
inspectCodexAdapter(context.targetPath, guidance, projectMcp, pinnedVersion, {
|
|
164
143
|
includeUserLocal,
|
|
165
144
|
}),
|
|
166
145
|
inspectClaudeAdapter(context.targetPath, guidance, projectMcp, pinnedVersion),
|
|
167
|
-
inspectCursorAdapter(context.targetPath, guidance, projectMcp, pinnedVersion),
|
|
168
146
|
]);
|
|
169
147
|
return {
|
|
170
148
|
targetPath: context.targetPath,
|
|
171
149
|
guidance,
|
|
172
|
-
adapters: [codex, claude
|
|
150
|
+
adapters: [codex, claude],
|
|
173
151
|
};
|
|
174
152
|
}
|
|
175
153
|
export async function installSupportedAgentAdapters(targetPath, options = {}) {
|
|
@@ -297,7 +275,6 @@ export async function inspectProjectLifecycleCompatibility(targetPath) {
|
|
|
297
275
|
await inspectGuidanceIndexLifecycleSurface(guidanceStatus.guidanceRootPath, resolvedTargetPath),
|
|
298
276
|
await inspectGuidanceUnitLifecycleSurface(guidanceStatus.guidanceRootPath, projectConfig, resolvedTargetPath),
|
|
299
277
|
inspectMcpManifestLifecycleSurface(resolvedTargetPath, projectConfig.mcp.enabled, adapterStatus),
|
|
300
|
-
inspectCursorRuleLifecycleSurface(resolvedTargetPath, adapterStatus),
|
|
301
278
|
inspectRuntimeBridgeLifecycleSurface(resolvedTargetPath, bridgeStatus),
|
|
302
279
|
]);
|
|
303
280
|
}
|
|
@@ -408,26 +385,6 @@ function normalizePortableRelativePath(relativePath) {
|
|
|
408
385
|
const normalized = relativePath.split(path.sep).join("/");
|
|
409
386
|
return normalized === "" ? "." : normalized.replace(/\/+$/, "");
|
|
410
387
|
}
|
|
411
|
-
export function renderCursorRule(input) {
|
|
412
|
-
const targetPrefix = input?.targetRelativePath
|
|
413
|
-
? normalizePortableRelativePath(input.targetRelativePath)
|
|
414
|
-
: ".";
|
|
415
|
-
const prefixed = (relativePath) => targetPrefix === "." ? relativePath : `${targetPrefix}/${relativePath}`;
|
|
416
|
-
return [
|
|
417
|
-
"---",
|
|
418
|
-
"description: GDH visibility reinforcement",
|
|
419
|
-
"alwaysApply: true",
|
|
420
|
-
"---",
|
|
421
|
-
`<!-- GDH CURSOR RULE VERSION: ${GDH_CURSOR_RULE_VERSION} -->`,
|
|
422
|
-
"# GDH Cursor Rule",
|
|
423
|
-
"",
|
|
424
|
-
"This GDH-managed Godot target uses GDH.",
|
|
425
|
-
"Apply this rule only for files inside this Godot target or when the user explicitly asks for GDH work on this target.",
|
|
426
|
-
`Follow the canonical target-local entrypoint in [AGENTS.md](../../${prefixed("AGENTS.md")}), then load the canonical guidance index at [.gdh/guidance/README.md](../../${prefixed(".gdh/guidance/README.md")}) before substantive Godot work.`,
|
|
427
|
-
"Do not duplicate or override the canonical GDH guidance chain here.",
|
|
428
|
-
"",
|
|
429
|
-
].join("\n");
|
|
430
|
-
}
|
|
431
388
|
export function renderClaudeOnboardCommand(pinnedVersion) {
|
|
432
389
|
return renderClaudeOnboardSkill(pinnedVersion);
|
|
433
390
|
}
|
|
@@ -456,15 +413,11 @@ async function inspectProjectMcpSupport(targetPath, options) {
|
|
|
456
413
|
pinnedVersion: options.pinnedVersion ?? "latest",
|
|
457
414
|
});
|
|
458
415
|
const nestedTarget = path.resolve(targetPath) !== path.resolve(options.integrationRootPath);
|
|
459
|
-
const [projectFile,
|
|
416
|
+
const [projectFile, targetProjectFile, codexProjectContent, localPathHints,] = await Promise.all([
|
|
460
417
|
inspectJsonFile(path.join(options.integrationRootPath, PROJECT_MCP_RELATIVE_PATH)),
|
|
461
|
-
inspectJsonFile(path.join(options.integrationRootPath, CURSOR_MCP_RELATIVE_PATH)),
|
|
462
418
|
nestedTarget
|
|
463
419
|
? inspectJsonFile(path.join(targetPath, PROJECT_MCP_RELATIVE_PATH))
|
|
464
420
|
: inspectJsonFile(path.join(options.integrationRootPath, PROJECT_MCP_RELATIVE_PATH)),
|
|
465
|
-
nestedTarget
|
|
466
|
-
? inspectJsonFile(path.join(targetPath, CURSOR_MCP_RELATIVE_PATH))
|
|
467
|
-
: inspectJsonFile(path.join(options.integrationRootPath, CURSOR_MCP_RELATIVE_PATH)),
|
|
468
421
|
fs
|
|
469
422
|
.readFile(path.join(options.integrationRootPath, CODEX_PROJECT_CONFIG_RELATIVE_PATH), "utf8")
|
|
470
423
|
.catch(() => null),
|
|
@@ -477,9 +430,7 @@ async function inspectProjectMcpSupport(targetPath, options) {
|
|
|
477
430
|
integrationRootPath: options.integrationRootPath,
|
|
478
431
|
localPathHints,
|
|
479
432
|
projectFile: inspectManagedMcpFile(projectFile, enabled, PROJECT_MCP_RELATIVE_PATH, "Claude project MCP config", managedMcpEntry),
|
|
480
|
-
cursorFile: inspectManagedMcpFile(cursorFile, enabled, CURSOR_MCP_RELATIVE_PATH, "Cursor project MCP config", managedMcpEntry),
|
|
481
433
|
targetProjectFile: inspectManagedMcpFile(targetProjectFile, enabled, PROJECT_MCP_RELATIVE_PATH, "target-local Claude project MCP config", managedMcpEntry),
|
|
482
|
-
targetCursorFile: inspectManagedMcpFile(targetCursorFile, enabled, CURSOR_MCP_RELATIVE_PATH, "target-local Cursor project MCP config", managedMcpEntry),
|
|
483
434
|
codexProjectFile: inspectManagedCodexProjectFile(codexProjectContent, enabled, options.pinnedVersion),
|
|
484
435
|
codexRegistration: options.includeUserLocal
|
|
485
436
|
? await inspectCodexRegistration(targetPath, enabled, codexServerName, codexConfigPath, options.integrationRootPath, options.pinnedVersion)
|
|
@@ -776,38 +727,6 @@ function inspectClaudeSkillSurface(targetPath, relativePath, content, expectedCo
|
|
|
776
727
|
}),
|
|
777
728
|
];
|
|
778
729
|
}
|
|
779
|
-
function inspectCursorCommandSurface(targetPath, relativePath, content, expectedContent, commandName) {
|
|
780
|
-
if (expectedContent === null) {
|
|
781
|
-
return [
|
|
782
|
-
createSurfaceStatus({
|
|
783
|
-
kind: "command_file",
|
|
784
|
-
scope: "repo",
|
|
785
|
-
targetPath,
|
|
786
|
-
relativePath,
|
|
787
|
-
present: content !== null,
|
|
788
|
-
state: "missing",
|
|
789
|
-
summary: `Cursor ${commandName} command cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
790
|
-
version: null,
|
|
791
|
-
}),
|
|
792
|
-
];
|
|
793
|
-
}
|
|
794
|
-
return [
|
|
795
|
-
createSurfaceStatus({
|
|
796
|
-
kind: "command_file",
|
|
797
|
-
scope: "repo",
|
|
798
|
-
targetPath,
|
|
799
|
-
relativePath,
|
|
800
|
-
present: content !== null,
|
|
801
|
-
state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
|
|
802
|
-
summary: content === null
|
|
803
|
-
? `Cursor \`/${commandName}\` command is missing and should install under .cursor/commands/.`
|
|
804
|
-
: content === expectedContent
|
|
805
|
-
? `Cursor can discover the managed \`/${commandName}\` command.`
|
|
806
|
-
: `Cursor \`/${commandName}\` command exists but no longer matches the expected managed GDH command.`,
|
|
807
|
-
version: null,
|
|
808
|
-
}),
|
|
809
|
-
];
|
|
810
|
-
}
|
|
811
730
|
async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, options) {
|
|
812
731
|
const codexSkillPath = path.join(targetPath, CODEX_ONBOARD_SKILL_RELATIVE_PATH);
|
|
813
732
|
const codexSkillContent = await fs.readFile(codexSkillPath, "utf8").catch(() => null);
|
|
@@ -1049,6 +968,15 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1049
968
|
inspectManagedHookSurface("claude", targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH, claudeStatuslineContent, expectedClaudeStatusline, "gdh-statusline"),
|
|
1050
969
|
inspectManagedHookSurface("claude", targetPath, CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, claudeAuthoringHookContent, expectedClaudeAuthoringHook, "authoring guard"),
|
|
1051
970
|
];
|
|
971
|
+
if (path.resolve(projectMcp.integrationRootPath) !== path.resolve(targetPath)) {
|
|
972
|
+
surfaces.push(...(await inspectRootSymlinkSurfaces({
|
|
973
|
+
agent: "claude",
|
|
974
|
+
integrationRootPath: projectMcp.integrationRootPath,
|
|
975
|
+
targetPath,
|
|
976
|
+
relativePaths: CLAUDE_SKILL_RELATIVE_PATHS,
|
|
977
|
+
noun: "Claude skill",
|
|
978
|
+
})));
|
|
979
|
+
}
|
|
1052
980
|
if (projectMcp.enabled) {
|
|
1053
981
|
surfaces.push(createSurfaceStatus({
|
|
1054
982
|
kind: "mcp_file",
|
|
@@ -1077,111 +1005,34 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1077
1005
|
}
|
|
1078
1006
|
return createAgentStatus("claude", guidance, surfaces);
|
|
1079
1007
|
}
|
|
1080
|
-
async function
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
.
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
// the planner returns `unchanged` for a missing file and install becomes a
|
|
1094
|
-
// no-op (Plan 13-05 integration-test Rule 2 fix).
|
|
1095
|
-
const cursorUpdateContent = await fs
|
|
1096
|
-
.readFile(path.join(targetPath, CURSOR_UPDATE_COMMAND_RELATIVE_PATH), "utf8")
|
|
1097
|
-
.catch(() => null);
|
|
1098
|
-
const cursorPrepareContent = await fs
|
|
1099
|
-
.readFile(path.join(targetPath, CURSOR_PREPARE_COMMAND_RELATIVE_PATH), "utf8")
|
|
1100
|
-
.catch(() => null);
|
|
1101
|
-
const cursorRunGameContent = await fs
|
|
1102
|
-
.readFile(path.resolve(targetPath, CURSOR_RUN_GAME_COMMAND_RELATIVE_PATH), "utf8")
|
|
1103
|
-
.catch(() => null);
|
|
1104
|
-
const cursorScanContent = await fs
|
|
1105
|
-
.readFile(path.join(targetPath, CURSOR_SCAN_COMMAND_RELATIVE_PATH), "utf8")
|
|
1106
|
-
.catch(() => null);
|
|
1107
|
-
const expectedContent = renderCursorRule();
|
|
1108
|
-
const version = readCursorRuleVersion(content);
|
|
1109
|
-
const expectedCursorOnboardSkill = pinnedVersion === null ? null : renderCursorOnboardSkill(pinnedVersion);
|
|
1110
|
-
const expectedCursorStatusSkill = pinnedVersion === null ? null : renderCursorStatusSkill(pinnedVersion);
|
|
1111
|
-
const expectedCursorMigrateSkill = pinnedVersion === null ? null : renderCursorMigrateSkill(pinnedVersion);
|
|
1112
|
-
const expectedCursorUpdateSkill = pinnedVersion === null ? null : renderCursorUpdateSkill(pinnedVersion);
|
|
1113
|
-
const expectedCursorPrepareSkill = pinnedVersion === null ? null : renderCursorPrepareSkill(pinnedVersion);
|
|
1114
|
-
const expectedCursorRunGameSkill = pinnedVersion === null ? null : renderCursorRunGameSkill(pinnedVersion);
|
|
1115
|
-
const expectedCursorScanSkill = pinnedVersion === null ? null : renderCursorScanSkill(pinnedVersion);
|
|
1116
|
-
const surfaces = [
|
|
1117
|
-
createSurfaceStatus({
|
|
1118
|
-
kind: "rule_file",
|
|
1119
|
-
scope: "repo",
|
|
1120
|
-
targetPath,
|
|
1121
|
-
relativePath: CURSOR_RULE_RELATIVE_PATH,
|
|
1122
|
-
present: content !== null,
|
|
1123
|
-
state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
|
|
1124
|
-
summary: content === null
|
|
1125
|
-
? "Cursor reinforcement is missing and should point back to AGENTS.md."
|
|
1126
|
-
: content === expectedContent
|
|
1127
|
-
? "Cursor has a thin always-on rule that points back to the canonical GDH guidance chain."
|
|
1128
|
-
: "Cursor reinforcement exists but no longer matches the expected managed GDH rule.",
|
|
1129
|
-
version,
|
|
1130
|
-
}),
|
|
1131
|
-
createSurfaceStatus({
|
|
1132
|
-
kind: "command_file",
|
|
1133
|
-
scope: "repo",
|
|
1134
|
-
targetPath,
|
|
1135
|
-
relativePath: CURSOR_ONBOARD_COMMAND_RELATIVE_PATH,
|
|
1136
|
-
present: onboardCommandContent !== null,
|
|
1137
|
-
state: onboardCommandContent === null
|
|
1138
|
-
? "missing"
|
|
1139
|
-
: expectedCursorOnboardSkill === null
|
|
1140
|
-
? "missing"
|
|
1141
|
-
: onboardCommandContent === expectedCursorOnboardSkill
|
|
1142
|
-
? "ready"
|
|
1143
|
-
: "misconfigured",
|
|
1144
|
-
summary: onboardCommandContent === null
|
|
1145
|
-
? "Cursor onboarding handoff is missing and should install `/gdh-onboard` under .cursor/commands/."
|
|
1146
|
-
: expectedCursorOnboardSkill === null
|
|
1147
|
-
? "Cursor onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1148
|
-
: onboardCommandContent === expectedCursorOnboardSkill
|
|
1149
|
-
? "Cursor can discover the managed `/gdh-onboard` handoff command."
|
|
1150
|
-
: "Cursor onboarding handoff exists but no longer matches the expected managed GDH command.",
|
|
1151
|
-
version: null,
|
|
1152
|
-
}),
|
|
1153
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_STATUS_COMMAND_RELATIVE_PATH, cursorStatusContent, expectedCursorStatusSkill, "gdh-status"),
|
|
1154
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_MIGRATE_COMMAND_RELATIVE_PATH, cursorMigrateContent, expectedCursorMigrateSkill, "gdh-migrate"),
|
|
1155
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_UPDATE_COMMAND_RELATIVE_PATH, cursorUpdateContent, expectedCursorUpdateSkill, "gdh-update"),
|
|
1156
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_PREPARE_COMMAND_RELATIVE_PATH, cursorPrepareContent, expectedCursorPrepareSkill, "gdh-prepare"),
|
|
1157
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_RUN_GAME_COMMAND_RELATIVE_PATH, cursorRunGameContent, expectedCursorRunGameSkill, "gdh-run-game"),
|
|
1158
|
-
...inspectCursorCommandSurface(targetPath, CURSOR_SCAN_COMMAND_RELATIVE_PATH, cursorScanContent, expectedCursorScanSkill, "gdh-scan"),
|
|
1159
|
-
];
|
|
1160
|
-
if (projectMcp.enabled) {
|
|
1161
|
-
surfaces.push(createSurfaceStatus({
|
|
1162
|
-
kind: "mcp_file",
|
|
1008
|
+
async function inspectRootSymlinkSurfaces(input) {
|
|
1009
|
+
return Promise.all(input.relativePaths.map(async (relativePath) => {
|
|
1010
|
+
const absolutePath = path.join(input.integrationRootPath, relativePath);
|
|
1011
|
+
const rootLinkDirectory = path.dirname(absolutePath);
|
|
1012
|
+
const targetFilePath = path.join(input.targetPath, relativePath);
|
|
1013
|
+
const expectedTarget = normalizePortableRelativePath(path.relative(rootLinkDirectory, targetFilePath));
|
|
1014
|
+
const stat = await fs.lstat(absolutePath).catch(() => null);
|
|
1015
|
+
const detectedTarget = stat?.isSymbolicLink()
|
|
1016
|
+
? await fs.readlink(absolutePath).catch(() => null)
|
|
1017
|
+
: null;
|
|
1018
|
+
const ready = stat?.isSymbolicLink() === true && detectedTarget === expectedTarget;
|
|
1019
|
+
return createSurfaceStatus({
|
|
1020
|
+
kind: "symlink",
|
|
1163
1021
|
scope: "repo",
|
|
1164
|
-
targetPath:
|
|
1165
|
-
relativePath
|
|
1166
|
-
present:
|
|
1167
|
-
state:
|
|
1168
|
-
summary:
|
|
1022
|
+
targetPath: input.integrationRootPath,
|
|
1023
|
+
relativePath,
|
|
1024
|
+
present: stat !== null,
|
|
1025
|
+
state: stat === null ? "missing" : ready ? "ready" : "misconfigured",
|
|
1026
|
+
summary: stat === null
|
|
1027
|
+
? `Root-launched ${input.noun} ${relativePath} is missing and should point to the target-local managed surface.`
|
|
1028
|
+
: ready
|
|
1029
|
+
? `Root-launched ${input.noun} ${relativePath} points to the target-local managed surface.`
|
|
1030
|
+
: `Root-launched ${input.noun} ${relativePath} does not point to the target-local managed surface.`,
|
|
1169
1031
|
version: null,
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
scope: "repo",
|
|
1175
|
-
targetPath,
|
|
1176
|
-
relativePath: CURSOR_MCP_RELATIVE_PATH,
|
|
1177
|
-
present: projectMcp.targetCursorFile.present,
|
|
1178
|
-
state: projectMcp.targetCursorFile.state,
|
|
1179
|
-
summary: projectMcp.targetCursorFile.summary,
|
|
1180
|
-
version: null,
|
|
1181
|
-
}));
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
return createAgentStatus("cursor", guidance, surfaces);
|
|
1032
|
+
expectedTarget,
|
|
1033
|
+
detectedTarget,
|
|
1034
|
+
});
|
|
1035
|
+
}));
|
|
1185
1036
|
}
|
|
1186
1037
|
function createAgentStatus(agent, guidance, surfaces) {
|
|
1187
1038
|
const state = !hasReadyVisibilityChain(guidance)
|
|
@@ -1294,17 +1145,12 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
1294
1145
|
}
|
|
1295
1146
|
if (adapter.agent === "claude") {
|
|
1296
1147
|
actions.push(...planClaudeInstallActions(targetPath, adapter, options.pinnedVersion, options.integrationRootPath));
|
|
1297
|
-
continue;
|
|
1298
|
-
}
|
|
1299
|
-
if (adapter.agent === "cursor") {
|
|
1300
|
-
actions.push(...planCursorInstallActions(targetPath, adapter, options.pinnedVersion, options.integrationRootPath));
|
|
1301
1148
|
}
|
|
1302
1149
|
}
|
|
1303
1150
|
actions.push(...planRetiredManagedSurfaceCleanupActions(targetPath));
|
|
1304
1151
|
if (path.resolve(options.integrationRootPath) !== path.resolve(targetPath)) {
|
|
1305
1152
|
actions.push(...planRetiredManagedSurfaceCleanupActions(options.integrationRootPath));
|
|
1306
1153
|
actions.push(...planLegacyCodexSkillCleanupActions(options.integrationRootPath, options.pinnedVersion));
|
|
1307
|
-
actions.push(...planLegacyCursorSkillCleanupActions(options.integrationRootPath));
|
|
1308
1154
|
}
|
|
1309
1155
|
return dedupeInstallActions(actions);
|
|
1310
1156
|
}
|
|
@@ -1330,21 +1176,6 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1330
1176
|
content: renderManagedMcpConfig(path.join(integrationRootPath, PROJECT_MCP_RELATIVE_PATH), managedMcpEntry),
|
|
1331
1177
|
}));
|
|
1332
1178
|
}
|
|
1333
|
-
if (projectMcp.cursorFile.state !== "ready") {
|
|
1334
|
-
actions.push(createInstallAction({
|
|
1335
|
-
agent,
|
|
1336
|
-
kind: "write_file",
|
|
1337
|
-
scope: "repo",
|
|
1338
|
-
targetPath: integrationRootPath,
|
|
1339
|
-
relativePath: CURSOR_MCP_RELATIVE_PATH,
|
|
1340
|
-
state: "planned",
|
|
1341
|
-
mode: projectMcp.cursorFile.present ? "replace" : "create",
|
|
1342
|
-
summary: projectMcp.cursorFile.present
|
|
1343
|
-
? "Replace the managed `gdh` MCP entry in .cursor/mcp.json while preserving any non-GDH servers."
|
|
1344
|
-
: "Create .cursor/mcp.json with the managed `gdh` MCP entry.",
|
|
1345
|
-
content: renderManagedMcpConfig(path.join(integrationRootPath, CURSOR_MCP_RELATIVE_PATH), managedMcpEntry),
|
|
1346
|
-
}));
|
|
1347
|
-
}
|
|
1348
1179
|
if (nestedTarget && projectMcp.targetProjectFile.state !== "ready") {
|
|
1349
1180
|
actions.push(createInstallAction({
|
|
1350
1181
|
agent,
|
|
@@ -1360,21 +1191,6 @@ function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDe
|
|
|
1360
1191
|
content: renderManagedMcpConfig(path.join(targetPath, PROJECT_MCP_RELATIVE_PATH), managedMcpEntry),
|
|
1361
1192
|
}));
|
|
1362
1193
|
}
|
|
1363
|
-
if (nestedTarget && projectMcp.targetCursorFile.state !== "ready") {
|
|
1364
|
-
actions.push(createInstallAction({
|
|
1365
|
-
agent,
|
|
1366
|
-
kind: "write_file",
|
|
1367
|
-
scope: "repo",
|
|
1368
|
-
targetPath,
|
|
1369
|
-
relativePath: CURSOR_MCP_RELATIVE_PATH,
|
|
1370
|
-
state: "planned",
|
|
1371
|
-
mode: projectMcp.targetCursorFile.present ? "replace" : "create",
|
|
1372
|
-
summary: projectMcp.targetCursorFile.present
|
|
1373
|
-
? "Replace the managed `gdh` MCP entry in target-local .cursor/mcp.json while preserving any non-GDH servers."
|
|
1374
|
-
: "Create target-local .cursor/mcp.json so Cursor can discover GDH when opened at the Godot target.",
|
|
1375
|
-
content: renderManagedMcpConfig(path.join(targetPath, CURSOR_MCP_RELATIVE_PATH), managedMcpEntry),
|
|
1376
|
-
}));
|
|
1377
|
-
}
|
|
1378
1194
|
if (projectMcp.localPathHints.gdhDevRepoPath !== effectiveDevRepoPath) {
|
|
1379
1195
|
actions.push(createInstallAction({
|
|
1380
1196
|
agent,
|
|
@@ -1511,8 +1327,6 @@ function agentLabel(agent) {
|
|
|
1511
1327
|
return "Claude";
|
|
1512
1328
|
case "codex":
|
|
1513
1329
|
return "Codex";
|
|
1514
|
-
case "cursor":
|
|
1515
|
-
return "Cursor";
|
|
1516
1330
|
}
|
|
1517
1331
|
}
|
|
1518
1332
|
function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion, projectMcp, integrationRootPath) {
|
|
@@ -1569,20 +1383,14 @@ function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion, project
|
|
|
1569
1383
|
// accepts both so old managed files can migrate without deleting user-authored
|
|
1570
1384
|
// files based only on path.
|
|
1571
1385
|
const LEGACY_CODEX_MANAGED_SKILL_MARKER = "<codex_skill_adapter>";
|
|
1572
|
-
const LEGACY_CURSOR_MANAGED_SKILL_MARKER = "<cursor_skill_adapter>";
|
|
1573
1386
|
function isManagedAgentSkillContent(content) {
|
|
1574
1387
|
return (content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1575
|
-
content.includes(LEGACY_CODEX_MANAGED_SKILL_MARKER)
|
|
1576
|
-
content.includes(LEGACY_CURSOR_MANAGED_SKILL_MARKER));
|
|
1388
|
+
content.includes(LEGACY_CODEX_MANAGED_SKILL_MARKER));
|
|
1577
1389
|
}
|
|
1578
1390
|
function isManagedLegacyCodexSkillContent(content) {
|
|
1579
1391
|
return (content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1580
1392
|
content.includes(LEGACY_CODEX_MANAGED_SKILL_MARKER));
|
|
1581
1393
|
}
|
|
1582
|
-
function isManagedLegacyCursorSkillContent(content) {
|
|
1583
|
-
return (content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1584
|
-
content.includes(LEGACY_CURSOR_MANAGED_SKILL_MARKER));
|
|
1585
|
-
}
|
|
1586
1394
|
function isManagedLegacyClaudeCommandContent(content, skillName) {
|
|
1587
1395
|
const slashName = skillName.replace("gdh-", "gdh:");
|
|
1588
1396
|
return (content.includes(`name: ${slashName}`) &&
|
|
@@ -1609,13 +1417,6 @@ const RETIRED_MANAGED_SURFACE_RELATIVE_PATHS = [
|
|
|
1609
1417
|
isManaged: isManagedAgentSkillContent,
|
|
1610
1418
|
replacementSummary: "Agents should rely on GDH post-edit hooks, MCP/CLI status, and explicit `gdh authoring check --mode final` evidence instead.",
|
|
1611
1419
|
},
|
|
1612
|
-
{
|
|
1613
|
-
agent: "cursor",
|
|
1614
|
-
relativePath: ".cursor/skills/gdh-check/SKILL.md",
|
|
1615
|
-
skillName: "gdh-check",
|
|
1616
|
-
isManaged: isManagedAgentSkillContent,
|
|
1617
|
-
replacementSummary: "Agents should rely on MCP/CLI status and explicit `gdh authoring check --mode final` evidence instead.",
|
|
1618
|
-
},
|
|
1619
1420
|
{
|
|
1620
1421
|
agent: "claude",
|
|
1621
1422
|
relativePath: ".claude/skills/gdh-check/SKILL.md",
|
|
@@ -1630,13 +1431,6 @@ const RETIRED_MANAGED_SURFACE_RELATIVE_PATHS = [
|
|
|
1630
1431
|
isManaged: isManagedAgentSkillContent,
|
|
1631
1432
|
replacementSummary: "Agents should use `gdh authoring check --mode final` for code-validity evidence.",
|
|
1632
1433
|
},
|
|
1633
|
-
{
|
|
1634
|
-
agent: "cursor",
|
|
1635
|
-
relativePath: ".cursor/skills/gdh-verify/SKILL.md",
|
|
1636
|
-
skillName: "gdh-verify",
|
|
1637
|
-
isManaged: isManagedAgentSkillContent,
|
|
1638
|
-
replacementSummary: "Agents should use `gdh authoring check --mode final` for code-validity evidence.",
|
|
1639
|
-
},
|
|
1640
1434
|
{
|
|
1641
1435
|
agent: "claude",
|
|
1642
1436
|
relativePath: ".claude/commands/gdh/verify.md",
|
|
@@ -1645,6 +1439,59 @@ const RETIRED_MANAGED_SURFACE_RELATIVE_PATHS = [
|
|
|
1645
1439
|
(content.includes("@skillcap/gdh@") || content.includes("gdh verify recommend")),
|
|
1646
1440
|
replacementSummary: "Agents should use `gdh authoring check --mode final` for code-validity evidence.",
|
|
1647
1441
|
},
|
|
1442
|
+
// Retired cursor agent (commit 7f65b098, "feat(adapters)!: drop cursor
|
|
1443
|
+
// agent from source"). Cursor was a hard delete — no deprecation shim — so
|
|
1444
|
+
// legacy targets that ran a pre-removal GDH still carry GDH-rendered files
|
|
1445
|
+
// under .cursor/. The inventory sweep handles targets with a prior
|
|
1446
|
+
// render-inventory.json; these entries cover the legacy-target case where
|
|
1447
|
+
// no inventory exists yet (pre-Phase 70 onboarding). Content-checked so
|
|
1448
|
+
// user-authored .cursor/ files are never touched. The `agent` field is
|
|
1449
|
+
// attribution-only — cursor is no longer in GdhSupportedAgent — and is set
|
|
1450
|
+
// to "claude" because cursor commands/skills were Claude-style markdown
|
|
1451
|
+
// surfaces. .cursor/mcp.json is intentionally NOT enumerated here: it is a
|
|
1452
|
+
// JSON file that may carry non-GDH MCP servers; deleting it whole would
|
|
1453
|
+
// nuke user content. (The stale `gdh` entry inside it is harmless — the
|
|
1454
|
+
// command it points at is dead — and a JSON-aware partial delete is a
|
|
1455
|
+
// separate concern.)
|
|
1456
|
+
...([
|
|
1457
|
+
"gdh-onboard",
|
|
1458
|
+
"gdh-status",
|
|
1459
|
+
"gdh-migrate",
|
|
1460
|
+
"gdh-update",
|
|
1461
|
+
"gdh-prepare",
|
|
1462
|
+
"gdh-run-game",
|
|
1463
|
+
"gdh-scan",
|
|
1464
|
+
].map((skillName) => ({
|
|
1465
|
+
agent: "claude",
|
|
1466
|
+
relativePath: `.cursor/commands/${skillName}.md`,
|
|
1467
|
+
skillName,
|
|
1468
|
+
isManaged: isManagedAgentSkillContent,
|
|
1469
|
+
replacementSummary: "Cursor is no longer a supported GDH adapter target; this file was rendered by a pre-removal GDH version.",
|
|
1470
|
+
}))),
|
|
1471
|
+
...([
|
|
1472
|
+
"gdh-onboard",
|
|
1473
|
+
"gdh-status",
|
|
1474
|
+
"gdh-migrate",
|
|
1475
|
+
"gdh-update",
|
|
1476
|
+
"gdh-check",
|
|
1477
|
+
"gdh-prepare",
|
|
1478
|
+
"gdh-run-game",
|
|
1479
|
+
"gdh-verify",
|
|
1480
|
+
"gdh-scan",
|
|
1481
|
+
].map((skillName) => ({
|
|
1482
|
+
agent: "claude",
|
|
1483
|
+
relativePath: `.cursor/skills/${skillName}/SKILL.md`,
|
|
1484
|
+
skillName,
|
|
1485
|
+
isManaged: isManagedAgentSkillContent,
|
|
1486
|
+
replacementSummary: "Cursor is no longer a supported GDH adapter target; this file was rendered by a pre-removal GDH version.",
|
|
1487
|
+
}))),
|
|
1488
|
+
{
|
|
1489
|
+
agent: "claude",
|
|
1490
|
+
relativePath: ".cursor/rules/gdh-agent.mdc",
|
|
1491
|
+
skillName: "gdh-agent-rule",
|
|
1492
|
+
isManaged: (content) => content.includes("GDH CURSOR RULE VERSION:"),
|
|
1493
|
+
replacementSummary: "Cursor is no longer a supported GDH adapter target; this rule file was rendered by a pre-removal GDH version.",
|
|
1494
|
+
},
|
|
1648
1495
|
];
|
|
1649
1496
|
function planRetiredManagedSurfaceCleanupActions(targetPath) {
|
|
1650
1497
|
const actions = [];
|
|
@@ -1667,7 +1514,6 @@ function planRetiredManagedSurfaceCleanupActions(targetPath) {
|
|
|
1667
1514
|
summary: `Remove retired managed \`${entry.skillName}\` surface. ${entry.replacementSummary}`,
|
|
1668
1515
|
}));
|
|
1669
1516
|
}
|
|
1670
|
-
actions.push(...planLegacyCursorSkillCleanupActions(targetPath));
|
|
1671
1517
|
return actions;
|
|
1672
1518
|
}
|
|
1673
1519
|
function planLegacyCodexSkillCleanupActions(targetPath, _pinnedVersion) {
|
|
@@ -1699,29 +1545,6 @@ function planLegacyCodexSkillCleanupActions(targetPath, _pinnedVersion) {
|
|
|
1699
1545
|
}
|
|
1700
1546
|
return actions;
|
|
1701
1547
|
}
|
|
1702
|
-
function planLegacyCursorSkillCleanupActions(targetPath) {
|
|
1703
|
-
const actions = [];
|
|
1704
|
-
for (const [relativePath, skillName] of LEGACY_CURSOR_SKILL_RELATIVE_PATHS) {
|
|
1705
|
-
const absolutePath = path.join(targetPath, relativePath);
|
|
1706
|
-
const content = fsSync.existsSync(absolutePath)
|
|
1707
|
-
? fsSync.readFileSync(absolutePath, "utf8")
|
|
1708
|
-
: null;
|
|
1709
|
-
if (content === null || !isManagedLegacyCursorSkillContent(content)) {
|
|
1710
|
-
continue;
|
|
1711
|
-
}
|
|
1712
|
-
actions.push(createInstallAction({
|
|
1713
|
-
agent: "cursor",
|
|
1714
|
-
kind: "remove_file",
|
|
1715
|
-
scope: "repo",
|
|
1716
|
-
targetPath,
|
|
1717
|
-
relativePath,
|
|
1718
|
-
state: "planned",
|
|
1719
|
-
mode: "delete",
|
|
1720
|
-
summary: `Remove legacy managed Cursor \`/${skillName}\` skill from .cursor/skills after installing the documented .cursor/commands location.`,
|
|
1721
|
-
}));
|
|
1722
|
-
}
|
|
1723
|
-
return actions;
|
|
1724
|
-
}
|
|
1725
1548
|
function planLegacyClaudeCommandCleanupActions(targetPath) {
|
|
1726
1549
|
const actions = [];
|
|
1727
1550
|
for (const [relativePath, skillName] of LEGACY_CLAUDE_SKILL_COMMAND_RELATIVE_PATHS) {
|
|
@@ -1870,7 +1693,13 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion, integratio
|
|
|
1870
1693
|
readySummary: "Root-launched Claude authoring hook already matches the managed target-scoped hook.",
|
|
1871
1694
|
createSummary: "Create the root-launched Claude authoring hook with target-scoped filtering.",
|
|
1872
1695
|
replaceSummary: "Replace the root-launched Claude authoring hook with the target-scoped managed hook.",
|
|
1873
|
-
}), planRootClaudeAuthoringSettingsAction(integrationRootPath)
|
|
1696
|
+
}), planRootClaudeAuthoringSettingsAction(integrationRootPath), ...planRootSymlinkActions({
|
|
1697
|
+
agent: "claude",
|
|
1698
|
+
integrationRootPath,
|
|
1699
|
+
targetPath,
|
|
1700
|
+
relativePaths: CLAUDE_SKILL_RELATIVE_PATHS,
|
|
1701
|
+
noun: "Claude skill",
|
|
1702
|
+
}));
|
|
1874
1703
|
}
|
|
1875
1704
|
// .claude/settings.json composite patch action.
|
|
1876
1705
|
// - Plan 02 (Strategy A, planner-lock #1): patch-merge the SessionStart
|
|
@@ -1883,7 +1712,7 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion, integratio
|
|
|
1883
1712
|
//
|
|
1884
1713
|
// Synchronous read via fsSync is intentional: planClaudeInstallActions is
|
|
1885
1714
|
// called without `await`, and making it async would ripple to every sibling
|
|
1886
|
-
// planner (Codex
|
|
1715
|
+
// planner (Codex). The composed patches are idempotent and
|
|
1887
1716
|
// commutative (proven in Task 1 Test J) so application order is irrelevant.
|
|
1888
1717
|
let existingSettingsContent = "";
|
|
1889
1718
|
try {
|
|
@@ -2006,60 +1835,6 @@ function planRootClaudeAuthoringSettingsAction(integrationRootPath) {
|
|
|
2006
1835
|
content: patchedSettings,
|
|
2007
1836
|
});
|
|
2008
1837
|
}
|
|
2009
|
-
function planCursorInstallActions(targetPath, adapter, pinnedVersion, integrationRootPath) {
|
|
2010
|
-
const actions = [];
|
|
2011
|
-
const cursorRuleSurface = adapter.surfaces.find((surface) => surface.relativePath === CURSOR_RULE_RELATIVE_PATH);
|
|
2012
|
-
const targetRelativePath = path.relative(integrationRootPath, targetPath) || ".";
|
|
2013
|
-
if (!cursorRuleSurface || cursorRuleSurface.state === "ready") {
|
|
2014
|
-
actions.push(createInstallAction({
|
|
2015
|
-
agent: "cursor",
|
|
2016
|
-
kind: "write_file",
|
|
2017
|
-
scope: "repo",
|
|
2018
|
-
targetPath,
|
|
2019
|
-
relativePath: CURSOR_RULE_RELATIVE_PATH,
|
|
2020
|
-
state: "unchanged",
|
|
2021
|
-
mode: "unchanged",
|
|
2022
|
-
summary: "The managed Cursor reinforcement rule already matches the expected GDH content.",
|
|
2023
|
-
version: GDH_CURSOR_RULE_VERSION,
|
|
2024
|
-
content: renderCursorRule(),
|
|
2025
|
-
}));
|
|
2026
|
-
}
|
|
2027
|
-
else {
|
|
2028
|
-
actions.push(createInstallAction({
|
|
2029
|
-
agent: "cursor",
|
|
2030
|
-
kind: "write_file",
|
|
2031
|
-
scope: "repo",
|
|
2032
|
-
targetPath,
|
|
2033
|
-
relativePath: CURSOR_RULE_RELATIVE_PATH,
|
|
2034
|
-
state: "planned",
|
|
2035
|
-
mode: cursorRuleSurface.present ? "replace" : "create",
|
|
2036
|
-
summary: cursorRuleSurface.present
|
|
2037
|
-
? "Replace the existing Cursor reinforcement rule with the managed GDH rule."
|
|
2038
|
-
: "Create the managed Cursor reinforcement rule that points back to AGENTS.md.",
|
|
2039
|
-
version: GDH_CURSOR_RULE_VERSION,
|
|
2040
|
-
content: renderCursorRule(),
|
|
2041
|
-
}));
|
|
2042
|
-
}
|
|
2043
|
-
actions.push(planCommandInstallAction("cursor", targetPath, adapter, CURSOR_ONBOARD_COMMAND_RELATIVE_PATH, renderCursorOnboardSkill, "gdh-onboard", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_STATUS_COMMAND_RELATIVE_PATH, renderCursorStatusSkill, "gdh-status", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_MIGRATE_COMMAND_RELATIVE_PATH, renderCursorMigrateSkill, "gdh-migrate", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_UPDATE_COMMAND_RELATIVE_PATH, renderCursorUpdateSkill, "gdh-update", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_PREPARE_COMMAND_RELATIVE_PATH, renderCursorPrepareSkill, "gdh-prepare", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_RUN_GAME_COMMAND_RELATIVE_PATH, renderCursorRunGameSkill, "gdh-run-game", pinnedVersion), planCommandInstallAction("cursor", targetPath, adapter, CURSOR_SCAN_COMMAND_RELATIVE_PATH, renderCursorScanSkill, "gdh-scan", pinnedVersion));
|
|
2044
|
-
if (path.resolve(integrationRootPath) !== path.resolve(targetPath)) {
|
|
2045
|
-
actions.push(planDirectWriteFileAction({
|
|
2046
|
-
agent: "cursor",
|
|
2047
|
-
targetPath: integrationRootPath,
|
|
2048
|
-
relativePath: CURSOR_RULE_RELATIVE_PATH,
|
|
2049
|
-
content: renderCursorRule({ targetRelativePath }),
|
|
2050
|
-
readySummary: "Root-launched Cursor rule already routes to the managed Godot target.",
|
|
2051
|
-
createSummary: "Create root-launched Cursor rule that routes to the managed Godot target.",
|
|
2052
|
-
replaceSummary: "Replace root-launched Cursor rule with target-aware links to the managed Godot target.",
|
|
2053
|
-
}), ...planRootSymlinkActions({
|
|
2054
|
-
agent: "cursor",
|
|
2055
|
-
integrationRootPath,
|
|
2056
|
-
targetPath,
|
|
2057
|
-
relativePaths: CURSOR_COMMAND_RELATIVE_PATHS,
|
|
2058
|
-
noun: "Cursor command",
|
|
2059
|
-
}));
|
|
2060
|
-
}
|
|
2061
|
-
return actions;
|
|
2062
|
-
}
|
|
2063
1838
|
function dedupeInstallActions(actions) {
|
|
2064
1839
|
const seen = new Set();
|
|
2065
1840
|
const deduped = [];
|
|
@@ -2111,8 +1886,11 @@ async function applyWriteFileAction(action) {
|
|
|
2111
1886
|
if (action.absolutePath === null) {
|
|
2112
1887
|
throw new Error("Write-file install action is missing an absolute path.");
|
|
2113
1888
|
}
|
|
1889
|
+
if (action.content === null) {
|
|
1890
|
+
throw new Error("Write-file install action is missing rendered content.");
|
|
1891
|
+
}
|
|
2114
1892
|
await fs.mkdir(path.dirname(action.absolutePath), { recursive: true });
|
|
2115
|
-
await fs.writeFile(action.absolutePath, action.content
|
|
1893
|
+
await fs.writeFile(action.absolutePath, action.content, "utf8");
|
|
2116
1894
|
}
|
|
2117
1895
|
async function applyRemoveFileAction(action) {
|
|
2118
1896
|
if (action.absolutePath === null) {
|
|
@@ -2143,16 +1921,6 @@ async function applyLocalHintsAction(action) {
|
|
|
2143
1921
|
gdhDevRepoPath: typeof parsed.gdhDevRepoPath === "string" ? parsed.gdhDevRepoPath : null,
|
|
2144
1922
|
});
|
|
2145
1923
|
}
|
|
2146
|
-
function readCursorRuleVersion(content) {
|
|
2147
|
-
if (content === null) {
|
|
2148
|
-
return null;
|
|
2149
|
-
}
|
|
2150
|
-
const match = content.match(/<!-- GDH CURSOR RULE VERSION: (\d+) -->/);
|
|
2151
|
-
if (!match?.[1]) {
|
|
2152
|
-
return null;
|
|
2153
|
-
}
|
|
2154
|
-
return Number.parseInt(match[1], 10);
|
|
2155
|
-
}
|
|
2156
1924
|
function resolveProjectMcpEnabled(projectConfig) {
|
|
2157
1925
|
if (projectConfig === null) {
|
|
2158
1926
|
return false;
|
|
@@ -2252,12 +2020,6 @@ function patchManagedCodexProjectSection(content, section) {
|
|
|
2252
2020
|
const afterJoin = afterNonEmpty.length > 0 ? `\n\n${afterNonEmpty}` : "\n";
|
|
2253
2021
|
return `${beforeJoin}${section}${afterJoin}`;
|
|
2254
2022
|
}
|
|
2255
|
-
function removeManagedCodexAuthoringHookBlock(content) {
|
|
2256
|
-
return content
|
|
2257
|
-
.replace(/(?:^|\n)# BEGIN GDH managed authoring hooks\n[\s\S]*?# END GDH managed authoring hooks\n?/, "\n")
|
|
2258
|
-
.replace(/\n{3,}/g, "\n\n")
|
|
2259
|
-
.trimEnd();
|
|
2260
|
-
}
|
|
2261
2023
|
function appendManagedCodexAuthoringHookBlock(content) {
|
|
2262
2024
|
const normalized = content.trimEnd();
|
|
2263
2025
|
const separator = normalized.length > 0 ? "\n\n" : "";
|
|
@@ -2287,30 +2049,6 @@ function ensureCodexHooksFeature(content) {
|
|
|
2287
2049
|
}
|
|
2288
2050
|
return [...lines.slice(0, featuresStart), ...featureLines, ...lines.slice(featuresEnd)].join("\n");
|
|
2289
2051
|
}
|
|
2290
|
-
function renderManagedCodexAuthoringHookBlock() {
|
|
2291
|
-
// Phase 82 / LSP-03. Render PostToolUse and Stop registrations inside one
|
|
2292
|
-
// BEGIN/END envelope, in that order. The empty line between the two blocks is
|
|
2293
|
-
// for human readability. removeManagedCodexAuthoringHookBlock strips the
|
|
2294
|
-
// entire envelope as a single unit, so re-render replaces both blocks
|
|
2295
|
-
// atomically (byte-identical idempotency).
|
|
2296
|
-
return [
|
|
2297
|
-
"# BEGIN GDH managed authoring hooks",
|
|
2298
|
-
"[[hooks.PostToolUse]]",
|
|
2299
|
-
'matcher = "^(apply_patch|Edit|Write)$"',
|
|
2300
|
-
"[[hooks.PostToolUse.hooks]]",
|
|
2301
|
-
'type = "command"',
|
|
2302
|
-
`command = ${JSON.stringify(CODEX_AUTHORING_HOOK_COMMAND)}`,
|
|
2303
|
-
"timeout = 30",
|
|
2304
|
-
"",
|
|
2305
|
-
"[[hooks.Stop]]",
|
|
2306
|
-
"[[hooks.Stop.hooks]]",
|
|
2307
|
-
'type = "command"',
|
|
2308
|
-
`command = ${JSON.stringify(CODEX_AUTHORING_HOOK_COMMAND)}`,
|
|
2309
|
-
"timeout = 60",
|
|
2310
|
-
"# END GDH managed authoring hooks",
|
|
2311
|
-
"",
|
|
2312
|
-
].join("\n");
|
|
2313
|
-
}
|
|
2314
2052
|
function extractManagedCodexSection(content) {
|
|
2315
2053
|
const lines = content.split("\n");
|
|
2316
2054
|
const start = lines.findIndex((line) => /^\[mcp_servers\.gdh\]\s*$/.test(line));
|
|
@@ -2942,9 +2680,8 @@ function inspectMcpManifestLifecycleSurface(targetPath, mcpEnabled, adapterStatu
|
|
|
2942
2680
|
});
|
|
2943
2681
|
}
|
|
2944
2682
|
const claudeMcp = findAdapterSurface(adapterStatus, "claude", "mcp_file");
|
|
2945
|
-
const cursorMcp = findAdapterSurface(adapterStatus, "cursor", "mcp_file");
|
|
2946
2683
|
const codexMcp = findAdapterSurface(adapterStatus, "codex", "mcp_file");
|
|
2947
|
-
const probes = [claudeMcp,
|
|
2684
|
+
const probes = [claudeMcp, codexMcp]
|
|
2948
2685
|
.filter((surface) => surface !== null)
|
|
2949
2686
|
.map((surface) => createVersionProbe({
|
|
2950
2687
|
targetPath,
|
|
@@ -2953,13 +2690,13 @@ function inspectMcpManifestLifecycleSurface(targetPath, mcpEnabled, adapterStatu
|
|
|
2953
2690
|
expectedVersion: null,
|
|
2954
2691
|
detectedVersion: surface.present ? surface.version : null,
|
|
2955
2692
|
}));
|
|
2956
|
-
const states = [claudeMcp?.state,
|
|
2693
|
+
const states = [claudeMcp?.state, codexMcp?.state].filter((state) => state !== undefined);
|
|
2957
2694
|
if (states.length > 0 && states.every((state) => state === "ready")) {
|
|
2958
2695
|
return createLifecycleSurfaceStatus({
|
|
2959
2696
|
surface: "mcp_manifest",
|
|
2960
2697
|
management: "managed",
|
|
2961
2698
|
state: "compatible",
|
|
2962
|
-
summary: "Project MCP config files are aligned for Codex
|
|
2699
|
+
summary: "Project MCP config files are aligned for Codex and Claude.",
|
|
2963
2700
|
reasons: [],
|
|
2964
2701
|
probes,
|
|
2965
2702
|
action: null,
|
|
@@ -2984,45 +2721,6 @@ function inspectMcpManifestLifecycleSurface(targetPath, mcpEnabled, adapterStatu
|
|
|
2984
2721
|
},
|
|
2985
2722
|
});
|
|
2986
2723
|
}
|
|
2987
|
-
function inspectCursorRuleLifecycleSurface(targetPath, adapterStatus) {
|
|
2988
|
-
const surface = findAdapterSurface(adapterStatus, "cursor", "rule_file");
|
|
2989
|
-
const probes = surface === null
|
|
2990
|
-
? []
|
|
2991
|
-
: [
|
|
2992
|
-
createVersionProbe({
|
|
2993
|
-
targetPath,
|
|
2994
|
-
relativePath: surface.relativePath ?? CURSOR_RULE_RELATIVE_PATH,
|
|
2995
|
-
present: surface.present,
|
|
2996
|
-
expectedVersion: GDH_CURSOR_RULE_VERSION,
|
|
2997
|
-
detectedVersion: surface.present ? surface.version : null,
|
|
2998
|
-
}),
|
|
2999
|
-
];
|
|
3000
|
-
if (surface?.state === "ready") {
|
|
3001
|
-
return createLifecycleSurfaceStatus({
|
|
3002
|
-
surface: "cursor_rule",
|
|
3003
|
-
management: "managed",
|
|
3004
|
-
state: "compatible",
|
|
3005
|
-
summary: "Cursor rule file matches the current GDH-managed surface.",
|
|
3006
|
-
reasons: [],
|
|
3007
|
-
probes,
|
|
3008
|
-
action: null,
|
|
3009
|
-
});
|
|
3010
|
-
}
|
|
3011
|
-
return createLifecycleSurfaceStatus({
|
|
3012
|
-
surface: "cursor_rule",
|
|
3013
|
-
management: "managed",
|
|
3014
|
-
state: surface?.present ? "migration_available" : "migration_needed",
|
|
3015
|
-
summary: "Cursor rule file needs to be created or refreshed through the adapter install flow.",
|
|
3016
|
-
reasons: surface?.present ? ["cursor_rule_misconfigured"] : ["cursor_rule_missing"],
|
|
3017
|
-
probes,
|
|
3018
|
-
action: {
|
|
3019
|
-
kind: "run_repair",
|
|
3020
|
-
summary: "Run GDH migrate or adapters install to refresh the managed Cursor rule file.",
|
|
3021
|
-
command: ["gdh", "adapters", "install", targetPath],
|
|
3022
|
-
autoApplicable: true,
|
|
3023
|
-
},
|
|
3024
|
-
});
|
|
3025
|
-
}
|
|
3026
2724
|
function inspectRuntimeBridgeLifecycleSurface(targetPath, bridgeStatus) {
|
|
3027
2725
|
const probes = bridgeStatus.managedArtifacts.map((artifact) => createVersionProbe({
|
|
3028
2726
|
targetPath,
|
|
@@ -3563,14 +3261,4 @@ export { DEFAULT_GRACEFUL_STOP_TIMEOUT_MS, STOP_AND_RESTART_ENV_SUBSET_KEYS, bui
|
|
|
3563
3261
|
// package should continue to use inspectProjectLifecycleCompatibility, which
|
|
3564
3262
|
// wraps this function with filesystem probing and surface discovery.
|
|
3565
3263
|
export { summarizeProjectLifecycleCompatibility };
|
|
3566
|
-
/**
|
|
3567
|
-
* Phase 82 / LSP-03. Test-only export of internals to support
|
|
3568
|
-
* codex-config-render.test.ts (Plan 82-02 Wave 0 RED test scaffold). Do NOT
|
|
3569
|
-
* consume this from production code paths; the public renderers/strippers go
|
|
3570
|
-
* through appendManagedCodexAuthoringHookBlock and the regular config patcher.
|
|
3571
|
-
*/
|
|
3572
|
-
export const __testing__ = {
|
|
3573
|
-
renderManagedCodexAuthoringHookBlock,
|
|
3574
|
-
removeManagedCodexAuthoringHookBlock,
|
|
3575
|
-
};
|
|
3576
3264
|
//# sourceMappingURL=index.js.map
|