@skillcap/gdh 0.18.2 → 0.19.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 +4 -4
- package/RELEASE-SPAN-UPDATE-CONTRACTS.json +91 -8
- package/node_modules/@gdh/adapters/dist/authoring-hook-render.d.ts +10 -0
- package/node_modules/@gdh/adapters/dist/authoring-hook-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/authoring-hook-render.js +150 -0
- package/node_modules/@gdh/adapters/dist/authoring-hook-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts +2 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +71 -6
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.d.ts +18 -30
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +364 -1128
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts +45 -0
- package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/skill-rendering.js +419 -0
- package/node_modules/@gdh/adapters/dist/skill-rendering.js.map +1 -0
- package/node_modules/@gdh/adapters/package.json +8 -8
- package/node_modules/@gdh/authoring/dist/diagnostics-summary.d.ts +8 -0
- package/node_modules/@gdh/authoring/dist/diagnostics-summary.d.ts.map +1 -0
- package/node_modules/@gdh/authoring/dist/diagnostics-summary.js +22 -0
- package/node_modules/@gdh/authoring/dist/diagnostics-summary.js.map +1 -0
- package/node_modules/@gdh/authoring/dist/index.d.ts +4 -1
- package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/index.js +17 -2
- package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
- package/node_modules/@gdh/authoring/dist/lsp.d.ts +5 -1
- package/node_modules/@gdh/authoring/dist/lsp.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/lsp.js +95 -1
- package/node_modules/@gdh/authoring/dist/lsp.js.map +1 -1
- package/node_modules/@gdh/authoring/dist/project.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/project.js +1 -0
- package/node_modules/@gdh/authoring/dist/project.js.map +1 -1
- package/node_modules/@gdh/authoring/dist/scene-resource.d.ts +2 -0
- package/node_modules/@gdh/authoring/dist/scene-resource.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/scene-resource.js +15 -1
- package/node_modules/@gdh/authoring/dist/scene-resource.js.map +1 -1
- package/node_modules/@gdh/authoring/package.json +2 -2
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +206 -280
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/package.json +10 -10
- package/node_modules/@gdh/core/dist/index.d.ts +78 -83
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +4 -4
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/dist/agent-contract.js +1 -1
- package/node_modules/@gdh/docs/dist/agent-contract.js.map +1 -1
- package/node_modules/@gdh/docs/dist/guidance.d.ts.map +1 -1
- package/node_modules/@gdh/docs/dist/guidance.js +84 -15
- package/node_modules/@gdh/docs/dist/guidance.js.map +1 -1
- package/node_modules/@gdh/docs/dist/rules.js +3 -3
- package/node_modules/@gdh/docs/dist/rules.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/dist/guidance-audit.d.ts.map +1 -1
- package/node_modules/@gdh/observability/dist/guidance-audit.js +1 -50
- 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/dist/bridge-broker-contract.d.ts +23 -0
- package/node_modules/@gdh/runtime/dist/bridge-broker-contract.d.ts.map +1 -0
- package/node_modules/@gdh/runtime/dist/bridge-broker-contract.js +120 -0
- package/node_modules/@gdh/runtime/dist/bridge-broker-contract.js.map +1 -0
- package/node_modules/@gdh/runtime/dist/index.d.ts +2 -1
- package/node_modules/@gdh/runtime/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/runtime/dist/index.js +28 -62
- package/node_modules/@gdh/runtime/dist/index.js.map +1 -1
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/package.json +3 -3
- package/node_modules/@gdh/verify/dist/index.d.ts +0 -1
- package/node_modules/@gdh/verify/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/verify/dist/index.js +1 -2
- package/node_modules/@gdh/verify/dist/index.js.map +1 -1
- package/node_modules/@gdh/verify/package.json +7 -7
- package/package.json +11 -11
|
@@ -10,11 +10,13 @@ import { createDefaultGuidanceUnits, createDefaultRulesDocument, getGuidanceStat
|
|
|
10
10
|
import { inspectGuidanceAudit } from "@gdh/observability";
|
|
11
11
|
import { inspectRuntimeBridgeSurface, inspectRuntimeKnowledgeSurface } from "@gdh/runtime";
|
|
12
12
|
import { readInventoryCacheOrScan } from "@gdh/scan";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { CLAUDE_SETTINGS_RELATIVE_PATH, patchClaudeSettingsForGdhAuthoringHooks, patchClaudeSettingsForGdhSessionStart, patchClaudeSettingsForGdhStatusline, } from "./claude-settings-patch.js";
|
|
14
|
+
import { CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, CODEX_AUTHORING_HOOK_COMMAND, CODEX_AUTHORING_HOOK_RELATIVE_PATH, renderGdhAuthoringHook, } from "./authoring-hook-render.js";
|
|
15
15
|
import { CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, } from "./claude-statusline-render.js";
|
|
16
16
|
import { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateHook, } from "./claude-update-hook-render.js";
|
|
17
17
|
import { renderClaudeCheckUpdateWorker } from "./claude-update-worker-render.js";
|
|
18
|
+
import { GDH_MANAGED_AGENT_SKILL_MARKER, renderClaudeCheckSkill, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexCheckSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill, renderCursorCheckSkill, renderCursorMigrateSkill, renderCursorOnboardSkill, renderCursorPrepareSkill, renderCursorScanSkill, renderCursorStatusSkill, renderCursorUpdateSkill, } from "./skill-rendering.js";
|
|
19
|
+
export { GDH_MANAGED_AGENT_SKILL_MARKER, GDH_SKILL_DEFINITIONS, GDH_SKILL_IDS, renderGdhSkill, renderManagedSkillMarker, renderClaudeCheckSkill, renderClaudeMigrateSkill, renderClaudeOnboardSkill, renderClaudePrepareSkill, renderClaudeScanSkill, renderClaudeStatusSkill, renderClaudeUpdateSkill, renderCodexCheckSkill, renderCodexMigrateSkill, renderCodexOnboardSkill, renderCodexPrepareSkill, renderCodexScanSkill, renderCodexStatusSkill, renderCodexUpdateSkill, renderCursorCheckSkill, renderCursorMigrateSkill, renderCursorOnboardSkill, renderCursorPrepareSkill, renderCursorScanSkill, renderCursorStatusSkill, renderCursorUpdateSkill, } from "./skill-rendering.js";
|
|
18
20
|
export const adaptersPackage = definePackageBoundary({
|
|
19
21
|
name: "@gdh/adapters",
|
|
20
22
|
layer: "integration",
|
|
@@ -26,7 +28,6 @@ export const adaptersPackage = definePackageBoundary({
|
|
|
26
28
|
"@gdh/observability",
|
|
27
29
|
"@gdh/runtime",
|
|
28
30
|
"@gdh/scan",
|
|
29
|
-
"@gdh/verify",
|
|
30
31
|
],
|
|
31
32
|
});
|
|
32
33
|
export const SUPPORTED_AGENTS = [
|
|
@@ -35,47 +36,60 @@ export const SUPPORTED_AGENTS = [
|
|
|
35
36
|
"cursor",
|
|
36
37
|
];
|
|
37
38
|
export const CLAUDE_SHIM_RELATIVE_PATH = "CLAUDE.md";
|
|
38
|
-
export const
|
|
39
|
+
export const CLAUDE_ONBOARD_SKILL_RELATIVE_PATH = ".claude/skills/gdh-onboard/SKILL.md";
|
|
39
40
|
export const PROJECT_MCP_RELATIVE_PATH = ".mcp.json";
|
|
40
41
|
export const CURSOR_MCP_RELATIVE_PATH = ".cursor/mcp.json";
|
|
41
42
|
export const CURSOR_RULE_RELATIVE_PATH = ".cursor/rules/gdh-agent.mdc";
|
|
42
43
|
export const CURSOR_ONBOARD_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-onboard/SKILL.md";
|
|
43
44
|
export const CODEX_ONBOARD_SKILL_RELATIVE_PATH = ".agents/skills/gdh-onboard/SKILL.md";
|
|
44
|
-
export const
|
|
45
|
-
export const
|
|
46
|
-
export const
|
|
47
|
-
export const
|
|
48
|
-
export const CLAUDE_VERIFY_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/verify.md";
|
|
45
|
+
export const CLAUDE_STATUS_SKILL_RELATIVE_PATH = ".claude/skills/gdh-status/SKILL.md";
|
|
46
|
+
export const CLAUDE_MIGRATE_SKILL_RELATIVE_PATH = ".claude/skills/gdh-migrate/SKILL.md";
|
|
47
|
+
export const CLAUDE_CHECK_SKILL_RELATIVE_PATH = ".claude/skills/gdh-check/SKILL.md";
|
|
48
|
+
export const CLAUDE_PREPARE_SKILL_RELATIVE_PATH = ".claude/skills/gdh-prepare/SKILL.md";
|
|
49
49
|
export const CODEX_STATUS_SKILL_RELATIVE_PATH = ".agents/skills/gdh-status/SKILL.md";
|
|
50
50
|
export const CODEX_MIGRATE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-migrate/SKILL.md";
|
|
51
51
|
export const CODEX_CHECK_SKILL_RELATIVE_PATH = ".agents/skills/gdh-check/SKILL.md";
|
|
52
52
|
export const CODEX_PREPARE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-prepare/SKILL.md";
|
|
53
|
-
export const CODEX_VERIFY_SKILL_RELATIVE_PATH = ".agents/skills/gdh-verify/SKILL.md";
|
|
54
53
|
export const CURSOR_STATUS_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-status/SKILL.md";
|
|
55
54
|
export const CURSOR_MIGRATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-migrate/SKILL.md";
|
|
56
55
|
export const CURSOR_CHECK_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-check/SKILL.md";
|
|
57
56
|
export const CURSOR_PREPARE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-prepare/SKILL.md";
|
|
58
|
-
export const CURSOR_VERIFY_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-verify/SKILL.md";
|
|
59
57
|
// Phase 13 SELF-01: /gdh-update skill surface path constants. The rendered
|
|
60
58
|
// bodies shell out to `npx -y @skillcap/gdh@latest self-update` (LITERAL
|
|
61
59
|
// @latest, not the pinned version — D-10) so the NEW CLI performs the update,
|
|
62
60
|
// not the (potentially pre-Phase-12) OLD pinned one. These constants are
|
|
63
61
|
// INTENTIONALLY excluded from VERIFY_DRIFT_SCANNED_FILES (D-13) because the
|
|
64
62
|
// rendered bodies are version-agnostic by design.
|
|
65
|
-
export const
|
|
63
|
+
export const CLAUDE_UPDATE_SKILL_RELATIVE_PATH = ".claude/skills/gdh-update/SKILL.md";
|
|
66
64
|
export const CODEX_UPDATE_SKILL_RELATIVE_PATH = ".agents/skills/gdh-update/SKILL.md";
|
|
67
65
|
export const CURSOR_UPDATE_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-update/SKILL.md";
|
|
68
|
-
export const
|
|
66
|
+
export const CLAUDE_SCAN_SKILL_RELATIVE_PATH = ".claude/skills/gdh-scan/SKILL.md";
|
|
69
67
|
export const CODEX_SCAN_SKILL_RELATIVE_PATH = ".agents/skills/gdh-scan/SKILL.md";
|
|
68
|
+
export const CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH = CLAUDE_ONBOARD_SKILL_RELATIVE_PATH;
|
|
69
|
+
export const CLAUDE_STATUS_COMMAND_RELATIVE_PATH = CLAUDE_STATUS_SKILL_RELATIVE_PATH;
|
|
70
|
+
export const CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH = CLAUDE_MIGRATE_SKILL_RELATIVE_PATH;
|
|
71
|
+
export const CLAUDE_CHECK_COMMAND_RELATIVE_PATH = CLAUDE_CHECK_SKILL_RELATIVE_PATH;
|
|
72
|
+
export const CLAUDE_PREPARE_COMMAND_RELATIVE_PATH = CLAUDE_PREPARE_SKILL_RELATIVE_PATH;
|
|
73
|
+
export const CLAUDE_UPDATE_COMMAND_RELATIVE_PATH = CLAUDE_UPDATE_SKILL_RELATIVE_PATH;
|
|
74
|
+
export const CLAUDE_SCAN_COMMAND_RELATIVE_PATH = CLAUDE_SCAN_SKILL_RELATIVE_PATH;
|
|
75
|
+
const LEGACY_CLAUDE_SKILL_COMMAND_RELATIVE_PATHS = [
|
|
76
|
+
[".claude/commands/gdh/onboard.md", "gdh-onboard"],
|
|
77
|
+
[".claude/commands/gdh/status.md", "gdh-status"],
|
|
78
|
+
[".claude/commands/gdh/migrate.md", "gdh-migrate"],
|
|
79
|
+
[".claude/commands/gdh/update.md", "gdh-update"],
|
|
80
|
+
[".claude/commands/gdh/check.md", "gdh-check"],
|
|
81
|
+
[".claude/commands/gdh/prepare.md", "gdh-prepare"],
|
|
82
|
+
[".claude/commands/gdh/scan.md", "gdh-scan"],
|
|
83
|
+
];
|
|
70
84
|
const LEGACY_CODEX_SKILL_RELATIVE_PATHS = [
|
|
71
|
-
[".codex/skills/gdh-onboard/SKILL.md",
|
|
72
|
-
[".codex/skills/gdh-status/SKILL.md",
|
|
73
|
-
[".codex/skills/gdh-migrate/SKILL.md",
|
|
74
|
-
[".codex/skills/gdh-update/SKILL.md",
|
|
75
|
-
[".codex/skills/gdh-check/SKILL.md",
|
|
76
|
-
[".codex/skills/gdh-prepare/SKILL.md",
|
|
77
|
-
[".codex/skills/gdh-verify/SKILL.md",
|
|
78
|
-
[".codex/skills/gdh-scan/SKILL.md",
|
|
85
|
+
[".codex/skills/gdh-onboard/SKILL.md", "gdh-onboard"],
|
|
86
|
+
[".codex/skills/gdh-status/SKILL.md", "gdh-status"],
|
|
87
|
+
[".codex/skills/gdh-migrate/SKILL.md", "gdh-migrate"],
|
|
88
|
+
[".codex/skills/gdh-update/SKILL.md", "gdh-update"],
|
|
89
|
+
[".codex/skills/gdh-check/SKILL.md", "gdh-check"],
|
|
90
|
+
[".codex/skills/gdh-prepare/SKILL.md", "gdh-prepare"],
|
|
91
|
+
[".codex/skills/gdh-verify/SKILL.md", "gdh-verify"],
|
|
92
|
+
[".codex/skills/gdh-scan/SKILL.md", "gdh-scan"],
|
|
79
93
|
];
|
|
80
94
|
export const CURSOR_SCAN_SKILL_RELATIVE_PATH = ".cursor/skills/gdh-scan/SKILL.md";
|
|
81
95
|
export const LOCAL_PATH_HINTS_RELATIVE_PATH = ".gdh-state/local-paths.json";
|
|
@@ -83,8 +97,7 @@ export const CODEX_PROJECT_CONFIG_RELATIVE_PATH = ".codex/config.toml";
|
|
|
83
97
|
export const GDH_MCP_SERVER_NAME = "gdh";
|
|
84
98
|
// Phase 17 UX-01: single source of truth for the `/gdh-status` preview-header
|
|
85
99
|
// literal. The character between "dry-run)" and "not" is em-dash U+2014 (NOT
|
|
86
|
-
// two hyphens). Centralizing here prevents silent drift across
|
|
87
|
-
// `/gdh-status` renderer bodies (Pitfall #5 three-adapter parity).
|
|
100
|
+
// two hyphens). Centralizing here prevents silent drift across shipped skills.
|
|
88
101
|
const PREVIEW_HEADER_LITERAL = "Preview (dry-run) — not applied";
|
|
89
102
|
const execFile = promisify(execFileCallback);
|
|
90
103
|
export async function getSupportedAgentAdaptersStatus(targetPath, options = {}) {
|
|
@@ -263,7 +276,6 @@ export async function createGsdSnapshot(targetPath, options = {}) {
|
|
|
263
276
|
const context = await buildAuthoringContext(targetPath);
|
|
264
277
|
const effectiveRepoState = deriveRepoState(context);
|
|
265
278
|
const files = normalizeChangedFiles(options.files ?? []);
|
|
266
|
-
const performed = [...new Set(options.performed ?? [])];
|
|
267
279
|
const guidance = await getGuidanceStatus(targetPath);
|
|
268
280
|
const [audit, guidanceResolve] = await Promise.all([
|
|
269
281
|
inspectGuidanceAudit(targetPath),
|
|
@@ -282,41 +294,6 @@ export async function createGsdSnapshot(targetPath, options = {}) {
|
|
|
282
294
|
guidance,
|
|
283
295
|
audit,
|
|
284
296
|
};
|
|
285
|
-
const validationRecommendation = files.length === 0
|
|
286
|
-
? {
|
|
287
|
-
state: "unavailable",
|
|
288
|
-
summary: "Validation expectations are unavailable until the snapshot is given changed files.",
|
|
289
|
-
value: null,
|
|
290
|
-
}
|
|
291
|
-
: {
|
|
292
|
-
state: "available",
|
|
293
|
-
summary: "Validation expectations were projected from the current GDH verify recommendation surface.",
|
|
294
|
-
value: await recommendValidationForChange({
|
|
295
|
-
targetPath,
|
|
296
|
-
inventory: context.inventory,
|
|
297
|
-
status: context.status,
|
|
298
|
-
projectConfig: context.projectConfig,
|
|
299
|
-
files,
|
|
300
|
-
}),
|
|
301
|
-
};
|
|
302
|
-
const donePolicy = validationRecommendation.value === null
|
|
303
|
-
? {
|
|
304
|
-
state: "unavailable",
|
|
305
|
-
summary: "Done-policy evaluation is unavailable until changed files are supplied for the snapshot.",
|
|
306
|
-
value: null,
|
|
307
|
-
}
|
|
308
|
-
: {
|
|
309
|
-
state: "available",
|
|
310
|
-
summary: "Done-policy evaluation was projected from the current GDH verify done surface.",
|
|
311
|
-
value: await evaluateDonePolicy({
|
|
312
|
-
targetPath,
|
|
313
|
-
inventory: context.inventory,
|
|
314
|
-
status: context.status,
|
|
315
|
-
projectConfig: context.projectConfig,
|
|
316
|
-
files,
|
|
317
|
-
performed,
|
|
318
|
-
}),
|
|
319
|
-
};
|
|
320
297
|
return {
|
|
321
298
|
targetPath,
|
|
322
299
|
adapter: {
|
|
@@ -326,12 +303,9 @@ export async function createGsdSnapshot(targetPath, options = {}) {
|
|
|
326
303
|
summary: "The GSD bridge is an optional read-mostly adapter over stable GDH outputs and is not required for core GDH behavior.",
|
|
327
304
|
},
|
|
328
305
|
files,
|
|
329
|
-
performed,
|
|
330
306
|
status: context.status,
|
|
331
307
|
guidanceStatus,
|
|
332
308
|
guidanceResolve,
|
|
333
|
-
validationRecommendation,
|
|
334
|
-
donePolicy,
|
|
335
309
|
};
|
|
336
310
|
}
|
|
337
311
|
export function renderCursorRule() {
|
|
@@ -351,1016 +325,25 @@ export function renderCursorRule() {
|
|
|
351
325
|
].join("\n");
|
|
352
326
|
}
|
|
353
327
|
export function renderClaudeOnboardCommand(pinnedVersion) {
|
|
354
|
-
return
|
|
355
|
-
"---",
|
|
356
|
-
"name: gdh:onboard",
|
|
357
|
-
"description: Finish GDH setup handoff and report project readiness",
|
|
358
|
-
"allowed-tools:",
|
|
359
|
-
" - Read",
|
|
360
|
-
" - Grep",
|
|
361
|
-
" - Glob",
|
|
362
|
-
" - Bash",
|
|
363
|
-
" - AskUserQuestion",
|
|
364
|
-
"---",
|
|
365
|
-
"<objective>",
|
|
366
|
-
`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.`,
|
|
367
|
-
"</objective>",
|
|
368
|
-
"",
|
|
369
|
-
"<process>",
|
|
370
|
-
"Follow this order:",
|
|
371
|
-
"",
|
|
372
|
-
`1. Confirm the selected target and current GDH state with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
373
|
-
"2. Read `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md` before asking for facts GDH already knows.",
|
|
374
|
-
`3. Check immediate readiness with \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\` and \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\`.`,
|
|
375
|
-
`4. If authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`; if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\`.`,
|
|
376
|
-
`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.`,
|
|
377
|
-
"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.",
|
|
378
|
-
"7. Ask the human only for narrow unresolved environment or target facts.",
|
|
379
|
-
"8. End with a concise readiness summary and the exact next development step.",
|
|
380
|
-
"</process>",
|
|
381
|
-
"",
|
|
382
|
-
"<rules>",
|
|
383
|
-
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
384
|
-
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
385
|
-
"- Keep the output short, operational, and specific.",
|
|
386
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
387
|
-
"</rules>",
|
|
388
|
-
"",
|
|
389
|
-
].join("\n");
|
|
328
|
+
return renderClaudeOnboardSkill(pinnedVersion);
|
|
390
329
|
}
|
|
391
|
-
export function renderCodexOnboardSkill(pinnedVersion) {
|
|
392
|
-
return [
|
|
393
|
-
"---",
|
|
394
|
-
'name: "gdh-onboard"',
|
|
395
|
-
'description: "Finish GDH setup handoff and report project readiness"',
|
|
396
|
-
"metadata:",
|
|
397
|
-
' short-description: "Finish GDH setup handoff and report project readiness"',
|
|
398
|
-
"---",
|
|
399
|
-
"",
|
|
400
|
-
"<codex_skill_adapter>",
|
|
401
|
-
"## Invocation",
|
|
402
|
-
"- This skill is invoked when the user says `/gdh-onboard` or mentions `$gdh-onboard`.",
|
|
403
|
-
"- Treat any extra user text as additional onboarding context.",
|
|
404
|
-
"",
|
|
405
|
-
"## User questions",
|
|
406
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing setup fact safely.",
|
|
407
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
408
|
-
"</codex_skill_adapter>",
|
|
409
|
-
"",
|
|
410
|
-
"<objective>",
|
|
411
|
-
`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.`,
|
|
412
|
-
"</objective>",
|
|
413
|
-
"",
|
|
414
|
-
"<process>",
|
|
415
|
-
"Follow this order:",
|
|
416
|
-
"",
|
|
417
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
418
|
-
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
419
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
420
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
421
|
-
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
422
|
-
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
423
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
424
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
425
|
-
"- 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",
|
|
426
|
-
"- ask only for narrow unresolved environment or target facts",
|
|
427
|
-
"- finish with a concise readiness summary and the exact next development step",
|
|
428
|
-
"</process>",
|
|
429
|
-
"",
|
|
430
|
-
"<rules>",
|
|
431
|
-
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
432
|
-
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
433
|
-
"- Keep output short, operational, and specific.",
|
|
434
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
435
|
-
"</rules>",
|
|
436
|
-
"",
|
|
437
|
-
].join("\n");
|
|
438
|
-
}
|
|
439
|
-
export function renderCursorOnboardSkill(pinnedVersion) {
|
|
440
|
-
return [
|
|
441
|
-
"---",
|
|
442
|
-
"name: gdh-onboard",
|
|
443
|
-
'description: "Finish GDH setup handoff and report project readiness"',
|
|
444
|
-
"---",
|
|
445
|
-
"",
|
|
446
|
-
"<cursor_skill_adapter>",
|
|
447
|
-
"## Invocation",
|
|
448
|
-
"- This skill is invoked when the user says `/gdh-onboard` or mentions `gdh-onboard`.",
|
|
449
|
-
"- Treat any extra user text as additional onboarding context.",
|
|
450
|
-
"",
|
|
451
|
-
"## User questions",
|
|
452
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing setup fact safely.",
|
|
453
|
-
"- Keep questions conversational and concise.",
|
|
454
|
-
"</cursor_skill_adapter>",
|
|
455
|
-
"",
|
|
456
|
-
"<objective>",
|
|
457
|
-
`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.`,
|
|
458
|
-
"</objective>",
|
|
459
|
-
"",
|
|
460
|
-
"<process>",
|
|
461
|
-
"Follow this order:",
|
|
462
|
-
"",
|
|
463
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
464
|
-
"- inspect `.gdh/project.yaml`, `docs/agent/README.md`, and `docs/agent/00-gdh-onboarding.md`",
|
|
465
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} guidance status\``,
|
|
466
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\``,
|
|
467
|
-
`- if authoring is available, run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
|
|
468
|
-
`- if LSP matters, run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\``,
|
|
469
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} run-config list\``,
|
|
470
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verification-scenario list\``,
|
|
471
|
-
"- 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",
|
|
472
|
-
"- ask only for narrow unresolved environment or target facts",
|
|
473
|
-
"- finish with a concise readiness summary and the exact next development step",
|
|
474
|
-
"</process>",
|
|
475
|
-
"",
|
|
476
|
-
"<rules>",
|
|
477
|
-
"- Do not start editing code during `/gdh-onboard` unless the human explicitly asks.",
|
|
478
|
-
"- Prefer GDH structured surfaces over repo guesswork.",
|
|
479
|
-
"- Keep output short, operational, and specific.",
|
|
480
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
481
|
-
"</rules>",
|
|
482
|
-
"",
|
|
483
|
-
].join("\n");
|
|
484
|
-
}
|
|
485
|
-
// --- gdh-status skill renders ---
|
|
486
330
|
export function renderClaudeStatusCommand(pinnedVersion) {
|
|
487
|
-
return
|
|
488
|
-
"---",
|
|
489
|
-
"name: gdh:status",
|
|
490
|
-
"description: Check GDH project readiness, surface migration needs, and suggest next step",
|
|
491
|
-
"allowed-tools:",
|
|
492
|
-
" - Read",
|
|
493
|
-
" - Grep",
|
|
494
|
-
" - Glob",
|
|
495
|
-
" - Bash",
|
|
496
|
-
"---",
|
|
497
|
-
"<objective>",
|
|
498
|
-
"Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
|
|
499
|
-
"</objective>",
|
|
500
|
-
"",
|
|
501
|
-
"<process>",
|
|
502
|
-
"Follow this order:",
|
|
503
|
-
"",
|
|
504
|
-
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field.`,
|
|
505
|
-
"2. Distinguish `blockingReasons` (needs /gdh-update or manual intervention) from `coupledReasons` (fixable via /gdh-migrate).",
|
|
506
|
-
`3. Check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\`.`,
|
|
507
|
-
`4. ${PREVIEW_HEADER_LITERAL} — migrate output at this step describes planned actions ("would delete …") not applied ones ("deleted").`,
|
|
508
|
-
"5. If status JSON `recoveryHints` array is non-empty, surface each entry's `{command, skillName}` pair.",
|
|
509
|
-
"6. Surface any degraded or unavailable capabilities.",
|
|
510
|
-
"7. Suggest the most productive next step based on current state.",
|
|
511
|
-
"</process>",
|
|
512
|
-
"",
|
|
513
|
-
"<rules>",
|
|
514
|
-
"- Do not start editing code.",
|
|
515
|
-
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
516
|
-
"- Keep output short and operational.",
|
|
517
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
518
|
-
"</rules>",
|
|
519
|
-
"",
|
|
520
|
-
].join("\n");
|
|
331
|
+
return renderClaudeStatusSkill(pinnedVersion);
|
|
521
332
|
}
|
|
522
|
-
export function renderCodexStatusSkill(pinnedVersion) {
|
|
523
|
-
return [
|
|
524
|
-
"---",
|
|
525
|
-
'name: "gdh-status"',
|
|
526
|
-
'description: "Check GDH project readiness, surface migration needs, and suggest next step"',
|
|
527
|
-
"metadata:",
|
|
528
|
-
' short-description: "Check GDH project readiness, surface migration needs, and suggest next step"',
|
|
529
|
-
"---",
|
|
530
|
-
"",
|
|
531
|
-
"<codex_skill_adapter>",
|
|
532
|
-
"## Invocation",
|
|
533
|
-
"- This skill is invoked when the user says `/gdh-status` or mentions `$gdh-status`.",
|
|
534
|
-
"- Treat any extra user text as additional status context.",
|
|
535
|
-
"",
|
|
536
|
-
"## User questions",
|
|
537
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
538
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
539
|
-
"</codex_skill_adapter>",
|
|
540
|
-
"",
|
|
541
|
-
"<objective>",
|
|
542
|
-
"Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
|
|
543
|
-
"</objective>",
|
|
544
|
-
"",
|
|
545
|
-
"<process>",
|
|
546
|
-
"Follow this order:",
|
|
547
|
-
"",
|
|
548
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
549
|
-
"- distinguish `blockingReasons` (needs /gdh-update or manual intervention) from `coupledReasons` (fixable via /gdh-migrate)",
|
|
550
|
-
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
551
|
-
`- ${PREVIEW_HEADER_LITERAL} — migrate output describes planned actions ("would delete …") not applied ones ("deleted")`,
|
|
552
|
-
"- if status JSON `recoveryHints` array is non-empty, surface each entry's `{command, skillName}` pair",
|
|
553
|
-
"- surface any degraded or unavailable capabilities",
|
|
554
|
-
"- suggest the most productive next step based on current state",
|
|
555
|
-
"</process>",
|
|
556
|
-
"",
|
|
557
|
-
"<rules>",
|
|
558
|
-
"- Do not start editing code.",
|
|
559
|
-
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
560
|
-
"- Keep output short and operational.",
|
|
561
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
562
|
-
"</rules>",
|
|
563
|
-
"",
|
|
564
|
-
].join("\n");
|
|
565
|
-
}
|
|
566
|
-
export function renderCursorStatusSkill(pinnedVersion) {
|
|
567
|
-
return [
|
|
568
|
-
"---",
|
|
569
|
-
"name: gdh-status",
|
|
570
|
-
'description: "Check GDH project readiness, surface migration needs, and suggest next step"',
|
|
571
|
-
"---",
|
|
572
|
-
"",
|
|
573
|
-
"<cursor_skill_adapter>",
|
|
574
|
-
"## Invocation",
|
|
575
|
-
"- This skill is invoked when the user says `/gdh-status` or mentions `gdh-status`.",
|
|
576
|
-
"- Treat any extra user text as additional status context.",
|
|
577
|
-
"",
|
|
578
|
-
"## User questions",
|
|
579
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
580
|
-
"- Keep questions conversational and concise.",
|
|
581
|
-
"</cursor_skill_adapter>",
|
|
582
|
-
"",
|
|
583
|
-
"<objective>",
|
|
584
|
-
"Check GDH project readiness, surface migration needs, and suggest the most productive next step.",
|
|
585
|
-
"</objective>",
|
|
586
|
-
"",
|
|
587
|
-
"<process>",
|
|
588
|
-
"Follow this order:",
|
|
589
|
-
"",
|
|
590
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} status\` and explain each readiness field`,
|
|
591
|
-
"- distinguish `blockingReasons` (needs /gdh-update or manual intervention) from `coupledReasons` (fixable via /gdh-migrate)",
|
|
592
|
-
`- check if migration is needed with \`npx -y @skillcap/gdh@${pinnedVersion} migrate\``,
|
|
593
|
-
`- ${PREVIEW_HEADER_LITERAL} — migrate output describes planned actions ("would delete …") not applied ones ("deleted")`,
|
|
594
|
-
"- if status JSON `recoveryHints` array is non-empty, surface each entry's `{command, skillName}` pair",
|
|
595
|
-
"- surface any degraded or unavailable capabilities",
|
|
596
|
-
"- suggest the most productive next step based on current state",
|
|
597
|
-
"</process>",
|
|
598
|
-
"",
|
|
599
|
-
"<rules>",
|
|
600
|
-
"- Do not start editing code.",
|
|
601
|
-
"- Prefer structured GDH surfaces over repo guesswork.",
|
|
602
|
-
"- Keep output short and operational.",
|
|
603
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
604
|
-
"</rules>",
|
|
605
|
-
"",
|
|
606
|
-
].join("\n");
|
|
607
|
-
}
|
|
608
|
-
// --- gdh-scan skill renders ---
|
|
609
333
|
export function renderClaudeScanCommand(pinnedVersion) {
|
|
610
|
-
return
|
|
611
|
-
"---",
|
|
612
|
-
"name: gdh:scan",
|
|
613
|
-
"description: Refresh inventory cache and explain persistence effect",
|
|
614
|
-
"allowed-tools:",
|
|
615
|
-
" - Read",
|
|
616
|
-
" - Grep",
|
|
617
|
-
" - Glob",
|
|
618
|
-
" - Bash",
|
|
619
|
-
"---",
|
|
620
|
-
"<objective>",
|
|
621
|
-
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
622
|
-
"</objective>",
|
|
623
|
-
"",
|
|
624
|
-
"<process>",
|
|
625
|
-
"Follow this order:",
|
|
626
|
-
"",
|
|
627
|
-
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} scan\` and parse the \`persisted\` field from the envelope.`,
|
|
628
|
-
"2. Check the `mode` field: `create`, `unchanged`, `overwrite`, or `null`.",
|
|
629
|
-
"3. Explain the persistence effect; if `null`, the target is not onboarded and no disk write occurred.",
|
|
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 renderCodexScanSkill(pinnedVersion) {
|
|
641
|
-
return [
|
|
642
|
-
"---",
|
|
643
|
-
'name: "gdh-scan"',
|
|
644
|
-
'description: "Refresh inventory cache and explain persistence effect"',
|
|
645
|
-
"metadata:",
|
|
646
|
-
' short-description: "Refresh inventory cache and explain persistence effect"',
|
|
647
|
-
"---",
|
|
648
|
-
"",
|
|
649
|
-
"<codex_skill_adapter>",
|
|
650
|
-
"## Invocation",
|
|
651
|
-
"- This skill is invoked when the user says `/gdh-scan` or mentions `$gdh-scan`.",
|
|
652
|
-
"- Treat any extra user text as additional scan context.",
|
|
653
|
-
"",
|
|
654
|
-
"## User questions",
|
|
655
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
656
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
657
|
-
"</codex_skill_adapter>",
|
|
658
|
-
"",
|
|
659
|
-
"<objective>",
|
|
660
|
-
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
661
|
-
"</objective>",
|
|
662
|
-
"",
|
|
663
|
-
"<process>",
|
|
664
|
-
"Follow this order:",
|
|
665
|
-
"",
|
|
666
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
667
|
-
"- parse the `persisted` field from the envelope",
|
|
668
|
-
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
669
|
-
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
670
|
-
"</process>",
|
|
671
|
-
"",
|
|
672
|
-
"<rules>",
|
|
673
|
-
"- Do not edit the persisted inventory directly.",
|
|
674
|
-
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
675
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
676
|
-
"</rules>",
|
|
677
|
-
"",
|
|
678
|
-
].join("\n");
|
|
679
|
-
}
|
|
680
|
-
export function renderCursorScanSkill(pinnedVersion) {
|
|
681
|
-
return [
|
|
682
|
-
"---",
|
|
683
|
-
"name: gdh-scan",
|
|
684
|
-
'description: "Refresh inventory cache and explain persistence effect"',
|
|
685
|
-
"---",
|
|
686
|
-
"",
|
|
687
|
-
"<cursor_skill_adapter>",
|
|
688
|
-
"## Invocation",
|
|
689
|
-
"- This skill is invoked when the user says `/gdh-scan` or mentions `gdh-scan`.",
|
|
690
|
-
"- Treat any extra user text as additional scan context.",
|
|
691
|
-
"",
|
|
692
|
-
"## User questions",
|
|
693
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
694
|
-
"- Keep questions conversational and concise.",
|
|
695
|
-
"</cursor_skill_adapter>",
|
|
696
|
-
"",
|
|
697
|
-
"<objective>",
|
|
698
|
-
"Refresh the inventory cache and explain the persistence effect of the scan.",
|
|
699
|
-
"</objective>",
|
|
700
|
-
"",
|
|
701
|
-
"<process>",
|
|
702
|
-
"Follow this order:",
|
|
703
|
-
"",
|
|
704
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} scan\``,
|
|
705
|
-
"- parse the `persisted` field from the envelope",
|
|
706
|
-
"- check `mode`: `create`, `unchanged`, `overwrite`, or `null`",
|
|
707
|
-
"- explain the persistence effect; if `null`, explain the target is not onboarded",
|
|
708
|
-
"</process>",
|
|
709
|
-
"",
|
|
710
|
-
"<rules>",
|
|
711
|
-
"- Do not edit the persisted inventory directly.",
|
|
712
|
-
"- Prefer the cached inventory for status reads; re-run scan only when freshness is in question.",
|
|
713
|
-
"- For cache/persistence behavior of scan, status, onboard: see `docs/agent/persistence-semantics.md`.",
|
|
714
|
-
"</rules>",
|
|
715
|
-
"",
|
|
716
|
-
].join("\n");
|
|
334
|
+
return renderClaudeScanSkill(pinnedVersion);
|
|
717
335
|
}
|
|
718
|
-
// --- gdh-migrate skill renders ---
|
|
719
336
|
export function renderClaudeMigrateCommand(pinnedVersion) {
|
|
720
|
-
return
|
|
721
|
-
"---",
|
|
722
|
-
"name: gdh:migrate",
|
|
723
|
-
"description: Preview and apply GDH project migrations",
|
|
724
|
-
"allowed-tools:",
|
|
725
|
-
" - Read",
|
|
726
|
-
" - Grep",
|
|
727
|
-
" - Glob",
|
|
728
|
-
" - Bash",
|
|
729
|
-
" - AskUserQuestion",
|
|
730
|
-
"---",
|
|
731
|
-
"<objective>",
|
|
732
|
-
"Preview and apply GDH project migrations safely with explicit user approval.",
|
|
733
|
-
"</objective>",
|
|
734
|
-
"",
|
|
735
|
-
"<process>",
|
|
736
|
-
"Follow this order:",
|
|
737
|
-
"",
|
|
738
|
-
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`).`,
|
|
739
|
-
"2. Inspect `compatibility.blockingReasons` vs `compatibility.coupledReasons` — if `blockingReasons` is non-empty, STOP: `migrate --apply` cannot fix them (recommend `/gdh-update` or manual intervention per each reason's recovery hint). If only `coupledReasons` is non-empty, proceed.",
|
|
740
|
-
'3. Explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh").',
|
|
741
|
-
`4. Offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves — after apply, the JSON \`mode\` field becomes \`"applied"\` and verbs switch to past tense ("deleted", "created", "refreshed").`,
|
|
742
|
-
"5. After apply, read `terminal.state` in the stdout JSON.",
|
|
743
|
-
"6. If `terminal.state` is `healthy`, confirm no further migration action is required and stop.",
|
|
744
|
-
"7. If `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping.",
|
|
745
|
-
"8. If `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of improvising a repair.",
|
|
746
|
-
"9. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
|
|
747
|
-
"</process>",
|
|
748
|
-
"",
|
|
749
|
-
"<rules>",
|
|
750
|
-
"- Never apply migrations without explicit user approval.",
|
|
751
|
-
"- Show the dry-run output first.",
|
|
752
|
-
"- Keep explanations concise.",
|
|
753
|
-
"</rules>",
|
|
754
|
-
"",
|
|
755
|
-
].join("\n");
|
|
756
|
-
}
|
|
757
|
-
export function renderCodexMigrateSkill(pinnedVersion) {
|
|
758
|
-
return [
|
|
759
|
-
"---",
|
|
760
|
-
'name: "gdh-migrate"',
|
|
761
|
-
'description: "Preview and apply GDH project migrations"',
|
|
762
|
-
"metadata:",
|
|
763
|
-
' short-description: "Preview and apply GDH project migrations"',
|
|
764
|
-
"---",
|
|
765
|
-
"",
|
|
766
|
-
"<codex_skill_adapter>",
|
|
767
|
-
"## Invocation",
|
|
768
|
-
"- This skill is invoked when the user says `/gdh-migrate` or mentions `$gdh-migrate`.",
|
|
769
|
-
"- Treat any extra user text as additional migration context.",
|
|
770
|
-
"",
|
|
771
|
-
"## User questions",
|
|
772
|
-
"- Always ask before applying migrations.",
|
|
773
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
774
|
-
"</codex_skill_adapter>",
|
|
775
|
-
"",
|
|
776
|
-
"<objective>",
|
|
777
|
-
"Preview and apply GDH project migrations safely with explicit user approval.",
|
|
778
|
-
"</objective>",
|
|
779
|
-
"",
|
|
780
|
-
"<process>",
|
|
781
|
-
"Follow this order:",
|
|
782
|
-
"",
|
|
783
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`)`,
|
|
784
|
-
"- inspect `compatibility.blockingReasons` vs `compatibility.coupledReasons` — if `blockingReasons` is non-empty, STOP: `migrate --apply` cannot fix them (recommend `/gdh-update` or manual intervention per each reason's recovery hint); if only `coupledReasons` is non-empty, proceed",
|
|
785
|
-
'- explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh")',
|
|
786
|
-
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves — after apply, the JSON \`mode\` field becomes \`"applied"\` and verbs switch to past tense ("deleted", "created", "refreshed")`,
|
|
787
|
-
"- after apply, read `terminal.state` in the stdout JSON",
|
|
788
|
-
"- if `terminal.state` is `healthy`, confirm no further migration action is required and stop",
|
|
789
|
-
"- if `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping",
|
|
790
|
-
"- if `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of improvising a repair",
|
|
791
|
-
"- if `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop",
|
|
792
|
-
"</process>",
|
|
793
|
-
"",
|
|
794
|
-
"<rules>",
|
|
795
|
-
"- Never apply migrations without explicit user approval.",
|
|
796
|
-
"- Show the dry-run output first.",
|
|
797
|
-
"- Keep explanations concise.",
|
|
798
|
-
"</rules>",
|
|
799
|
-
"",
|
|
800
|
-
].join("\n");
|
|
801
|
-
}
|
|
802
|
-
export function renderCursorMigrateSkill(pinnedVersion) {
|
|
803
|
-
return [
|
|
804
|
-
"---",
|
|
805
|
-
"name: gdh-migrate",
|
|
806
|
-
'description: "Preview and apply GDH project migrations"',
|
|
807
|
-
"---",
|
|
808
|
-
"",
|
|
809
|
-
"<cursor_skill_adapter>",
|
|
810
|
-
"## Invocation",
|
|
811
|
-
"- This skill is invoked when the user says `/gdh-migrate` or mentions `gdh-migrate`.",
|
|
812
|
-
"- Treat any extra user text as additional migration context.",
|
|
813
|
-
"",
|
|
814
|
-
"## User questions",
|
|
815
|
-
"- Always ask before applying migrations.",
|
|
816
|
-
"- Keep questions conversational and concise.",
|
|
817
|
-
"</cursor_skill_adapter>",
|
|
818
|
-
"",
|
|
819
|
-
"<objective>",
|
|
820
|
-
"Preview and apply GDH project migrations safely with explicit user approval.",
|
|
821
|
-
"</objective>",
|
|
822
|
-
"",
|
|
823
|
-
"<process>",
|
|
824
|
-
"Follow this order:",
|
|
825
|
-
"",
|
|
826
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`)`,
|
|
827
|
-
"- inspect `compatibility.blockingReasons` vs `compatibility.coupledReasons` — if `blockingReasons` is non-empty, STOP: `migrate --apply` cannot fix them (recommend `/gdh-update` or manual intervention per each reason's recovery hint); if only `coupledReasons` is non-empty, proceed",
|
|
828
|
-
'- explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh")',
|
|
829
|
-
`- offer to run \`npx -y @skillcap/gdh@${pinnedVersion} migrate --apply\` if the user approves — after apply, the JSON \`mode\` field becomes \`"applied"\` and verbs switch to past tense ("deleted", "created", "refreshed")`,
|
|
830
|
-
"- after apply, read `terminal.state` in the stdout JSON",
|
|
831
|
-
"- if `terminal.state` is `healthy`, confirm no further migration action is required and stop",
|
|
832
|
-
"- if `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping",
|
|
833
|
-
"- if `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of improvising a repair",
|
|
834
|
-
"- if `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop",
|
|
835
|
-
"</process>",
|
|
836
|
-
"",
|
|
837
|
-
"<rules>",
|
|
838
|
-
"- Never apply migrations without explicit user approval.",
|
|
839
|
-
"- Show the dry-run output first.",
|
|
840
|
-
"- Keep explanations concise.",
|
|
841
|
-
"</rules>",
|
|
842
|
-
"",
|
|
843
|
-
].join("\n");
|
|
844
|
-
}
|
|
845
|
-
// --- gdh-update skill renders (Phase 13 SELF-01) ---
|
|
846
|
-
//
|
|
847
|
-
// D-10 invariant: every rendered body shells out to the LITERAL string
|
|
848
|
-
// `@skillcap/gdh@latest` in every npx line (dry-run, apply, verify drift).
|
|
849
|
-
// The `pinnedVersion` parameter is accepted for planSkillInstallAction
|
|
850
|
-
// signature symmetry with every other renderer, but MUST NOT be interpolated
|
|
851
|
-
// into the shellout — running the OLD pinned CLI (potentially pre-Phase-12
|
|
852
|
-
// and lacking bumpAndRebakePin entirely) to perform its own update is the
|
|
853
|
-
// failure mode Phase 13 exists to close. Check 44 in scripts/validate-docs.mjs
|
|
854
|
-
// enforces both the @latest presence AND the @${pinnedVersion} absence.
|
|
855
|
-
//
|
|
856
|
-
// Phase 41 update-flow policy: preview first, then explicit approval before
|
|
857
|
-
// apply, then terminal-driven follow-through. The renderers still avoid
|
|
858
|
-
// adapter-specific branching logic here — they all consume the same
|
|
859
|
-
// structured `preview` JSON from `gdh self-update --dry-run`, then after
|
|
860
|
-
// apply they use `terminal.state` as the final truth for whether the update
|
|
861
|
-
// is healthy, needs follow-up commands, needs manual review, or is blocked.
|
|
862
|
-
//
|
|
863
|
-
// D-12: accept an optional positional version forwarded verbatim to the CLI.
|
|
864
|
-
// `/gdh-update` = latest; `/gdh-update 0.6.0` = pin that version.
|
|
865
|
-
//
|
|
866
|
-
// D-13: the three rendered skill files are EXCLUDED from VERIFY_DRIFT_SCANNED_FILES
|
|
867
|
-
// because @latest is not a semver literal — the baked-version scanner would
|
|
868
|
-
// permanently report no_baked_version. See rationale comments adjacent to the
|
|
869
|
-
// VERIFY_DRIFT_SCANNED_FILES declaration in packages/cli/src/index.ts.
|
|
870
|
-
export function renderClaudeUpdateCommand(_pinnedVersion) {
|
|
871
|
-
return [
|
|
872
|
-
"---",
|
|
873
|
-
"name: gdh:update",
|
|
874
|
-
"description: Update GDH to npm latest (bump pinned version + re-bake managed surfaces)",
|
|
875
|
-
"allowed-tools:",
|
|
876
|
-
" - Read",
|
|
877
|
-
" - Bash",
|
|
878
|
-
"---",
|
|
879
|
-
"<objective>",
|
|
880
|
-
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
881
|
-
"Treat any positional argument (e.g., `/gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
882
|
-
"</objective>",
|
|
883
|
-
"",
|
|
884
|
-
"<process>",
|
|
885
|
-
"Follow this order:",
|
|
886
|
-
"",
|
|
887
|
-
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
888
|
-
"2. Read the `preview` field in the stdout JSON. If `preview.state` is `blocked`, surface the issues and stop. If `preview.state` is `noop`, explain the project is already at the target version and stop.",
|
|
889
|
-
"3. When `preview.state` is `ready`, summarize the current version, target version, intervening releases, bounded release highlights, ordered steps, and which work is `mechanical`, `agent_reasoning`, or `manual_review`.",
|
|
890
|
-
"4. Ask for explicit approval before apply.",
|
|
891
|
-
"5. 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`).",
|
|
892
|
-
"6. If this chat or editor keeps a long-lived GDH MCP session alive, do the MCP cleanup yourself before trusting MCP follow-up output: stop stale `gdh mcp serve` / `@skillcap/gdh ... mcp serve` processes for this target when possible, then let the next MCP connection restart from the updated config. If the client owns reconnection and the process cannot be controlled from Bash, report that limitation after attempting cleanup.",
|
|
893
|
-
"7. Verify baked pinning: run `npx -y @skillcap/gdh@latest verify drift` to confirm every managed skill/command surface matches the new pin. This does not validate runtime bridge or other lifecycle surfaces.",
|
|
894
|
-
"8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
|
|
895
|
-
"9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
|
|
896
|
-
"10. If `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping.",
|
|
897
|
-
"11. If `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of inventing a repair.",
|
|
898
|
-
"12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
|
|
899
|
-
"</process>",
|
|
900
|
-
"",
|
|
901
|
-
"<rules>",
|
|
902
|
-
"- Do ask for explicit approval after the structured preview and before apply.",
|
|
903
|
-
"- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
|
|
904
|
-
"- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
|
|
905
|
-
"- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
|
|
906
|
-
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
907
|
-
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
908
|
-
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
909
|
-
"</rules>",
|
|
910
|
-
"",
|
|
911
|
-
].join("\n");
|
|
337
|
+
return renderClaudeMigrateSkill(pinnedVersion);
|
|
912
338
|
}
|
|
913
|
-
export function
|
|
914
|
-
return
|
|
915
|
-
"---",
|
|
916
|
-
'name: "gdh-update"',
|
|
917
|
-
'description: "Update GDH to npm latest (bump pinned version + re-bake managed surfaces)"',
|
|
918
|
-
"metadata:",
|
|
919
|
-
' short-description: "Update GDH to npm latest"',
|
|
920
|
-
"---",
|
|
921
|
-
"",
|
|
922
|
-
"<codex_skill_adapter>",
|
|
923
|
-
"## Invocation",
|
|
924
|
-
"- This skill is invoked when the user says `/gdh-update` or mentions `$gdh-update`.",
|
|
925
|
-
"- Treat any positional argument (e.g., `/gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
926
|
-
"</codex_skill_adapter>",
|
|
927
|
-
"",
|
|
928
|
-
"<objective>",
|
|
929
|
-
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
930
|
-
"</objective>",
|
|
931
|
-
"",
|
|
932
|
-
"<process>",
|
|
933
|
-
"Follow this order:",
|
|
934
|
-
"",
|
|
935
|
-
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
936
|
-
"2. Read the `preview` field in the stdout JSON. If `preview.state` is `blocked`, surface the issues and stop. If `preview.state` is `noop`, explain the project is already at the target version and stop.",
|
|
937
|
-
"3. When `preview.state` is `ready`, summarize the current version, target version, intervening releases, bounded release highlights, ordered steps, and which work is `mechanical`, `agent_reasoning`, or `manual_review`.",
|
|
938
|
-
"4. Ask for explicit approval before apply.",
|
|
939
|
-
"5. 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`).",
|
|
940
|
-
"6. If this chat or editor keeps a long-lived GDH MCP session alive, do the MCP cleanup yourself before trusting MCP follow-up output: stop stale `gdh mcp serve` / `@skillcap/gdh ... mcp serve` processes for this target when possible, then let the next MCP connection restart from the updated config. If the client owns reconnection and the process cannot be controlled from Bash, report that limitation after attempting cleanup.",
|
|
941
|
-
"7. Verify baked pinning: run `npx -y @skillcap/gdh@latest verify drift` to confirm every managed skill/command surface matches the new pin. This does not validate runtime bridge or other lifecycle surfaces.",
|
|
942
|
-
"8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
|
|
943
|
-
"9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
|
|
944
|
-
"10. If `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping.",
|
|
945
|
-
"11. If `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of inventing a repair.",
|
|
946
|
-
"12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
|
|
947
|
-
"</process>",
|
|
948
|
-
"",
|
|
949
|
-
"<rules>",
|
|
950
|
-
"- Do ask for explicit approval after the structured preview and before apply.",
|
|
951
|
-
"- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
|
|
952
|
-
"- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
|
|
953
|
-
"- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
|
|
954
|
-
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
955
|
-
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
956
|
-
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
957
|
-
"</rules>",
|
|
958
|
-
"",
|
|
959
|
-
].join("\n");
|
|
339
|
+
export function renderClaudeUpdateCommand(pinnedVersion) {
|
|
340
|
+
return renderClaudeUpdateSkill(pinnedVersion);
|
|
960
341
|
}
|
|
961
|
-
export function renderCursorUpdateSkill(_pinnedVersion) {
|
|
962
|
-
return [
|
|
963
|
-
"---",
|
|
964
|
-
"name: gdh-update",
|
|
965
|
-
'description: "Update GDH to npm latest (bump pinned version + re-bake managed surfaces)"',
|
|
966
|
-
"---",
|
|
967
|
-
"",
|
|
968
|
-
"<cursor_skill_adapter>",
|
|
969
|
-
"## Invocation",
|
|
970
|
-
"- This skill is invoked when the user says `/gdh-update` or mentions `gdh-update`.",
|
|
971
|
-
"- Treat any positional argument (e.g., `gdh-update 0.6.0`) as an explicit version; otherwise default to npm latest.",
|
|
972
|
-
"</cursor_skill_adapter>",
|
|
973
|
-
"",
|
|
974
|
-
"<objective>",
|
|
975
|
-
"Update this project's GDH pinning to npm latest and re-bake every managed surface at the new pin.",
|
|
976
|
-
"</objective>",
|
|
977
|
-
"",
|
|
978
|
-
"<process>",
|
|
979
|
-
"Follow this order:",
|
|
980
|
-
"",
|
|
981
|
-
"1. Preview: run `npx -y @skillcap/gdh@latest self-update [version] --dry-run` (omit `[version]` to preview against npm latest).",
|
|
982
|
-
"2. Read the `preview` field in the stdout JSON. If `preview.state` is `blocked`, surface the issues and stop. If `preview.state` is `noop`, explain the project is already at the target version and stop.",
|
|
983
|
-
"3. When `preview.state` is `ready`, summarize the current version, target version, intervening releases, bounded release highlights, ordered steps, and which work is `mechanical`, `agent_reasoning`, or `manual_review`.",
|
|
984
|
-
"4. Ask for explicit approval before apply.",
|
|
985
|
-
"5. 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`).",
|
|
986
|
-
"6. If this chat or editor keeps a long-lived GDH MCP session alive, do the MCP cleanup yourself before trusting MCP follow-up output: stop stale `gdh mcp serve` / `@skillcap/gdh ... mcp serve` processes for this target when possible, then let the next MCP connection restart from the updated config. If the client owns reconnection and the process cannot be controlled from Bash, report that limitation after attempting cleanup.",
|
|
987
|
-
"7. Verify baked pinning: run `npx -y @skillcap/gdh@latest verify drift` to confirm every managed skill/command surface matches the new pin. This does not validate runtime bridge or other lifecycle surfaces.",
|
|
988
|
-
"8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
|
|
989
|
-
"9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
|
|
990
|
-
"10. If `terminal.state` is `follow_up_required`, run the surfaced `terminal.commands`, then run the surfaced `terminal.validationCommands`, and confirm the follow-up results before stopping.",
|
|
991
|
-
"11. If `terminal.state` is `manual_review_required`, run any surfaced `terminal.commands` first because they are auto-applicable, then run the surfaced `terminal.validationCommands`, explain the remaining `terminal.manualSteps`, and stop for review instead of inventing a repair.",
|
|
992
|
-
"12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
|
|
993
|
-
"</process>",
|
|
994
|
-
"",
|
|
995
|
-
"<rules>",
|
|
996
|
-
"- Do ask for explicit approval after the structured preview and before apply.",
|
|
997
|
-
"- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
|
|
998
|
-
"- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
|
|
999
|
-
"- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
|
|
1000
|
-
"- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
|
|
1001
|
-
"- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
|
|
1002
|
-
"- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
|
|
1003
|
-
"</rules>",
|
|
1004
|
-
"",
|
|
1005
|
-
].join("\n");
|
|
1006
|
-
}
|
|
1007
|
-
// --- gdh-check skill renders ---
|
|
1008
342
|
export function renderClaudeCheckCommand(pinnedVersion) {
|
|
1009
|
-
return
|
|
1010
|
-
"---",
|
|
1011
|
-
"name: gdh:check",
|
|
1012
|
-
"description: Run GDH authoring checks and explain diagnostics",
|
|
1013
|
-
"allowed-tools:",
|
|
1014
|
-
" - Read",
|
|
1015
|
-
" - Grep",
|
|
1016
|
-
" - Glob",
|
|
1017
|
-
" - Bash",
|
|
1018
|
-
"---",
|
|
1019
|
-
"<objective>",
|
|
1020
|
-
"Run GDH authoring checks and explain diagnostics in human-readable terms.",
|
|
1021
|
-
"</objective>",
|
|
1022
|
-
"",
|
|
1023
|
-
"<process>",
|
|
1024
|
-
"Follow this order:",
|
|
1025
|
-
"",
|
|
1026
|
-
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence.`,
|
|
1027
|
-
`2. Run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence.`,
|
|
1028
|
-
"3. Explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`).",
|
|
1029
|
-
"4. Surface any import-state caveats or editor-side warnings.",
|
|
1030
|
-
`5. If stale managed LSP state is suspected, use bounded GDH cleanup such as \`npx -y @skillcap/gdh@${pinnedVersion} lsp prune\` or \`npx -y @skillcap/gdh@${pinnedVersion} lsp stop\`; do not hand-manage Godot LSP processes.`,
|
|
1031
|
-
"6. If issues found, suggest concrete remediation steps.",
|
|
1032
|
-
"</process>",
|
|
1033
|
-
"",
|
|
1034
|
-
"<rules>",
|
|
1035
|
-
"- Do not fix issues automatically unless asked.",
|
|
1036
|
-
"- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
|
|
1037
|
-
"- The gdh lsp lifecycle commands are status, prune, and stop.",
|
|
1038
|
-
"- Explain diagnostics in human-readable terms.",
|
|
1039
|
-
"- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
|
|
1040
|
-
"- Report both hard failures and informational caveats.",
|
|
1041
|
-
"</rules>",
|
|
1042
|
-
"",
|
|
1043
|
-
].join("\n");
|
|
1044
|
-
}
|
|
1045
|
-
export function renderCodexCheckSkill(pinnedVersion) {
|
|
1046
|
-
return [
|
|
1047
|
-
"---",
|
|
1048
|
-
'name: "gdh-check"',
|
|
1049
|
-
'description: "Run GDH authoring checks and explain diagnostics"',
|
|
1050
|
-
"metadata:",
|
|
1051
|
-
' short-description: "Run GDH authoring checks and explain diagnostics"',
|
|
1052
|
-
"---",
|
|
1053
|
-
"",
|
|
1054
|
-
"<codex_skill_adapter>",
|
|
1055
|
-
"## Invocation",
|
|
1056
|
-
"- This skill is invoked when the user says `/gdh-check` or mentions `$gdh-check`.",
|
|
1057
|
-
"- Treat any extra user text as additional check context.",
|
|
1058
|
-
"",
|
|
1059
|
-
"## User questions",
|
|
1060
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
1061
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
1062
|
-
"</codex_skill_adapter>",
|
|
1063
|
-
"",
|
|
1064
|
-
"<objective>",
|
|
1065
|
-
"Run GDH authoring checks and explain diagnostics in human-readable terms.",
|
|
1066
|
-
"</objective>",
|
|
1067
|
-
"",
|
|
1068
|
-
"<process>",
|
|
1069
|
-
"Follow this order:",
|
|
1070
|
-
"",
|
|
1071
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence`,
|
|
1072
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence`,
|
|
1073
|
-
"- explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`)",
|
|
1074
|
-
"- surface any import-state caveats or editor-side warnings",
|
|
1075
|
-
`- if stale managed LSP state is suspected, use bounded GDH cleanup such as \`npx -y @skillcap/gdh@${pinnedVersion} lsp prune\` or \`npx -y @skillcap/gdh@${pinnedVersion} lsp stop\`; do not hand-manage Godot LSP processes`,
|
|
1076
|
-
"- if issues found, suggest concrete remediation steps",
|
|
1077
|
-
"</process>",
|
|
1078
|
-
"",
|
|
1079
|
-
"<rules>",
|
|
1080
|
-
"- Do not fix issues automatically unless asked.",
|
|
1081
|
-
"- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
|
|
1082
|
-
"- The gdh lsp lifecycle commands are status, prune, and stop.",
|
|
1083
|
-
"- Explain diagnostics in human-readable terms.",
|
|
1084
|
-
"- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
|
|
1085
|
-
"- Report both hard failures and informational caveats.",
|
|
1086
|
-
"</rules>",
|
|
1087
|
-
"",
|
|
1088
|
-
].join("\n");
|
|
343
|
+
return renderClaudeCheckSkill(pinnedVersion);
|
|
1089
344
|
}
|
|
1090
|
-
export function renderCursorCheckSkill(pinnedVersion) {
|
|
1091
|
-
return [
|
|
1092
|
-
"---",
|
|
1093
|
-
"name: gdh-check",
|
|
1094
|
-
'description: "Run GDH authoring checks and explain diagnostics"',
|
|
1095
|
-
"---",
|
|
1096
|
-
"",
|
|
1097
|
-
"<cursor_skill_adapter>",
|
|
1098
|
-
"## Invocation",
|
|
1099
|
-
"- This skill is invoked when the user says `/gdh-check` or mentions `gdh-check`.",
|
|
1100
|
-
"- Treat any extra user text as additional check context.",
|
|
1101
|
-
"",
|
|
1102
|
-
"## User questions",
|
|
1103
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
1104
|
-
"- Keep questions conversational and concise.",
|
|
1105
|
-
"</cursor_skill_adapter>",
|
|
1106
|
-
"",
|
|
1107
|
-
"<objective>",
|
|
1108
|
-
"Run GDH authoring checks and explain diagnostics in human-readable terms.",
|
|
1109
|
-
"</objective>",
|
|
1110
|
-
"",
|
|
1111
|
-
"<process>",
|
|
1112
|
-
"Follow this order:",
|
|
1113
|
-
"",
|
|
1114
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence`,
|
|
1115
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence`,
|
|
1116
|
-
"- explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`)",
|
|
1117
|
-
"- surface any import-state caveats or editor-side warnings",
|
|
1118
|
-
`- if stale managed LSP state is suspected, use bounded GDH cleanup such as \`npx -y @skillcap/gdh@${pinnedVersion} lsp prune\` or \`npx -y @skillcap/gdh@${pinnedVersion} lsp stop\`; do not hand-manage Godot LSP processes`,
|
|
1119
|
-
"- if issues found, suggest concrete remediation steps",
|
|
1120
|
-
"</process>",
|
|
1121
|
-
"",
|
|
1122
|
-
"<rules>",
|
|
1123
|
-
"- Do not fix issues automatically unless asked.",
|
|
1124
|
-
"- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
|
|
1125
|
-
"- The gdh lsp lifecycle commands are status, prune, and stop.",
|
|
1126
|
-
"- Explain diagnostics in human-readable terms.",
|
|
1127
|
-
"- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
|
|
1128
|
-
"- Report both hard failures and informational caveats.",
|
|
1129
|
-
"</rules>",
|
|
1130
|
-
"",
|
|
1131
|
-
].join("\n");
|
|
1132
|
-
}
|
|
1133
|
-
// --- gdh-prepare skill renders ---
|
|
1134
345
|
export function renderClaudePrepareCommand(pinnedVersion) {
|
|
1135
|
-
return
|
|
1136
|
-
"---",
|
|
1137
|
-
"name: gdh:prepare",
|
|
1138
|
-
"description: Prepare a Godot target for authoring or runtime work",
|
|
1139
|
-
"allowed-tools:",
|
|
1140
|
-
" - Read",
|
|
1141
|
-
" - Grep",
|
|
1142
|
-
" - Glob",
|
|
1143
|
-
" - Bash",
|
|
1144
|
-
" - AskUserQuestion",
|
|
1145
|
-
"---",
|
|
1146
|
-
"<objective>",
|
|
1147
|
-
"Prepare a Godot target for authoring or runtime work using GDH target preparation.",
|
|
1148
|
-
"</objective>",
|
|
1149
|
-
"",
|
|
1150
|
-
"<process>",
|
|
1151
|
-
"Follow this order:",
|
|
1152
|
-
"",
|
|
1153
|
-
`1. Run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions.`,
|
|
1154
|
-
"2. Explain what hydration and import refresh will do.",
|
|
1155
|
-
`3. If the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\`.`,
|
|
1156
|
-
"4. If a `--source-target` is relevant, explain when and why to use it.",
|
|
1157
|
-
`5. Verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\`.`,
|
|
1158
|
-
"</process>",
|
|
1159
|
-
"",
|
|
1160
|
-
"<rules>",
|
|
1161
|
-
"- Always show dry-run first.",
|
|
1162
|
-
"- Explain worktree hydration context.",
|
|
1163
|
-
"- Do not skip import refresh without explicit reason.",
|
|
1164
|
-
"</rules>",
|
|
1165
|
-
"",
|
|
1166
|
-
].join("\n");
|
|
1167
|
-
}
|
|
1168
|
-
export function renderCodexPrepareSkill(pinnedVersion) {
|
|
1169
|
-
return [
|
|
1170
|
-
"---",
|
|
1171
|
-
'name: "gdh-prepare"',
|
|
1172
|
-
'description: "Prepare a Godot target for authoring or runtime work"',
|
|
1173
|
-
"metadata:",
|
|
1174
|
-
' short-description: "Prepare a Godot target for authoring or runtime work"',
|
|
1175
|
-
"---",
|
|
1176
|
-
"",
|
|
1177
|
-
"<codex_skill_adapter>",
|
|
1178
|
-
"## Invocation",
|
|
1179
|
-
"- This skill is invoked when the user says `/gdh-prepare` or mentions `$gdh-prepare`.",
|
|
1180
|
-
"- Treat any extra user text as additional preparation context.",
|
|
1181
|
-
"",
|
|
1182
|
-
"## User questions",
|
|
1183
|
-
"- Ask before running preparation if the user has not explicitly approved.",
|
|
1184
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
1185
|
-
"</codex_skill_adapter>",
|
|
1186
|
-
"",
|
|
1187
|
-
"<objective>",
|
|
1188
|
-
"Prepare a Godot target for authoring or runtime work using GDH target preparation.",
|
|
1189
|
-
"</objective>",
|
|
1190
|
-
"",
|
|
1191
|
-
"<process>",
|
|
1192
|
-
"Follow this order:",
|
|
1193
|
-
"",
|
|
1194
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
1195
|
-
"- explain what hydration and import refresh will do",
|
|
1196
|
-
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
1197
|
-
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
1198
|
-
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
1199
|
-
"</process>",
|
|
1200
|
-
"",
|
|
1201
|
-
"<rules>",
|
|
1202
|
-
"- Always show dry-run first.",
|
|
1203
|
-
"- Explain worktree hydration context.",
|
|
1204
|
-
"- Do not skip import refresh without explicit reason.",
|
|
1205
|
-
"</rules>",
|
|
1206
|
-
"",
|
|
1207
|
-
].join("\n");
|
|
1208
|
-
}
|
|
1209
|
-
export function renderCursorPrepareSkill(pinnedVersion) {
|
|
1210
|
-
return [
|
|
1211
|
-
"---",
|
|
1212
|
-
"name: gdh-prepare",
|
|
1213
|
-
'description: "Prepare a Godot target for authoring or runtime work"',
|
|
1214
|
-
"---",
|
|
1215
|
-
"",
|
|
1216
|
-
"<cursor_skill_adapter>",
|
|
1217
|
-
"## Invocation",
|
|
1218
|
-
"- This skill is invoked when the user says `/gdh-prepare` or mentions `gdh-prepare`.",
|
|
1219
|
-
"- Treat any extra user text as additional preparation context.",
|
|
1220
|
-
"",
|
|
1221
|
-
"## User questions",
|
|
1222
|
-
"- Ask before running preparation if the user has not explicitly approved.",
|
|
1223
|
-
"- Keep questions conversational and concise.",
|
|
1224
|
-
"</cursor_skill_adapter>",
|
|
1225
|
-
"",
|
|
1226
|
-
"<objective>",
|
|
1227
|
-
"Prepare a Godot target for authoring or runtime work using GDH target preparation.",
|
|
1228
|
-
"</objective>",
|
|
1229
|
-
"",
|
|
1230
|
-
"<process>",
|
|
1231
|
-
"Follow this order:",
|
|
1232
|
-
"",
|
|
1233
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare --dry-run\` first to preview planned actions`,
|
|
1234
|
-
"- explain what hydration and import refresh will do",
|
|
1235
|
-
`- if the user approves, run \`npx -y @skillcap/gdh@${pinnedVersion} target prepare\``,
|
|
1236
|
-
"- if a `--source-target` is relevant, explain when and why to use it",
|
|
1237
|
-
`- verify preparation succeeded with \`npx -y @skillcap/gdh@${pinnedVersion} status\``,
|
|
1238
|
-
"</process>",
|
|
1239
|
-
"",
|
|
1240
|
-
"<rules>",
|
|
1241
|
-
"- Always show dry-run first.",
|
|
1242
|
-
"- Explain worktree hydration context.",
|
|
1243
|
-
"- Do not skip import refresh without explicit reason.",
|
|
1244
|
-
"</rules>",
|
|
1245
|
-
"",
|
|
1246
|
-
].join("\n");
|
|
1247
|
-
}
|
|
1248
|
-
// --- gdh-verify skill renders ---
|
|
1249
|
-
export function renderClaudeVerifyCommand(pinnedVersion) {
|
|
1250
|
-
return [
|
|
1251
|
-
"---",
|
|
1252
|
-
"name: gdh:verify",
|
|
1253
|
-
"description: Evaluate verification readiness and done-policy for changed files",
|
|
1254
|
-
"allowed-tools:",
|
|
1255
|
-
" - Read",
|
|
1256
|
-
" - Grep",
|
|
1257
|
-
" - Glob",
|
|
1258
|
-
" - Bash",
|
|
1259
|
-
"---",
|
|
1260
|
-
"<objective>",
|
|
1261
|
-
"Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
|
|
1262
|
-
"</objective>",
|
|
1263
|
-
"",
|
|
1264
|
-
"<process>",
|
|
1265
|
-
"Follow this order:",
|
|
1266
|
-
"",
|
|
1267
|
-
"1. Identify changed files from git diff or user input.",
|
|
1268
|
-
`2. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds.`,
|
|
1269
|
-
`3. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility.`,
|
|
1270
|
-
"4. For authoring checks, explain validator-family expectations: `gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`, and manual validation for unsupported authoring files.",
|
|
1271
|
-
"5. Summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence.",
|
|
1272
|
-
"6. Suggest specific next verification steps.",
|
|
1273
|
-
"</process>",
|
|
1274
|
-
"",
|
|
1275
|
-
"<rules>",
|
|
1276
|
-
"- Do not mark work as done if done-policy is not satisfied.",
|
|
1277
|
-
"- Surface all recommended validation kinds.",
|
|
1278
|
-
"- Keep the summary actionable.",
|
|
1279
|
-
"</rules>",
|
|
1280
|
-
"",
|
|
1281
|
-
].join("\n");
|
|
1282
|
-
}
|
|
1283
|
-
export function renderCodexVerifySkill(pinnedVersion) {
|
|
1284
|
-
return [
|
|
1285
|
-
"---",
|
|
1286
|
-
'name: "gdh-verify"',
|
|
1287
|
-
'description: "Evaluate verification readiness and done-policy for changed files"',
|
|
1288
|
-
"metadata:",
|
|
1289
|
-
' short-description: "Evaluate verification readiness and done-policy for changed files"',
|
|
1290
|
-
"---",
|
|
1291
|
-
"",
|
|
1292
|
-
"<codex_skill_adapter>",
|
|
1293
|
-
"## Invocation",
|
|
1294
|
-
"- This skill is invoked when the user says `/gdh-verify` or mentions `$gdh-verify`.",
|
|
1295
|
-
"- Treat any extra user text as additional verification context.",
|
|
1296
|
-
"",
|
|
1297
|
-
"## User questions",
|
|
1298
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
1299
|
-
"- If structured user-input tooling is unavailable, ask concise plain-text questions instead.",
|
|
1300
|
-
"</codex_skill_adapter>",
|
|
1301
|
-
"",
|
|
1302
|
-
"<objective>",
|
|
1303
|
-
"Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
|
|
1304
|
-
"</objective>",
|
|
1305
|
-
"",
|
|
1306
|
-
"<process>",
|
|
1307
|
-
"Follow this order:",
|
|
1308
|
-
"",
|
|
1309
|
-
"- identify changed files from git diff or user input",
|
|
1310
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1311
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
1312
|
-
"- for authoring checks, explain validator-family expectations: `gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`, and manual validation for unsupported authoring files",
|
|
1313
|
-
"- summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence",
|
|
1314
|
-
"- suggest specific next verification steps",
|
|
1315
|
-
"</process>",
|
|
1316
|
-
"",
|
|
1317
|
-
"<rules>",
|
|
1318
|
-
"- Do not mark work as done if done-policy is not satisfied.",
|
|
1319
|
-
"- Surface all recommended validation kinds.",
|
|
1320
|
-
"- Keep the summary actionable.",
|
|
1321
|
-
"</rules>",
|
|
1322
|
-
"",
|
|
1323
|
-
].join("\n");
|
|
1324
|
-
}
|
|
1325
|
-
export function renderCursorVerifySkill(pinnedVersion) {
|
|
1326
|
-
return [
|
|
1327
|
-
"---",
|
|
1328
|
-
"name: gdh-verify",
|
|
1329
|
-
'description: "Evaluate verification readiness and done-policy for changed files"',
|
|
1330
|
-
"---",
|
|
1331
|
-
"",
|
|
1332
|
-
"<cursor_skill_adapter>",
|
|
1333
|
-
"## Invocation",
|
|
1334
|
-
"- This skill is invoked when the user says `/gdh-verify` or mentions `gdh-verify`.",
|
|
1335
|
-
"- Treat any extra user text as additional verification context.",
|
|
1336
|
-
"",
|
|
1337
|
-
"## User questions",
|
|
1338
|
-
"- Ask only narrow follow-up questions when GDH cannot infer the missing fact safely.",
|
|
1339
|
-
"- Keep questions conversational and concise.",
|
|
1340
|
-
"</cursor_skill_adapter>",
|
|
1341
|
-
"",
|
|
1342
|
-
"<objective>",
|
|
1343
|
-
"Evaluate verification readiness and done-policy for changed files using GDH verification surfaces.",
|
|
1344
|
-
"</objective>",
|
|
1345
|
-
"",
|
|
1346
|
-
"<process>",
|
|
1347
|
-
"Follow this order:",
|
|
1348
|
-
"",
|
|
1349
|
-
"- identify changed files from git diff or user input",
|
|
1350
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
|
|
1351
|
-
`- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
|
|
1352
|
-
"- for authoring checks, explain validator-family expectations: `gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`, and manual validation for unsupported authoring files",
|
|
1353
|
-
"- summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence",
|
|
1354
|
-
"- suggest specific next verification steps",
|
|
1355
|
-
"</process>",
|
|
1356
|
-
"",
|
|
1357
|
-
"<rules>",
|
|
1358
|
-
"- Do not mark work as done if done-policy is not satisfied.",
|
|
1359
|
-
"- Surface all recommended validation kinds.",
|
|
1360
|
-
"- Keep the summary actionable.",
|
|
1361
|
-
"</rules>",
|
|
1362
|
-
"",
|
|
1363
|
-
].join("\n");
|
|
346
|
+
return renderClaudePrepareSkill(pinnedVersion);
|
|
1364
347
|
}
|
|
1365
348
|
async function inspectProjectMcpSupport(targetPath, options) {
|
|
1366
349
|
const projectConfig = await readProjectConfig(targetPath);
|
|
@@ -1588,34 +571,94 @@ function inspectCodexSkillSurface(targetPath, relativePath, content, expectedCon
|
|
|
1588
571
|
}),
|
|
1589
572
|
];
|
|
1590
573
|
}
|
|
1591
|
-
function
|
|
574
|
+
function inspectCodexAuthoringHookConfig(targetPath, content, enabled) {
|
|
575
|
+
if (!enabled) {
|
|
576
|
+
return createSurfaceStatus({
|
|
577
|
+
kind: "hook_config",
|
|
578
|
+
scope: "repo",
|
|
579
|
+
targetPath,
|
|
580
|
+
relativePath: CODEX_PROJECT_CONFIG_RELATIVE_PATH,
|
|
581
|
+
present: content !== null,
|
|
582
|
+
state: "ready",
|
|
583
|
+
summary: "Codex authoring hooks are disabled because project MCP config is disabled.",
|
|
584
|
+
version: null,
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
const ready = content !== null &&
|
|
588
|
+
/^\s*codex_hooks\s*=\s*true\s*$/m.test(content) &&
|
|
589
|
+
content.includes("# BEGIN GDH managed authoring hooks") &&
|
|
590
|
+
content.includes(CODEX_AUTHORING_HOOK_RELATIVE_PATH);
|
|
591
|
+
return createSurfaceStatus({
|
|
592
|
+
kind: "hook_config",
|
|
593
|
+
scope: "repo",
|
|
594
|
+
targetPath,
|
|
595
|
+
relativePath: CODEX_PROJECT_CONFIG_RELATIVE_PATH,
|
|
596
|
+
present: content !== null,
|
|
597
|
+
state: content === null ? "missing" : ready ? "ready" : "misconfigured",
|
|
598
|
+
summary: content === null
|
|
599
|
+
? "Codex project config is missing and should register GDH authoring hooks."
|
|
600
|
+
: ready
|
|
601
|
+
? "Codex project config enables GDH PostToolUse and Stop authoring hooks."
|
|
602
|
+
: "Codex project config exists but is missing the managed GDH authoring hook block.",
|
|
603
|
+
version: null,
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
function inspectManagedHookSurface(agent, targetPath, relativePath, content, expectedContent, hookName) {
|
|
607
|
+
if (expectedContent === null) {
|
|
608
|
+
return createSurfaceStatus({
|
|
609
|
+
kind: "hook_file",
|
|
610
|
+
scope: "repo",
|
|
611
|
+
targetPath,
|
|
612
|
+
relativePath,
|
|
613
|
+
present: content !== null,
|
|
614
|
+
state: "missing",
|
|
615
|
+
summary: `${agentLabel(agent)} ${hookName} hook cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
616
|
+
version: null,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
return createSurfaceStatus({
|
|
620
|
+
kind: "hook_file",
|
|
621
|
+
scope: "repo",
|
|
622
|
+
targetPath,
|
|
623
|
+
relativePath,
|
|
624
|
+
present: content !== null,
|
|
625
|
+
state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
|
|
626
|
+
summary: content === null
|
|
627
|
+
? `${agentLabel(agent)} ${hookName} hook file is missing.`
|
|
628
|
+
: content === expectedContent
|
|
629
|
+
? `${agentLabel(agent)} ${hookName} hook file is managed and current.`
|
|
630
|
+
: `${agentLabel(agent)} ${hookName} hook file exists but no longer matches the managed GDH hook.`,
|
|
631
|
+
version: null,
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
function inspectClaudeSkillSurface(targetPath, relativePath, content, expectedContent, skillName) {
|
|
1592
635
|
if (expectedContent === null) {
|
|
1593
636
|
return [
|
|
1594
637
|
createSurfaceStatus({
|
|
1595
|
-
kind: "
|
|
638
|
+
kind: "skill_file",
|
|
1596
639
|
scope: "repo",
|
|
1597
640
|
targetPath,
|
|
1598
641
|
relativePath,
|
|
1599
642
|
present: content !== null,
|
|
1600
643
|
state: "missing",
|
|
1601
|
-
summary: `Claude ${
|
|
644
|
+
summary: `Claude ${skillName} skill cannot be validated yet: no \`gdh_version\` is pinned (run \`gdh setup\` or \`gdh migrate --apply\`).`,
|
|
1602
645
|
version: null,
|
|
1603
646
|
}),
|
|
1604
647
|
];
|
|
1605
648
|
}
|
|
1606
649
|
return [
|
|
1607
650
|
createSurfaceStatus({
|
|
1608
|
-
kind: "
|
|
651
|
+
kind: "skill_file",
|
|
1609
652
|
scope: "repo",
|
|
1610
653
|
targetPath,
|
|
1611
654
|
relativePath,
|
|
1612
655
|
present: content !== null,
|
|
1613
656
|
state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
|
|
1614
657
|
summary: content === null
|
|
1615
|
-
? `Claude \`/${
|
|
658
|
+
? `Claude \`/${skillName}\` skill is missing and should install under .claude/skills/.`
|
|
1616
659
|
: content === expectedContent
|
|
1617
|
-
? `Claude can discover the managed \`/${
|
|
1618
|
-
: `Claude \`/${
|
|
660
|
+
? `Claude can discover the managed \`/${skillName}\` skill.`
|
|
661
|
+
: `Claude \`/${skillName}\` skill exists but no longer matches the expected managed GDH skill.`,
|
|
1619
662
|
version: null,
|
|
1620
663
|
}),
|
|
1621
664
|
];
|
|
@@ -1674,20 +717,29 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersi
|
|
|
1674
717
|
const codexPrepareContent = await fs
|
|
1675
718
|
.readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8")
|
|
1676
719
|
.catch(() => null);
|
|
1677
|
-
const codexVerifyContent = await fs
|
|
1678
|
-
.readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8")
|
|
1679
|
-
.catch(() => null);
|
|
1680
720
|
const codexScanContent = await fs
|
|
1681
721
|
.readFile(path.join(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH), "utf8")
|
|
1682
722
|
.catch(() => null);
|
|
723
|
+
const codexAuthoringHookContent = await fs
|
|
724
|
+
.readFile(path.join(projectMcp.integrationRootPath, CODEX_AUTHORING_HOOK_RELATIVE_PATH), "utf8")
|
|
725
|
+
.catch(() => null);
|
|
726
|
+
const codexProjectConfigContent = await fs
|
|
727
|
+
.readFile(path.join(projectMcp.integrationRootPath, CODEX_PROJECT_CONFIG_RELATIVE_PATH), "utf8")
|
|
728
|
+
.catch(() => null);
|
|
1683
729
|
const expectedCodexOnboardSkill = pinnedVersion === null ? null : renderCodexOnboardSkill(pinnedVersion);
|
|
1684
730
|
const expectedCodexStatusSkill = pinnedVersion === null ? null : renderCodexStatusSkill(pinnedVersion);
|
|
1685
731
|
const expectedCodexMigrateSkill = pinnedVersion === null ? null : renderCodexMigrateSkill(pinnedVersion);
|
|
1686
732
|
const expectedCodexUpdateSkill = pinnedVersion === null ? null : renderCodexUpdateSkill(pinnedVersion);
|
|
1687
733
|
const expectedCodexCheckSkill = pinnedVersion === null ? null : renderCodexCheckSkill(pinnedVersion);
|
|
1688
734
|
const expectedCodexPrepareSkill = pinnedVersion === null ? null : renderCodexPrepareSkill(pinnedVersion);
|
|
1689
|
-
const expectedCodexVerifySkill = pinnedVersion === null ? null : renderCodexVerifySkill(pinnedVersion);
|
|
1690
735
|
const expectedCodexScanSkill = pinnedVersion === null ? null : renderCodexScanSkill(pinnedVersion);
|
|
736
|
+
const expectedCodexAuthoringHook = pinnedVersion === null
|
|
737
|
+
? null
|
|
738
|
+
: renderGdhAuthoringHook({
|
|
739
|
+
pinnedVersion,
|
|
740
|
+
targetRelativePath: path.relative(projectMcp.integrationRootPath, targetPath) || ".",
|
|
741
|
+
agent: "codex",
|
|
742
|
+
});
|
|
1691
743
|
const surfaces = [
|
|
1692
744
|
createSurfaceStatus({
|
|
1693
745
|
kind: "canonical_entrypoint",
|
|
@@ -1734,8 +786,9 @@ async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersi
|
|
|
1734
786
|
...inspectCodexSkillSurface(targetPath, CODEX_UPDATE_SKILL_RELATIVE_PATH, codexUpdateContent, expectedCodexUpdateSkill, "gdh-update"),
|
|
1735
787
|
...inspectCodexSkillSurface(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH, codexCheckContent, expectedCodexCheckSkill, "gdh-check"),
|
|
1736
788
|
...inspectCodexSkillSurface(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH, codexPrepareContent, expectedCodexPrepareSkill, "gdh-prepare"),
|
|
1737
|
-
...inspectCodexSkillSurface(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH, codexVerifyContent, expectedCodexVerifySkill, "gdh-verify"),
|
|
1738
789
|
...inspectCodexSkillSurface(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH, codexScanContent, expectedCodexScanSkill, "gdh-scan"),
|
|
790
|
+
inspectManagedHookSurface("codex", projectMcp.integrationRootPath, CODEX_AUTHORING_HOOK_RELATIVE_PATH, codexAuthoringHookContent, expectedCodexAuthoringHook, "authoring guard"),
|
|
791
|
+
inspectCodexAuthoringHookConfig(projectMcp.integrationRootPath, codexProjectConfigContent, projectMcp.enabled),
|
|
1739
792
|
];
|
|
1740
793
|
if (projectMcp.enabled) {
|
|
1741
794
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1775,7 +828,7 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1775
828
|
const claudeMigrateContent = await fs
|
|
1776
829
|
.readFile(path.join(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH), "utf8")
|
|
1777
830
|
.catch(() => null);
|
|
1778
|
-
// Phase 13 Plan 13-03 deliverable — /gdh-update
|
|
831
|
+
// Phase 13 Plan 13-03 deliverable — /gdh-update skill for Claude.
|
|
1779
832
|
// Inspection wiring is required so planSkillInstallAction can see the surface
|
|
1780
833
|
// state; otherwise the planner returns `unchanged` for a missing file and
|
|
1781
834
|
// install becomes a no-op (Plan 13-05 integration-test Rule 2 fix).
|
|
@@ -1788,9 +841,6 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1788
841
|
const claudePrepareContent = await fs
|
|
1789
842
|
.readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8")
|
|
1790
843
|
.catch(() => null);
|
|
1791
|
-
const claudeVerifyContent = await fs
|
|
1792
|
-
.readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8")
|
|
1793
|
-
.catch(() => null);
|
|
1794
844
|
const claudeScanContent = await fs
|
|
1795
845
|
.readFile(path.join(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH), "utf8")
|
|
1796
846
|
.catch(() => null);
|
|
@@ -1803,6 +853,9 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1803
853
|
const claudeStatuslineContent = await fs
|
|
1804
854
|
.readFile(path.join(targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH), "utf8")
|
|
1805
855
|
.catch(() => null);
|
|
856
|
+
const claudeAuthoringHookContent = await fs
|
|
857
|
+
.readFile(path.join(targetPath, CLAUDE_AUTHORING_HOOK_RELATIVE_PATH), "utf8")
|
|
858
|
+
.catch(() => null);
|
|
1806
859
|
let detectedTarget = null;
|
|
1807
860
|
if (lstat?.isSymbolicLink()) {
|
|
1808
861
|
detectedTarget = await fs.readlink(absolutePath).catch(() => null);
|
|
@@ -1811,12 +864,18 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1811
864
|
const expectedClaudeCheckUpdateHook = pinnedVersion === null ? null : renderClaudeCheckUpdateHook(pinnedVersion);
|
|
1812
865
|
const expectedClaudeCheckUpdateWorker = pinnedVersion === null ? null : renderClaudeCheckUpdateWorker(pinnedVersion);
|
|
1813
866
|
const expectedClaudeStatusline = pinnedVersion === null ? null : renderClaudeUpdateStatusline(pinnedVersion);
|
|
867
|
+
const expectedClaudeAuthoringHook = pinnedVersion === null
|
|
868
|
+
? null
|
|
869
|
+
: renderGdhAuthoringHook({
|
|
870
|
+
pinnedVersion,
|
|
871
|
+
targetRelativePath: ".",
|
|
872
|
+
agent: "claude",
|
|
873
|
+
});
|
|
1814
874
|
const expectedClaudeStatusCommand = pinnedVersion === null ? null : renderClaudeStatusCommand(pinnedVersion);
|
|
1815
875
|
const expectedClaudeMigrateCommand = pinnedVersion === null ? null : renderClaudeMigrateCommand(pinnedVersion);
|
|
1816
876
|
const expectedClaudeUpdateCommand = pinnedVersion === null ? null : renderClaudeUpdateCommand(pinnedVersion);
|
|
1817
877
|
const expectedClaudeCheckCommand = pinnedVersion === null ? null : renderClaudeCheckCommand(pinnedVersion);
|
|
1818
878
|
const expectedClaudePrepareCommand = pinnedVersion === null ? null : renderClaudePrepareCommand(pinnedVersion);
|
|
1819
|
-
const expectedClaudeVerifyCommand = pinnedVersion === null ? null : renderClaudeVerifyCommand(pinnedVersion);
|
|
1820
879
|
const expectedClaudeScanCommand = pinnedVersion === null ? null : renderClaudeScanCommand(pinnedVersion);
|
|
1821
880
|
const surfaces = [
|
|
1822
881
|
createSurfaceStatus({
|
|
@@ -1840,7 +899,7 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1840
899
|
detectedTarget,
|
|
1841
900
|
}),
|
|
1842
901
|
createSurfaceStatus({
|
|
1843
|
-
kind: "
|
|
902
|
+
kind: "skill_file",
|
|
1844
903
|
scope: "repo",
|
|
1845
904
|
targetPath,
|
|
1846
905
|
relativePath: CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH,
|
|
@@ -1853,24 +912,24 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1853
912
|
? "ready"
|
|
1854
913
|
: "misconfigured",
|
|
1855
914
|
summary: onboardCommandContent === null
|
|
1856
|
-
? "Claude onboarding handoff is missing and should install `/gdh-onboard` under .claude/
|
|
915
|
+
? "Claude onboarding handoff is missing and should install `/gdh-onboard` under .claude/skills/."
|
|
1857
916
|
: expectedClaudeOnboardCommand === null
|
|
1858
917
|
? "Claude onboarding handoff cannot be validated yet: no `gdh_version` is pinned (run `gdh setup` or `gdh migrate --apply`)."
|
|
1859
918
|
: onboardCommandContent === expectedClaudeOnboardCommand
|
|
1860
|
-
? "Claude can discover the managed `/gdh-onboard` handoff
|
|
1861
|
-
: "Claude onboarding handoff exists but no longer matches the expected managed GDH
|
|
919
|
+
? "Claude can discover the managed `/gdh-onboard` handoff skill."
|
|
920
|
+
: "Claude onboarding handoff exists but no longer matches the expected managed GDH skill.",
|
|
1862
921
|
version: null,
|
|
1863
922
|
}),
|
|
1864
|
-
...
|
|
1865
|
-
...
|
|
1866
|
-
...
|
|
1867
|
-
...
|
|
1868
|
-
...
|
|
1869
|
-
...
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
923
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, claudeStatusContent, expectedClaudeStatusCommand, "gdh-status"),
|
|
924
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, claudeMigrateContent, expectedClaudeMigrateCommand, "gdh-migrate"),
|
|
925
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_UPDATE_COMMAND_RELATIVE_PATH, claudeUpdateContent, expectedClaudeUpdateCommand, "gdh-update"),
|
|
926
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, claudeCheckContent, expectedClaudeCheckCommand, "gdh-check"),
|
|
927
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, claudePrepareContent, expectedClaudePrepareCommand, "gdh-prepare"),
|
|
928
|
+
...inspectClaudeSkillSurface(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH, claudeScanContent, expectedClaudeScanCommand, "gdh-scan"),
|
|
929
|
+
inspectManagedHookSurface("claude", targetPath, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, claudeCheckUpdateHookContent, expectedClaudeCheckUpdateHook, "gdh-check-update-hook"),
|
|
930
|
+
inspectManagedHookSurface("claude", targetPath, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, claudeCheckUpdateWorkerContent, expectedClaudeCheckUpdateWorker, "gdh-check-update-worker"),
|
|
931
|
+
inspectManagedHookSurface("claude", targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH, claudeStatuslineContent, expectedClaudeStatusline, "gdh-statusline"),
|
|
932
|
+
inspectManagedHookSurface("claude", targetPath, CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, claudeAuthoringHookContent, expectedClaudeAuthoringHook, "authoring guard"),
|
|
1874
933
|
];
|
|
1875
934
|
if (projectMcp.enabled) {
|
|
1876
935
|
surfaces.push(createSurfaceStatus({
|
|
@@ -1912,9 +971,6 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1912
971
|
const cursorPrepareContent = await fs
|
|
1913
972
|
.readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8")
|
|
1914
973
|
.catch(() => null);
|
|
1915
|
-
const cursorVerifyContent = await fs
|
|
1916
|
-
.readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8")
|
|
1917
|
-
.catch(() => null);
|
|
1918
974
|
const cursorScanContent = await fs
|
|
1919
975
|
.readFile(path.join(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH), "utf8")
|
|
1920
976
|
.catch(() => null);
|
|
@@ -1926,7 +982,6 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1926
982
|
const expectedCursorUpdateSkill = pinnedVersion === null ? null : renderCursorUpdateSkill(pinnedVersion);
|
|
1927
983
|
const expectedCursorCheckSkill = pinnedVersion === null ? null : renderCursorCheckSkill(pinnedVersion);
|
|
1928
984
|
const expectedCursorPrepareSkill = pinnedVersion === null ? null : renderCursorPrepareSkill(pinnedVersion);
|
|
1929
|
-
const expectedCursorVerifySkill = pinnedVersion === null ? null : renderCursorVerifySkill(pinnedVersion);
|
|
1930
985
|
const expectedCursorScanSkill = pinnedVersion === null ? null : renderCursorScanSkill(pinnedVersion);
|
|
1931
986
|
const surfaces = [
|
|
1932
987
|
createSurfaceStatus({
|
|
@@ -1970,7 +1025,6 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVers
|
|
|
1970
1025
|
...inspectCursorSkillSurface(targetPath, CURSOR_UPDATE_SKILL_RELATIVE_PATH, cursorUpdateContent, expectedCursorUpdateSkill, "gdh-update"),
|
|
1971
1026
|
...inspectCursorSkillSurface(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH, cursorCheckContent, expectedCursorCheckSkill, "gdh-check"),
|
|
1972
1027
|
...inspectCursorSkillSurface(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH, cursorPrepareContent, expectedCursorPrepareSkill, "gdh-prepare"),
|
|
1973
|
-
...inspectCursorSkillSurface(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH, cursorVerifyContent, expectedCursorVerifySkill, "gdh-verify"),
|
|
1974
1028
|
...inspectCursorSkillSurface(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH, cursorScanContent, expectedCursorScanSkill, "gdh-scan"),
|
|
1975
1029
|
];
|
|
1976
1030
|
if (projectMcp.enabled) {
|
|
@@ -2079,6 +1133,7 @@ async function planInstallActions(targetPath, adapters, requestedAgents, options
|
|
|
2079
1133
|
actions.push(...planCursorInstallActions(targetPath, adapter, options.pinnedVersion));
|
|
2080
1134
|
}
|
|
2081
1135
|
}
|
|
1136
|
+
actions.push(...planRetiredVerifySurfaceCleanupActions(targetPath));
|
|
2082
1137
|
return dedupeInstallActions(actions);
|
|
2083
1138
|
}
|
|
2084
1139
|
function planSharedRepoInstallActions(targetPath, projectMcp, agent, effectiveDevRepoPath, integrationRootPath, pinnedVersion) {
|
|
@@ -2155,7 +1210,7 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
2155
1210
|
relativePath,
|
|
2156
1211
|
state: "unchanged",
|
|
2157
1212
|
mode: "unchanged",
|
|
2158
|
-
summary: `The managed ${agentLabel(agent)} \`/${skillName}\`
|
|
1213
|
+
summary: `The managed ${agentLabel(agent)} \`/${skillName}\` skill already matches the expected GDH content.`,
|
|
2159
1214
|
content: renderFn(pinnedVersion),
|
|
2160
1215
|
});
|
|
2161
1216
|
}
|
|
@@ -2168,8 +1223,37 @@ function planSkillInstallAction(agent, targetPath, adapter, relativePath, render
|
|
|
2168
1223
|
state: "planned",
|
|
2169
1224
|
mode: surface.present ? "replace" : "create",
|
|
2170
1225
|
summary: surface.present
|
|
2171
|
-
? `Replace the existing ${agentLabel(agent)} \`/${skillName}\`
|
|
2172
|
-
: `Create the managed ${agentLabel(agent)} \`/${skillName}\`
|
|
1226
|
+
? `Replace the existing ${agentLabel(agent)} \`/${skillName}\` skill with the managed GDH skill.`
|
|
1227
|
+
: `Create the managed ${agentLabel(agent)} \`/${skillName}\` skill.`,
|
|
1228
|
+
content: renderFn(pinnedVersion),
|
|
1229
|
+
});
|
|
1230
|
+
}
|
|
1231
|
+
function planHookInstallAction(agent, targetPath, adapter, relativePath, renderFn, hookName, pinnedVersion) {
|
|
1232
|
+
const surface = adapter.surfaces.find((entry) => entry.relativePath === relativePath);
|
|
1233
|
+
if (!surface || surface.state === "ready") {
|
|
1234
|
+
return createInstallAction({
|
|
1235
|
+
agent,
|
|
1236
|
+
kind: "write_file",
|
|
1237
|
+
scope: "repo",
|
|
1238
|
+
targetPath,
|
|
1239
|
+
relativePath,
|
|
1240
|
+
state: "unchanged",
|
|
1241
|
+
mode: "unchanged",
|
|
1242
|
+
summary: `${agentLabel(agent)} ${hookName} hook already matches the managed GDH hook.`,
|
|
1243
|
+
content: renderFn(pinnedVersion),
|
|
1244
|
+
});
|
|
1245
|
+
}
|
|
1246
|
+
return createInstallAction({
|
|
1247
|
+
agent,
|
|
1248
|
+
kind: "write_file",
|
|
1249
|
+
scope: "repo",
|
|
1250
|
+
targetPath,
|
|
1251
|
+
relativePath,
|
|
1252
|
+
state: "planned",
|
|
1253
|
+
mode: surface.present ? "replace" : "create",
|
|
1254
|
+
summary: surface.present
|
|
1255
|
+
? `Replace the existing ${agentLabel(agent)} ${hookName} hook with the managed GDH hook.`
|
|
1256
|
+
: `Create the managed ${agentLabel(agent)} ${hookName} hook.`,
|
|
2173
1257
|
content: renderFn(pinnedVersion),
|
|
2174
1258
|
});
|
|
2175
1259
|
}
|
|
@@ -2191,8 +1275,12 @@ function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion, project
|
|
|
2191
1275
|
planSkillInstallAction("codex", targetPath, adapter, CODEX_UPDATE_SKILL_RELATIVE_PATH, renderCodexUpdateSkill, "gdh-update", pinnedVersion),
|
|
2192
1276
|
planSkillInstallAction("codex", targetPath, adapter, CODEX_CHECK_SKILL_RELATIVE_PATH, renderCodexCheckSkill, "gdh-check", pinnedVersion),
|
|
2193
1277
|
planSkillInstallAction("codex", targetPath, adapter, CODEX_PREPARE_SKILL_RELATIVE_PATH, renderCodexPrepareSkill, "gdh-prepare", pinnedVersion),
|
|
2194
|
-
planSkillInstallAction("codex", targetPath, adapter, CODEX_VERIFY_SKILL_RELATIVE_PATH, renderCodexVerifySkill, "gdh-verify", pinnedVersion),
|
|
2195
1278
|
planSkillInstallAction("codex", targetPath, adapter, CODEX_SCAN_SKILL_RELATIVE_PATH, renderCodexScanSkill, "gdh-scan", pinnedVersion),
|
|
1279
|
+
planSkillInstallAction("codex", integrationRootPath, adapter, CODEX_AUTHORING_HOOK_RELATIVE_PATH, (version) => renderGdhAuthoringHook({
|
|
1280
|
+
pinnedVersion: version,
|
|
1281
|
+
targetRelativePath: path.relative(integrationRootPath, targetPath) || ".",
|
|
1282
|
+
agent: "codex",
|
|
1283
|
+
}), "authoring guard", pinnedVersion),
|
|
2196
1284
|
];
|
|
2197
1285
|
if (projectMcp.enabled && projectMcp.codexProjectFile.state !== "ready") {
|
|
2198
1286
|
const absolutePath = path.join(integrationRootPath, CODEX_PROJECT_CONFIG_RELATIVE_PATH);
|
|
@@ -2216,19 +1304,77 @@ function planCodexRepoInstallActions(targetPath, adapter, pinnedVersion, project
|
|
|
2216
1304
|
actions.push(...planLegacyCodexSkillCleanupActions(targetPath, pinnedVersion));
|
|
2217
1305
|
return actions;
|
|
2218
1306
|
}
|
|
2219
|
-
//
|
|
2220
|
-
//
|
|
2221
|
-
//
|
|
2222
|
-
//
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
1307
|
+
// Current skill renders use a neutral Markdown-safe GDH_MANAGED_AGENT_SKILL
|
|
1308
|
+
// marker. Legacy renders used provider-specific XML-ish marker blocks. Cleanup
|
|
1309
|
+
// accepts both so old managed files can migrate without deleting user-authored
|
|
1310
|
+
// files based only on path.
|
|
1311
|
+
const LEGACY_CODEX_MANAGED_SKILL_MARKER = "<codex_skill_adapter>";
|
|
1312
|
+
const LEGACY_CURSOR_MANAGED_SKILL_MARKER = "<cursor_skill_adapter>";
|
|
1313
|
+
function isManagedAgentSkillContent(content) {
|
|
1314
|
+
return (content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1315
|
+
content.includes(LEGACY_CODEX_MANAGED_SKILL_MARKER) ||
|
|
1316
|
+
content.includes(LEGACY_CURSOR_MANAGED_SKILL_MARKER));
|
|
1317
|
+
}
|
|
2226
1318
|
function isManagedLegacyCodexSkillContent(content) {
|
|
2227
|
-
return content.includes(
|
|
1319
|
+
return (content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1320
|
+
content.includes(LEGACY_CODEX_MANAGED_SKILL_MARKER));
|
|
1321
|
+
}
|
|
1322
|
+
function isManagedLegacyClaudeCommandContent(content, skillName) {
|
|
1323
|
+
const slashName = skillName.replace("gdh-", "gdh:");
|
|
1324
|
+
return (content.includes(`name: ${slashName}`) &&
|
|
1325
|
+
(content.includes("@skillcap/gdh@") ||
|
|
1326
|
+
content.includes(GDH_MANAGED_AGENT_SKILL_MARKER) ||
|
|
1327
|
+
content.includes("<objective>") ||
|
|
1328
|
+
content.includes("<process>") ||
|
|
1329
|
+
content.includes("<rules>")));
|
|
1330
|
+
}
|
|
1331
|
+
const RETIRED_VERIFY_SURFACE_RELATIVE_PATHS = [
|
|
1332
|
+
{
|
|
1333
|
+
agent: "codex",
|
|
1334
|
+
relativePath: ".agents/skills/gdh-verify/SKILL.md",
|
|
1335
|
+
skillName: "gdh-verify",
|
|
1336
|
+
isManaged: isManagedAgentSkillContent,
|
|
1337
|
+
},
|
|
1338
|
+
{
|
|
1339
|
+
agent: "cursor",
|
|
1340
|
+
relativePath: ".cursor/skills/gdh-verify/SKILL.md",
|
|
1341
|
+
skillName: "gdh-verify",
|
|
1342
|
+
isManaged: isManagedAgentSkillContent,
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
agent: "claude",
|
|
1346
|
+
relativePath: ".claude/commands/gdh/verify.md",
|
|
1347
|
+
skillName: "gdh-verify",
|
|
1348
|
+
isManaged: (content) => content.includes("name: gdh:verify") &&
|
|
1349
|
+
(content.includes("@skillcap/gdh@") || content.includes("gdh verify recommend")),
|
|
1350
|
+
},
|
|
1351
|
+
];
|
|
1352
|
+
function planRetiredVerifySurfaceCleanupActions(targetPath) {
|
|
1353
|
+
const actions = [];
|
|
1354
|
+
for (const entry of RETIRED_VERIFY_SURFACE_RELATIVE_PATHS) {
|
|
1355
|
+
const absolutePath = path.join(targetPath, entry.relativePath);
|
|
1356
|
+
const content = fsSync.existsSync(absolutePath)
|
|
1357
|
+
? fsSync.readFileSync(absolutePath, "utf8")
|
|
1358
|
+
: null;
|
|
1359
|
+
if (content === null || !entry.isManaged(content)) {
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
actions.push(createInstallAction({
|
|
1363
|
+
agent: entry.agent,
|
|
1364
|
+
kind: "remove_file",
|
|
1365
|
+
scope: "repo",
|
|
1366
|
+
targetPath,
|
|
1367
|
+
relativePath: entry.relativePath,
|
|
1368
|
+
state: "planned",
|
|
1369
|
+
mode: "delete",
|
|
1370
|
+
summary: `Remove retired managed \`/${entry.skillName}\` surface. Agents should use \`/gdh-check\` for code-validity evidence.`,
|
|
1371
|
+
}));
|
|
1372
|
+
}
|
|
1373
|
+
return actions;
|
|
2228
1374
|
}
|
|
2229
1375
|
function planLegacyCodexSkillCleanupActions(targetPath, _pinnedVersion) {
|
|
2230
1376
|
const actions = [];
|
|
2231
|
-
for (const [relativePath,
|
|
1377
|
+
for (const [relativePath, skillName] of LEGACY_CODEX_SKILL_RELATIVE_PATHS) {
|
|
2232
1378
|
const absolutePath = path.join(targetPath, relativePath);
|
|
2233
1379
|
const content = fsSync.existsSync(absolutePath)
|
|
2234
1380
|
? fsSync.readFileSync(absolutePath, "utf8")
|
|
@@ -2255,6 +1401,29 @@ function planLegacyCodexSkillCleanupActions(targetPath, _pinnedVersion) {
|
|
|
2255
1401
|
}
|
|
2256
1402
|
return actions;
|
|
2257
1403
|
}
|
|
1404
|
+
function planLegacyClaudeCommandCleanupActions(targetPath) {
|
|
1405
|
+
const actions = [];
|
|
1406
|
+
for (const [relativePath, skillName] of LEGACY_CLAUDE_SKILL_COMMAND_RELATIVE_PATHS) {
|
|
1407
|
+
const absolutePath = path.join(targetPath, relativePath);
|
|
1408
|
+
const content = fsSync.existsSync(absolutePath)
|
|
1409
|
+
? fsSync.readFileSync(absolutePath, "utf8")
|
|
1410
|
+
: null;
|
|
1411
|
+
if (content === null || !isManagedLegacyClaudeCommandContent(content, skillName)) {
|
|
1412
|
+
continue;
|
|
1413
|
+
}
|
|
1414
|
+
actions.push(createInstallAction({
|
|
1415
|
+
agent: "claude",
|
|
1416
|
+
kind: "remove_file",
|
|
1417
|
+
scope: "repo",
|
|
1418
|
+
targetPath,
|
|
1419
|
+
relativePath,
|
|
1420
|
+
state: "planned",
|
|
1421
|
+
mode: "delete",
|
|
1422
|
+
summary: `Remove legacy managed Claude \`/${skillName}\` command after installing the provider-recommended .claude/skills surface.`,
|
|
1423
|
+
}));
|
|
1424
|
+
}
|
|
1425
|
+
return actions;
|
|
1426
|
+
}
|
|
2258
1427
|
function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath, pinnedVersion) {
|
|
2259
1428
|
if (!projectMcp.enabled || projectMcp.codexServerName === null) {
|
|
2260
1429
|
return [];
|
|
@@ -2333,14 +1502,18 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
|
|
|
2333
1502
|
expectedTarget: "AGENTS.md",
|
|
2334
1503
|
}));
|
|
2335
1504
|
}
|
|
2336
|
-
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,
|
|
1505
|
+
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_SCAN_COMMAND_RELATIVE_PATH, renderClaudeScanCommand, "gdh-scan", pinnedVersion),
|
|
2337
1506
|
// UPD-01 managed hook surfaces baked at the pinned version.
|
|
2338
|
-
|
|
1507
|
+
planHookInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, renderClaudeCheckUpdateHook, "gdh-check-update-hook", pinnedVersion), planHookInstallAction("claude", targetPath, adapter, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateWorker, "gdh-check-update-worker", pinnedVersion),
|
|
2339
1508
|
// UPD-02 managed statusline surface baked at the pinned version. The .js
|
|
2340
1509
|
// file is ALWAYS baked, even when settings.json statusLine is not owned
|
|
2341
1510
|
// by GDH (write-if-absent below) — users can manually point their config
|
|
2342
1511
|
// at gdh-statusline.js later; the baked file is a no-op until wired.
|
|
2343
|
-
|
|
1512
|
+
planHookInstallAction("claude", targetPath, adapter, CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, "gdh-statusline", pinnedVersion), planHookInstallAction("claude", targetPath, adapter, CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, (version) => renderGdhAuthoringHook({
|
|
1513
|
+
pinnedVersion: version,
|
|
1514
|
+
targetRelativePath: ".",
|
|
1515
|
+
agent: "claude",
|
|
1516
|
+
}), "authoring guard", pinnedVersion));
|
|
2344
1517
|
// UPD-01 + UPD-02 .claude/settings.json composite patch action.
|
|
2345
1518
|
// - Plan 02 (Strategy A, planner-lock #1): patch-merge the SessionStart
|
|
2346
1519
|
// hook entry by exact command-literal match, preserving siblings.
|
|
@@ -2360,7 +1533,7 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
|
|
|
2360
1533
|
catch {
|
|
2361
1534
|
existingSettingsContent = "";
|
|
2362
1535
|
}
|
|
2363
|
-
const patchedSettings = patchClaudeSettingsForGdhStatusline(patchClaudeSettingsForGdhSessionStart(existingSettingsContent));
|
|
1536
|
+
const patchedSettings = patchClaudeSettingsForGdhStatusline(patchClaudeSettingsForGdhAuthoringHooks(patchClaudeSettingsForGdhSessionStart(existingSettingsContent)));
|
|
2364
1537
|
const settingsIsUnchanged = existingSettingsContent === patchedSettings;
|
|
2365
1538
|
const settingsExistedOnDisk = existingSettingsContent.length > 0;
|
|
2366
1539
|
actions.push(createInstallAction({
|
|
@@ -2372,12 +1545,13 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
|
|
|
2372
1545
|
state: settingsIsUnchanged ? "unchanged" : "planned",
|
|
2373
1546
|
mode: settingsIsUnchanged ? "unchanged" : settingsExistedOnDisk ? "replace" : "create",
|
|
2374
1547
|
summary: settingsIsUnchanged
|
|
2375
|
-
? "GDH SessionStart hook
|
|
1548
|
+
? "GDH SessionStart hook, authoring guard hooks, and statusline already registered in .claude/settings.json."
|
|
2376
1549
|
: settingsExistedOnDisk
|
|
2377
|
-
? "Register the GDH SessionStart hook and statusline (write-if-absent) in .claude/settings.json while preserving sibling content (patch-merge)."
|
|
2378
|
-
: "Create .claude/settings.json with the GDH SessionStart hook
|
|
1550
|
+
? "Register the GDH SessionStart hook, authoring guard hooks, and statusline (write-if-absent) in .claude/settings.json while preserving sibling content (patch-merge)."
|
|
1551
|
+
: "Create .claude/settings.json with the GDH SessionStart hook, authoring guard hooks, and statusline registration.",
|
|
2379
1552
|
content: patchedSettings,
|
|
2380
1553
|
}));
|
|
1554
|
+
actions.push(...planLegacyClaudeCommandCleanupActions(targetPath));
|
|
2381
1555
|
return actions;
|
|
2382
1556
|
}
|
|
2383
1557
|
function planCursorInstallActions(targetPath, adapter, pinnedVersion) {
|
|
@@ -2413,7 +1587,7 @@ function planCursorInstallActions(targetPath, adapter, pinnedVersion) {
|
|
|
2413
1587
|
content: renderCursorRule(),
|
|
2414
1588
|
}));
|
|
2415
1589
|
}
|
|
2416
|
-
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,
|
|
1590
|
+
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_SCAN_SKILL_RELATIVE_PATH, renderCursorScanSkill, "gdh-scan", pinnedVersion));
|
|
2417
1591
|
return actions;
|
|
2418
1592
|
}
|
|
2419
1593
|
function dedupeInstallActions(actions) {
|
|
@@ -2578,19 +1752,23 @@ export function renderManagedCodexProjectSection(pinnedVersion) {
|
|
|
2578
1752
|
}
|
|
2579
1753
|
export function renderManagedCodexProjectConfig(existingContent, pinnedVersion) {
|
|
2580
1754
|
const section = renderManagedCodexProjectSection(pinnedVersion);
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
1755
|
+
const withoutManagedHooks = removeManagedCodexAuthoringHookBlock(existingContent ?? "");
|
|
1756
|
+
const withFeature = ensureCodexHooksFeature(withoutManagedHooks);
|
|
1757
|
+
const withMcp = patchManagedCodexProjectSection(withFeature, section);
|
|
1758
|
+
return appendManagedCodexAuthoringHookBlock(withMcp);
|
|
1759
|
+
}
|
|
1760
|
+
function patchManagedCodexProjectSection(content, section) {
|
|
1761
|
+
const lines = content.split("\n");
|
|
2585
1762
|
const sectionStart = lines.findIndex((line) => /^\[mcp_servers\.gdh\]\s*$/.test(line));
|
|
2586
1763
|
if (sectionStart === -1) {
|
|
2587
|
-
const trailingNewline =
|
|
2588
|
-
const separator =
|
|
2589
|
-
return `${
|
|
1764
|
+
const trailingNewline = content.endsWith("\n") ? "" : "\n";
|
|
1765
|
+
const separator = content.length > 0 ? "\n" : "";
|
|
1766
|
+
return `${content}${trailingNewline}${separator}${section}\n`;
|
|
2590
1767
|
}
|
|
2591
1768
|
let sectionEnd = lines.length;
|
|
2592
1769
|
for (let i = sectionStart + 1; i < lines.length; i++) {
|
|
2593
|
-
if (/^\[/.test(lines[i] ?? "")
|
|
1770
|
+
if (/^\[/.test(lines[i] ?? "") ||
|
|
1771
|
+
/^# BEGIN GDH managed authoring hooks$/.test(lines[i] ?? "")) {
|
|
2594
1772
|
sectionEnd = i;
|
|
2595
1773
|
break;
|
|
2596
1774
|
}
|
|
@@ -2603,6 +1781,62 @@ export function renderManagedCodexProjectConfig(existingContent, pinnedVersion)
|
|
|
2603
1781
|
const afterJoin = afterNonEmpty.length > 0 ? `\n\n${afterNonEmpty}` : "\n";
|
|
2604
1782
|
return `${beforeJoin}${section}${afterJoin}`;
|
|
2605
1783
|
}
|
|
1784
|
+
function removeManagedCodexAuthoringHookBlock(content) {
|
|
1785
|
+
return content
|
|
1786
|
+
.replace(/(?:^|\n)# BEGIN GDH managed authoring hooks\n[\s\S]*?# END GDH managed authoring hooks\n?/, "\n")
|
|
1787
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
1788
|
+
.trimEnd();
|
|
1789
|
+
}
|
|
1790
|
+
function appendManagedCodexAuthoringHookBlock(content) {
|
|
1791
|
+
const normalized = content.trimEnd();
|
|
1792
|
+
const separator = normalized.length > 0 ? "\n\n" : "";
|
|
1793
|
+
return `${normalized}${separator}${renderManagedCodexAuthoringHookBlock()}`;
|
|
1794
|
+
}
|
|
1795
|
+
function ensureCodexHooksFeature(content) {
|
|
1796
|
+
const lines = content.split("\n");
|
|
1797
|
+
const featuresStart = lines.findIndex((line) => /^\[features\]\s*$/.test(line));
|
|
1798
|
+
if (featuresStart === -1) {
|
|
1799
|
+
const separator = content.trim().length > 0 ? "\n\n" : "";
|
|
1800
|
+
return `${content}${separator}[features]\ncodex_hooks = true`;
|
|
1801
|
+
}
|
|
1802
|
+
let featuresEnd = lines.length;
|
|
1803
|
+
for (let i = featuresStart + 1; i < lines.length; i++) {
|
|
1804
|
+
if (/^\[/.test(lines[i] ?? "")) {
|
|
1805
|
+
featuresEnd = i;
|
|
1806
|
+
break;
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
const featureLines = lines.slice(featuresStart, featuresEnd);
|
|
1810
|
+
const codexHooksIndex = featureLines.findIndex((line) => /^\s*codex_hooks\s*=/.test(line));
|
|
1811
|
+
if (codexHooksIndex === -1) {
|
|
1812
|
+
featureLines.push("codex_hooks = true");
|
|
1813
|
+
}
|
|
1814
|
+
else {
|
|
1815
|
+
featureLines[codexHooksIndex] = "codex_hooks = true";
|
|
1816
|
+
}
|
|
1817
|
+
return [...lines.slice(0, featuresStart), ...featureLines, ...lines.slice(featuresEnd)].join("\n");
|
|
1818
|
+
}
|
|
1819
|
+
function renderManagedCodexAuthoringHookBlock() {
|
|
1820
|
+
return [
|
|
1821
|
+
"# BEGIN GDH managed authoring hooks",
|
|
1822
|
+
"[[hooks.PostToolUse]]",
|
|
1823
|
+
'matcher = "apply_patch|Edit|Write"',
|
|
1824
|
+
"[[hooks.PostToolUse.hooks]]",
|
|
1825
|
+
'type = "command"',
|
|
1826
|
+
`command = ${JSON.stringify(CODEX_AUTHORING_HOOK_COMMAND)}`,
|
|
1827
|
+
"timeout = 30",
|
|
1828
|
+
'statusMessage = "Checking GDH authoring edit"',
|
|
1829
|
+
"",
|
|
1830
|
+
"[[hooks.Stop]]",
|
|
1831
|
+
"[[hooks.Stop.hooks]]",
|
|
1832
|
+
'type = "command"',
|
|
1833
|
+
`command = ${JSON.stringify(CODEX_AUTHORING_HOOK_COMMAND)}`,
|
|
1834
|
+
"timeout = 120",
|
|
1835
|
+
'statusMessage = "Checking GDH final authoring validation"',
|
|
1836
|
+
"# END GDH managed authoring hooks",
|
|
1837
|
+
"",
|
|
1838
|
+
].join("\n");
|
|
1839
|
+
}
|
|
2606
1840
|
function extractManagedCodexSection(content) {
|
|
2607
1841
|
const lines = content.split("\n");
|
|
2608
1842
|
const start = lines.findIndex((line) => /^\[mcp_servers\.gdh\]\s*$/.test(line));
|
|
@@ -2611,7 +1845,8 @@ function extractManagedCodexSection(content) {
|
|
|
2611
1845
|
}
|
|
2612
1846
|
let end = lines.length;
|
|
2613
1847
|
for (let i = start + 1; i < lines.length; i++) {
|
|
2614
|
-
if (/^\[/.test(lines[i] ?? "")
|
|
1848
|
+
if (/^\[/.test(lines[i] ?? "") ||
|
|
1849
|
+
/^# BEGIN GDH managed authoring hooks$/.test(lines[i] ?? "")) {
|
|
2615
1850
|
end = i;
|
|
2616
1851
|
break;
|
|
2617
1852
|
}
|
|
@@ -2888,7 +2123,7 @@ async function inspectRulesLifecycleSurface(targetPath, projectConfig) {
|
|
|
2888
2123
|
surface: "rules_schema",
|
|
2889
2124
|
management: "project_owned",
|
|
2890
2125
|
state: "migration_needed",
|
|
2891
|
-
summary: "Rules are missing from .gdh/rules.yaml, so
|
|
2126
|
+
summary: "Rules are missing from .gdh/rules.yaml, so guidance enforcement is incomplete.",
|
|
2892
2127
|
reasons: ["rules_missing"],
|
|
2893
2128
|
probes,
|
|
2894
2129
|
action: {
|
|
@@ -3771,6 +3006,7 @@ function normalizeChangedFiles(files) {
|
|
|
3771
3006
|
}
|
|
3772
3007
|
export { CLAUDE_STATUSLINE_RELATIVE_PATH } from "./claude-statusline-render.js";
|
|
3773
3008
|
export { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH } from "./claude-update-hook-render.js";
|
|
3009
|
+
export { CLAUDE_AUTHORING_HOOK_COMMAND, CLAUDE_AUTHORING_HOOK_RELATIVE_PATH, CODEX_AUTHORING_HOOK_COMMAND, CODEX_AUTHORING_HOOK_RELATIVE_PATH, } from "./authoring-hook-render.js";
|
|
3774
3010
|
export { bumpAndRebakePin, } from "./self-update-mechanics.js";
|
|
3775
3011
|
// Internal aggregator exposed for Wave 0 unit tests
|
|
3776
3012
|
// (packages/adapters/src/lifecycle-compatibility.test.ts). Callers outside this
|