@skillcap/gdh 0.16.0 → 0.17.1

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.
Files changed (56) hide show
  1. package/INSTALL-BUNDLE.json +1 -1
  2. package/RELEASE-SPAN-UPDATE-CONTRACTS.json +145 -0
  3. package/node_modules/@gdh/adapters/dist/index.d.ts +2 -2
  4. package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
  5. package/node_modules/@gdh/adapters/dist/index.js +164 -125
  6. package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
  7. package/node_modules/@gdh/adapters/package.json +8 -8
  8. package/node_modules/@gdh/authoring/dist/index.d.ts +4 -3
  9. package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
  10. package/node_modules/@gdh/authoring/dist/index.js +80 -9
  11. package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
  12. package/node_modules/@gdh/authoring/dist/lsp-client.d.ts +47 -0
  13. package/node_modules/@gdh/authoring/dist/lsp-client.d.ts.map +1 -0
  14. package/node_modules/@gdh/authoring/dist/lsp-client.js +371 -0
  15. package/node_modules/@gdh/authoring/dist/lsp-client.js.map +1 -0
  16. package/node_modules/@gdh/authoring/dist/lsp-test-server.test-utils.d.ts +35 -0
  17. package/node_modules/@gdh/authoring/dist/lsp-test-server.test-utils.d.ts.map +1 -0
  18. package/node_modules/@gdh/authoring/dist/lsp-test-server.test-utils.js +194 -0
  19. package/node_modules/@gdh/authoring/dist/lsp-test-server.test-utils.js.map +1 -0
  20. package/node_modules/@gdh/authoring/dist/lsp.d.ts +62 -1
  21. package/node_modules/@gdh/authoring/dist/lsp.d.ts.map +1 -1
  22. package/node_modules/@gdh/authoring/dist/lsp.js +1278 -112
  23. package/node_modules/@gdh/authoring/dist/lsp.js.map +1 -1
  24. package/node_modules/@gdh/authoring/dist/scene-resource.d.ts +39 -0
  25. package/node_modules/@gdh/authoring/dist/scene-resource.d.ts.map +1 -0
  26. package/node_modules/@gdh/authoring/dist/scene-resource.js +544 -0
  27. package/node_modules/@gdh/authoring/dist/scene-resource.js.map +1 -0
  28. package/node_modules/@gdh/authoring/package.json +2 -2
  29. package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
  30. package/node_modules/@gdh/cli/dist/index.js +116 -18
  31. package/node_modules/@gdh/cli/dist/index.js.map +1 -1
  32. package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
  33. package/node_modules/@gdh/cli/dist/migrate.js +12 -5
  34. package/node_modules/@gdh/cli/dist/migrate.js.map +1 -1
  35. package/node_modules/@gdh/cli/package.json +10 -10
  36. package/node_modules/@gdh/core/dist/index.d.ts +48 -13
  37. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  38. package/node_modules/@gdh/core/dist/index.js +14 -17
  39. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  40. package/node_modules/@gdh/core/package.json +1 -1
  41. package/node_modules/@gdh/docs/dist/guidance.d.ts.map +1 -1
  42. package/node_modules/@gdh/docs/dist/guidance.js +12 -2
  43. package/node_modules/@gdh/docs/dist/guidance.js.map +1 -1
  44. package/node_modules/@gdh/docs/dist/rules.d.ts.map +1 -1
  45. package/node_modules/@gdh/docs/dist/rules.js +2 -2
  46. package/node_modules/@gdh/docs/dist/rules.js.map +1 -1
  47. package/node_modules/@gdh/docs/package.json +2 -2
  48. package/node_modules/@gdh/mcp/package.json +8 -8
  49. package/node_modules/@gdh/observability/package.json +2 -2
  50. package/node_modules/@gdh/runtime/package.json +2 -2
  51. package/node_modules/@gdh/scan/package.json +3 -3
  52. package/node_modules/@gdh/verify/dist/policy.d.ts.map +1 -1
  53. package/node_modules/@gdh/verify/dist/policy.js +157 -29
  54. package/node_modules/@gdh/verify/dist/policy.js.map +1 -1
  55. package/node_modules/@gdh/verify/package.json +7 -7
  56. package/package.json +11 -11
@@ -4,17 +4,17 @@ import fs from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { promisify } from "node:util";
7
- import { readProjectConfig, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, } from "@gdh/authoring";
8
- import { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateHook, } from "./claude-update-hook-render.js";
9
- import { renderClaudeCheckUpdateWorker } from "./claude-update-worker-render.js";
10
- import { CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, } from "./claude-statusline-render.js";
11
- import { CLAUDE_SETTINGS_RELATIVE_PATH, patchClaudeSettingsForGdhSessionStart, patchClaudeSettingsForGdhStatusline, } from "./claude-settings-patch.js";
12
- import { GDH_AGENT_CONTRACT_VERSION, GDH_CURSOR_RULE_VERSION, GDH_GUIDANCE_INDEX_VERSION, GDH_GUIDANCE_UNIT_VERSION, GDH_PROJECT_CONFIG_VERSION, GDH_RECIPE_SCHEMA_VERSION, GDH_RULES_SCHEMA_VERSION, GDH_SCENARIO_SCHEMA_VERSION, assertProjectLifecycleCompatibilityInvariant, definePackageBoundary, resolveCurrentGdhInstall, resolveConfiguredGodotEditorBin, resolveGdhProductMetadata, } from "@gdh/core";
7
+ import { readProjectConfig, readWorktreeState, resolveAuthoringStatus, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, } from "@gdh/authoring";
8
+ import { assertProjectLifecycleCompatibilityInvariant, definePackageBoundary, GDH_AGENT_CONTRACT_VERSION, GDH_CURSOR_RULE_VERSION, GDH_GUIDANCE_INDEX_VERSION, GDH_GUIDANCE_UNIT_VERSION, GDH_PROJECT_CONFIG_VERSION, GDH_RECIPE_SCHEMA_VERSION, GDH_RULES_SCHEMA_VERSION, GDH_SCENARIO_SCHEMA_VERSION, resolveConfiguredGodotEditorBin, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
13
9
  import { createDefaultGuidanceUnits, getGuidanceStatus, resolveGuidanceQuery, resolveRecoveryHints, } from "@gdh/docs";
14
10
  import { inspectGuidanceAudit } from "@gdh/observability";
15
- import { inspectRuntimeBridgeSurface, inspectRuntimeKnowledgeSurface, } from "@gdh/runtime";
11
+ import { inspectRuntimeBridgeSurface, inspectRuntimeKnowledgeSurface } from "@gdh/runtime";
16
12
  import { readInventoryCacheOrScan } from "@gdh/scan";
17
13
  import { evaluateDonePolicy, recommendValidationForChange } from "@gdh/verify";
14
+ import { CLAUDE_SETTINGS_RELATIVE_PATH, patchClaudeSettingsForGdhSessionStart, patchClaudeSettingsForGdhStatusline, } from "./claude-settings-patch.js";
15
+ import { CLAUDE_STATUSLINE_RELATIVE_PATH, renderClaudeUpdateStatusline, } from "./claude-statusline-render.js";
16
+ import { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH, renderClaudeCheckUpdateHook, } from "./claude-update-hook-render.js";
17
+ import { renderClaudeCheckUpdateWorker } from "./claude-update-worker-render.js";
18
18
  export const adaptersPackage = definePackageBoundary({
19
19
  name: "@gdh/adapters",
20
20
  layer: "integration",
@@ -29,7 +29,11 @@ export const adaptersPackage = definePackageBoundary({
29
29
  "@gdh/verify",
30
30
  ],
31
31
  });
32
- export const SUPPORTED_AGENTS = ["codex", "claude", "cursor"];
32
+ export const SUPPORTED_AGENTS = [
33
+ "codex",
34
+ "claude",
35
+ "cursor",
36
+ ];
33
37
  export const CLAUDE_SHIM_RELATIVE_PATH = "CLAUDE.md";
34
38
  export const CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH = ".claude/commands/gdh/onboard.md";
35
39
  export const PROJECT_MCP_RELATIVE_PATH = ".mcp.json";
@@ -199,9 +203,7 @@ export async function inspectProjectLifecycleCompatibility(targetPath) {
199
203
  autoApplicable: false,
200
204
  },
201
205
  });
202
- return summarizeProjectLifecycleCompatibility(resolvedTargetPath, [
203
- blockedSurface,
204
- ]);
206
+ return summarizeProjectLifecycleCompatibility(resolvedTargetPath, [blockedSurface]);
205
207
  }
206
208
  const guidanceStatus = await getGuidanceStatus(resolvedTargetPath);
207
209
  const bridgeStatus = await inspectRuntimeBridgeSurface({
@@ -721,12 +723,12 @@ export function renderClaudeMigrateCommand(pinnedVersion) {
721
723
  "",
722
724
  `1. Run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`).`,
723
725
  "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.",
724
- "3. Explain what each migration step will change and why (use \"would\" verb forms — \"would delete\", \"would create\", \"would refresh\").",
726
+ '3. Explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh").',
725
727
  `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").`,
726
728
  "5. After apply, read `terminal.state` in the stdout JSON.",
727
729
  "6. If `terminal.state` is `healthy`, confirm no further migration action is required and stop.",
728
730
  "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.",
729
- "8. If `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of improvising a repair.",
731
+ "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.",
730
732
  "9. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
731
733
  "</process>",
732
734
  "",
@@ -766,12 +768,12 @@ export function renderCodexMigrateSkill(pinnedVersion) {
766
768
  "",
767
769
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`)`,
768
770
  "- 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",
769
- "- explain what each migration step will change and why (use \"would\" verb forms — \"would delete\", \"would create\", \"would refresh\")",
771
+ '- explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh")',
770
772
  `- 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")`,
771
773
  "- after apply, read `terminal.state` in the stdout JSON",
772
774
  "- if `terminal.state` is `healthy`, confirm no further migration action is required and stop",
773
775
  "- 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",
774
- "- if `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of improvising a repair",
776
+ "- 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",
775
777
  "- if `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop",
776
778
  "</process>",
777
779
  "",
@@ -809,12 +811,12 @@ export function renderCursorMigrateSkill(pinnedVersion) {
809
811
  "",
810
812
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} migrate\` to preview pending migrations (this is a dry-run; the JSON \`mode\` field will be \`"preview"\`)`,
811
813
  "- 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",
812
- "- explain what each migration step will change and why (use \"would\" verb forms — \"would delete\", \"would create\", \"would refresh\")",
814
+ '- explain what each migration step will change and why (use "would" verb forms — "would delete", "would create", "would refresh")',
813
815
  `- 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")`,
814
816
  "- after apply, read `terminal.state` in the stdout JSON",
815
817
  "- if `terminal.state` is `healthy`, confirm no further migration action is required and stop",
816
818
  "- 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",
817
- "- if `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of improvising a repair",
819
+ "- 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",
818
820
  "- if `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop",
819
821
  "</process>",
820
822
  "",
@@ -878,7 +880,7 @@ export function renderClaudeUpdateCommand(_pinnedVersion) {
878
880
  "8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
879
881
  "9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
880
882
  "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.",
881
- "11. If `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of inventing a repair.",
883
+ "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.",
882
884
  "12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
883
885
  "</process>",
884
886
  "",
@@ -886,6 +888,7 @@ export function renderClaudeUpdateCommand(_pinnedVersion) {
886
888
  "- Do ask for explicit approval after the structured preview and before apply.",
887
889
  "- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
888
890
  "- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
891
+ "- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
889
892
  "- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
890
893
  "- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
891
894
  "- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
@@ -925,7 +928,7 @@ export function renderCodexUpdateSkill(_pinnedVersion) {
925
928
  "8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
926
929
  "9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
927
930
  "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.",
928
- "11. If `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of inventing a repair.",
931
+ "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.",
929
932
  "12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
930
933
  "</process>",
931
934
  "",
@@ -933,6 +936,7 @@ export function renderCodexUpdateSkill(_pinnedVersion) {
933
936
  "- Do ask for explicit approval after the structured preview and before apply.",
934
937
  "- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
935
938
  "- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
939
+ "- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
936
940
  "- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
937
941
  "- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
938
942
  "- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
@@ -970,7 +974,7 @@ export function renderCursorUpdateSkill(_pinnedVersion) {
970
974
  "8. Read `terminal.state` in the apply stdout JSON and treat it as the lifecycle/runtime truth.",
971
975
  "9. If `terminal.state` is `healthy`, confirm the update completed and stop.",
972
976
  "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.",
973
- "11. If `terminal.state` is `manual_review_required`, explain the surfaced `terminal.manualSteps`, name the surfaced `terminal.validationCommands`, and stop for review instead of inventing a repair.",
977
+ "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.",
974
978
  "12. If `terminal.state` is `blocked`, surface `terminal.summary` plus the reasons and stop.",
975
979
  "</process>",
976
980
  "",
@@ -978,6 +982,7 @@ export function renderCursorUpdateSkill(_pinnedVersion) {
978
982
  "- Do ask for explicit approval after the structured preview and before apply.",
979
983
  "- Do not invent migration steps from prose docs; use the machine-readable `preview` payload.",
980
984
  "- Do treat `terminal.state` as the primary apply truth; the additive compatibility fields are not the main follow-through contract.",
985
+ "- `terminal.commands` contains only GDH-classified auto-applicable follow-up; project-owned review stays in `terminal.manualSteps`.",
981
986
  "- Bake literal `@latest` in the shellout so the new CLI performs the update, not the old one.",
982
987
  "- If `self-update` returns `rolled_back` or `blocked`, surface the failure reason and stop (do not retry).",
983
988
  "- If `self-update` returns `skipped_dev_mode`, explain that dev-from-source mode bypasses pinning; no action needed.",
@@ -1004,15 +1009,20 @@ export function renderClaudeCheckCommand(pinnedVersion) {
1004
1009
  "<process>",
1005
1010
  "Follow this order:",
1006
1011
  "",
1007
- `1. Run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\`.`,
1008
- "2. Explain each diagnostic finding with severity and provenance.",
1009
- "3. Surface any import-state caveats or editor-side warnings.",
1010
- "4. If issues found, suggest concrete remediation steps.",
1012
+ `1. Run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence.`,
1013
+ `2. Run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence.`,
1014
+ "3. Explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`).",
1015
+ "4. Surface any import-state caveats or editor-side warnings.",
1016
+ `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.`,
1017
+ "6. If issues found, suggest concrete remediation steps.",
1011
1018
  "</process>",
1012
1019
  "",
1013
1020
  "<rules>",
1014
1021
  "- Do not fix issues automatically unless asked.",
1022
+ "- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
1023
+ "- The gdh lsp lifecycle commands are status, prune, and stop.",
1015
1024
  "- Explain diagnostics in human-readable terms.",
1025
+ "- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
1016
1026
  "- Report both hard failures and informational caveats.",
1017
1027
  "</rules>",
1018
1028
  "",
@@ -1044,15 +1054,20 @@ export function renderCodexCheckSkill(pinnedVersion) {
1044
1054
  "<process>",
1045
1055
  "Follow this order:",
1046
1056
  "",
1047
- `- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
1048
- "- explain each diagnostic finding with severity and provenance",
1057
+ `- run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence`,
1058
+ `- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence`,
1059
+ "- explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`)",
1049
1060
  "- surface any import-state caveats or editor-side warnings",
1061
+ `- 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`,
1050
1062
  "- if issues found, suggest concrete remediation steps",
1051
1063
  "</process>",
1052
1064
  "",
1053
1065
  "<rules>",
1054
1066
  "- Do not fix issues automatically unless asked.",
1067
+ "- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
1068
+ "- The gdh lsp lifecycle commands are status, prune, and stop.",
1055
1069
  "- Explain diagnostics in human-readable terms.",
1070
+ "- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
1056
1071
  "- Report both hard failures and informational caveats.",
1057
1072
  "</rules>",
1058
1073
  "",
@@ -1082,15 +1097,20 @@ export function renderCursorCheckSkill(pinnedVersion) {
1082
1097
  "<process>",
1083
1098
  "Follow this order:",
1084
1099
  "",
1085
- `- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\``,
1086
- "- explain each diagnostic finding with severity and provenance",
1100
+ `- run \`npx -y @skillcap/gdh@${pinnedVersion} lsp status\` only for lifecycle visibility; do not treat lifecycle readiness as diagnostic evidence`,
1101
+ `- run \`npx -y @skillcap/gdh@${pinnedVersion} authoring check\` to collect validator evidence`,
1102
+ "- explain each diagnostic finding with severity, provenance, and validator family (`gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`)",
1087
1103
  "- surface any import-state caveats or editor-side warnings",
1104
+ `- 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`,
1088
1105
  "- if issues found, suggest concrete remediation steps",
1089
1106
  "</process>",
1090
1107
  "",
1091
1108
  "<rules>",
1092
1109
  "- Do not fix issues automatically unless asked.",
1110
+ "- Do not hand-manage Godot LSP processes; use GDH lifecycle commands.",
1111
+ "- The gdh lsp lifecycle commands are status, prune, and stop.",
1093
1112
  "- Explain diagnostics in human-readable terms.",
1113
+ "- A ready `authoring.lsp` lifecycle is not proof that the authoring check collected diagnostics.",
1094
1114
  "- Report both hard failures and informational caveats.",
1095
1115
  "</rules>",
1096
1116
  "",
@@ -1233,8 +1253,9 @@ export function renderClaudeVerifyCommand(pinnedVersion) {
1233
1253
  "1. Identify changed files from git diff or user input.",
1234
1254
  `2. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds.`,
1235
1255
  `3. Run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility.`,
1236
- "4. Summarize gaps between recommended and performed validation.",
1237
- "5. Suggest specific next verification steps.",
1256
+ "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.",
1257
+ "5. Summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence.",
1258
+ "6. Suggest specific next verification steps.",
1238
1259
  "</process>",
1239
1260
  "",
1240
1261
  "<rules>",
@@ -1274,7 +1295,8 @@ export function renderCodexVerifySkill(pinnedVersion) {
1274
1295
  "- identify changed files from git diff or user input",
1275
1296
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
1276
1297
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
1277
- "- summarize gaps between recommended and performed validation",
1298
+ "- for authoring checks, explain validator-family expectations: `gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`, and manual validation for unsupported authoring files",
1299
+ "- summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence",
1278
1300
  "- suggest specific next verification steps",
1279
1301
  "</process>",
1280
1302
  "",
@@ -1313,7 +1335,8 @@ export function renderCursorVerifySkill(pinnedVersion) {
1313
1335
  "- identify changed files from git diff or user input",
1314
1336
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} verify recommend\` with those files to get recommended validation kinds`,
1315
1337
  `- run \`npx -y @skillcap/gdh@${pinnedVersion} verify done\` with performed validations to check done eligibility`,
1316
- "- summarize gaps between recommended and performed validation",
1338
+ "- for authoring checks, explain validator-family expectations: `gdscript_lsp` for `.gd`, `godot_scene_resource` for `.tscn`/`.tres`, and manual validation for unsupported authoring files",
1339
+ "- summarize gaps between recommended and performed validation, including unavailable/degraded authoring evidence",
1317
1340
  "- suggest specific next verification steps",
1318
1341
  "</process>",
1319
1342
  "",
@@ -1334,7 +1357,9 @@ async function inspectProjectMcpSupport(targetPath, options) {
1334
1357
  const [projectFile, cursorFile, codexProjectContent, localPathHints] = await Promise.all([
1335
1358
  inspectJsonFile(path.join(options.integrationRootPath, PROJECT_MCP_RELATIVE_PATH)),
1336
1359
  inspectJsonFile(path.join(options.integrationRootPath, CURSOR_MCP_RELATIVE_PATH)),
1337
- fs.readFile(path.join(options.integrationRootPath, CODEX_PROJECT_CONFIG_RELATIVE_PATH), "utf8").catch(() => null),
1360
+ fs
1361
+ .readFile(path.join(options.integrationRootPath, CODEX_PROJECT_CONFIG_RELATIVE_PATH), "utf8")
1362
+ .catch(() => null),
1338
1363
  readLocalPathHints(options.integrationRootPath),
1339
1364
  ]);
1340
1365
  const codexConfigPath = path.join(os.homedir(), ".codex/config.toml");
@@ -1539,11 +1564,7 @@ function inspectCodexSkillSurface(targetPath, relativePath, content, expectedCon
1539
1564
  targetPath,
1540
1565
  relativePath,
1541
1566
  present: content !== null,
1542
- state: content === null
1543
- ? "missing"
1544
- : content === expectedContent
1545
- ? "ready"
1546
- : "misconfigured",
1567
+ state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
1547
1568
  summary: content === null
1548
1569
  ? `Codex \`/${skillName}\` skill is missing and should install under .codex/skills/.`
1549
1570
  : content === expectedContent
@@ -1575,11 +1596,7 @@ function inspectClaudeCommandSurface(targetPath, relativePath, content, expected
1575
1596
  targetPath,
1576
1597
  relativePath,
1577
1598
  present: content !== null,
1578
- state: content === null
1579
- ? "missing"
1580
- : content === expectedContent
1581
- ? "ready"
1582
- : "misconfigured",
1599
+ state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
1583
1600
  summary: content === null
1584
1601
  ? `Claude \`/${commandName}\` command is missing and should install under .claude/commands/gdh/.`
1585
1602
  : content === expectedContent
@@ -1611,11 +1628,7 @@ function inspectCursorSkillSurface(targetPath, relativePath, content, expectedCo
1611
1628
  targetPath,
1612
1629
  relativePath,
1613
1630
  present: content !== null,
1614
- state: content === null
1615
- ? "missing"
1616
- : content === expectedContent
1617
- ? "ready"
1618
- : "misconfigured",
1631
+ state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
1619
1632
  summary: content === null
1620
1633
  ? `Cursor \`/${skillName}\` skill is missing and should install under .cursor/skills/.`
1621
1634
  : content === expectedContent
@@ -1628,17 +1641,31 @@ function inspectCursorSkillSurface(targetPath, relativePath, content, expectedCo
1628
1641
  async function inspectCodexAdapter(targetPath, guidance, projectMcp, pinnedVersion, options) {
1629
1642
  const codexSkillPath = path.join(targetPath, CODEX_ONBOARD_SKILL_RELATIVE_PATH);
1630
1643
  const codexSkillContent = await fs.readFile(codexSkillPath, "utf8").catch(() => null);
1631
- const codexStatusContent = await fs.readFile(path.join(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1632
- const codexMigrateContent = await fs.readFile(path.join(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1644
+ const codexStatusContent = await fs
1645
+ .readFile(path.join(targetPath, CODEX_STATUS_SKILL_RELATIVE_PATH), "utf8")
1646
+ .catch(() => null);
1647
+ const codexMigrateContent = await fs
1648
+ .readFile(path.join(targetPath, CODEX_MIGRATE_SKILL_RELATIVE_PATH), "utf8")
1649
+ .catch(() => null);
1633
1650
  // Phase 13 Plan 13-03 deliverable — /gdh-update skill for Codex. Inspection
1634
1651
  // wiring is required so planSkillInstallAction can see the surface state;
1635
1652
  // otherwise the planner returns `unchanged` for a missing file and install
1636
1653
  // becomes a no-op (Plan 13-05 integration-test Rule 2 fix).
1637
- const codexUpdateContent = await fs.readFile(path.join(targetPath, CODEX_UPDATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1638
- const codexCheckContent = await fs.readFile(path.join(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1639
- const codexPrepareContent = await fs.readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1640
- const codexVerifyContent = await fs.readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1641
- const codexScanContent = await fs.readFile(path.join(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1654
+ const codexUpdateContent = await fs
1655
+ .readFile(path.join(targetPath, CODEX_UPDATE_SKILL_RELATIVE_PATH), "utf8")
1656
+ .catch(() => null);
1657
+ const codexCheckContent = await fs
1658
+ .readFile(path.join(targetPath, CODEX_CHECK_SKILL_RELATIVE_PATH), "utf8")
1659
+ .catch(() => null);
1660
+ const codexPrepareContent = await fs
1661
+ .readFile(path.join(targetPath, CODEX_PREPARE_SKILL_RELATIVE_PATH), "utf8")
1662
+ .catch(() => null);
1663
+ const codexVerifyContent = await fs
1664
+ .readFile(path.join(targetPath, CODEX_VERIFY_SKILL_RELATIVE_PATH), "utf8")
1665
+ .catch(() => null);
1666
+ const codexScanContent = await fs
1667
+ .readFile(path.join(targetPath, CODEX_SCAN_SKILL_RELATIVE_PATH), "utf8")
1668
+ .catch(() => null);
1642
1669
  const expectedCodexOnboardSkill = pinnedVersion === null ? null : renderCodexOnboardSkill(pinnedVersion);
1643
1670
  const expectedCodexStatusSkill = pinnedVersion === null ? null : renderCodexStatusSkill(pinnedVersion);
1644
1671
  const expectedCodexMigrateSkill = pinnedVersion === null ? null : renderCodexMigrateSkill(pinnedVersion);
@@ -1728,20 +1755,40 @@ async function inspectClaudeAdapter(targetPath, guidance, projectMcp, pinnedVers
1728
1755
  const onboardCommandPath = path.join(targetPath, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH);
1729
1756
  const lstat = await fs.lstat(absolutePath).catch(() => null);
1730
1757
  const onboardCommandContent = await fs.readFile(onboardCommandPath, "utf8").catch(() => null);
1731
- const claudeStatusContent = await fs.readFile(path.join(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1732
- const claudeMigrateContent = await fs.readFile(path.join(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1758
+ const claudeStatusContent = await fs
1759
+ .readFile(path.join(targetPath, CLAUDE_STATUS_COMMAND_RELATIVE_PATH), "utf8")
1760
+ .catch(() => null);
1761
+ const claudeMigrateContent = await fs
1762
+ .readFile(path.join(targetPath, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH), "utf8")
1763
+ .catch(() => null);
1733
1764
  // Phase 13 Plan 13-03 deliverable — /gdh-update slash command for Claude.
1734
1765
  // Inspection wiring is required so planSkillInstallAction can see the surface
1735
1766
  // state; otherwise the planner returns `unchanged` for a missing file and
1736
1767
  // install becomes a no-op (Plan 13-05 integration-test Rule 2 fix).
1737
- const claudeUpdateContent = await fs.readFile(path.join(targetPath, CLAUDE_UPDATE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1738
- const claudeCheckContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1739
- const claudePrepareContent = await fs.readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1740
- const claudeVerifyContent = await fs.readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1741
- const claudeScanContent = await fs.readFile(path.join(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH), "utf8").catch(() => null);
1742
- const claudeCheckUpdateHookContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH), "utf8").catch(() => null);
1743
- const claudeCheckUpdateWorkerContent = await fs.readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH), "utf8").catch(() => null);
1744
- const claudeStatuslineContent = await fs.readFile(path.join(targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH), "utf8").catch(() => null);
1768
+ const claudeUpdateContent = await fs
1769
+ .readFile(path.join(targetPath, CLAUDE_UPDATE_COMMAND_RELATIVE_PATH), "utf8")
1770
+ .catch(() => null);
1771
+ const claudeCheckContent = await fs
1772
+ .readFile(path.join(targetPath, CLAUDE_CHECK_COMMAND_RELATIVE_PATH), "utf8")
1773
+ .catch(() => null);
1774
+ const claudePrepareContent = await fs
1775
+ .readFile(path.join(targetPath, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH), "utf8")
1776
+ .catch(() => null);
1777
+ const claudeVerifyContent = await fs
1778
+ .readFile(path.join(targetPath, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH), "utf8")
1779
+ .catch(() => null);
1780
+ const claudeScanContent = await fs
1781
+ .readFile(path.join(targetPath, CLAUDE_SCAN_COMMAND_RELATIVE_PATH), "utf8")
1782
+ .catch(() => null);
1783
+ const claudeCheckUpdateHookContent = await fs
1784
+ .readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH), "utf8")
1785
+ .catch(() => null);
1786
+ const claudeCheckUpdateWorkerContent = await fs
1787
+ .readFile(path.join(targetPath, CLAUDE_CHECK_UPDATE_WORKER_RELATIVE_PATH), "utf8")
1788
+ .catch(() => null);
1789
+ const claudeStatuslineContent = await fs
1790
+ .readFile(path.join(targetPath, CLAUDE_STATUSLINE_RELATIVE_PATH), "utf8")
1791
+ .catch(() => null);
1745
1792
  let detectedTarget = null;
1746
1793
  if (lstat?.isSymbolicLink()) {
1747
1794
  detectedTarget = await fs.readlink(absolutePath).catch(() => null);
@@ -1832,17 +1879,31 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVers
1832
1879
  const onboardSkillPath = path.join(targetPath, CURSOR_ONBOARD_SKILL_RELATIVE_PATH);
1833
1880
  const content = await fs.readFile(absolutePath, "utf8").catch(() => null);
1834
1881
  const onboardSkillContent = await fs.readFile(onboardSkillPath, "utf8").catch(() => null);
1835
- const cursorStatusContent = await fs.readFile(path.join(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1836
- const cursorMigrateContent = await fs.readFile(path.join(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1882
+ const cursorStatusContent = await fs
1883
+ .readFile(path.join(targetPath, CURSOR_STATUS_SKILL_RELATIVE_PATH), "utf8")
1884
+ .catch(() => null);
1885
+ const cursorMigrateContent = await fs
1886
+ .readFile(path.join(targetPath, CURSOR_MIGRATE_SKILL_RELATIVE_PATH), "utf8")
1887
+ .catch(() => null);
1837
1888
  // Phase 13 Plan 13-03 deliverable — /gdh-update skill for Cursor. Inspection
1838
1889
  // wiring required so planSkillInstallAction sees the surface state; otherwise
1839
1890
  // the planner returns `unchanged` for a missing file and install becomes a
1840
1891
  // no-op (Plan 13-05 integration-test Rule 2 fix).
1841
- const cursorUpdateContent = await fs.readFile(path.join(targetPath, CURSOR_UPDATE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1842
- const cursorCheckContent = await fs.readFile(path.join(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1843
- const cursorPrepareContent = await fs.readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1844
- const cursorVerifyContent = await fs.readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1845
- const cursorScanContent = await fs.readFile(path.join(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH), "utf8").catch(() => null);
1892
+ const cursorUpdateContent = await fs
1893
+ .readFile(path.join(targetPath, CURSOR_UPDATE_SKILL_RELATIVE_PATH), "utf8")
1894
+ .catch(() => null);
1895
+ const cursorCheckContent = await fs
1896
+ .readFile(path.join(targetPath, CURSOR_CHECK_SKILL_RELATIVE_PATH), "utf8")
1897
+ .catch(() => null);
1898
+ const cursorPrepareContent = await fs
1899
+ .readFile(path.join(targetPath, CURSOR_PREPARE_SKILL_RELATIVE_PATH), "utf8")
1900
+ .catch(() => null);
1901
+ const cursorVerifyContent = await fs
1902
+ .readFile(path.join(targetPath, CURSOR_VERIFY_SKILL_RELATIVE_PATH), "utf8")
1903
+ .catch(() => null);
1904
+ const cursorScanContent = await fs
1905
+ .readFile(path.join(targetPath, CURSOR_SCAN_SKILL_RELATIVE_PATH), "utf8")
1906
+ .catch(() => null);
1846
1907
  const expectedContent = renderCursorRule();
1847
1908
  const version = readCursorRuleVersion(content);
1848
1909
  const expectedCursorOnboardSkill = pinnedVersion === null ? null : renderCursorOnboardSkill(pinnedVersion);
@@ -1860,11 +1921,7 @@ async function inspectCursorAdapter(targetPath, guidance, projectMcp, pinnedVers
1860
1921
  targetPath,
1861
1922
  relativePath: CURSOR_RULE_RELATIVE_PATH,
1862
1923
  present: content !== null,
1863
- state: content === null
1864
- ? "missing"
1865
- : content === expectedContent
1866
- ? "ready"
1867
- : "misconfigured",
1924
+ state: content === null ? "missing" : content === expectedContent ? "ready" : "misconfigured",
1868
1925
  summary: content === null
1869
1926
  ? "Cursor reinforcement is missing and should point back to AGENTS.md."
1870
1927
  : content === expectedContent
@@ -2150,12 +2207,7 @@ function planCodexUserInstallActions(targetPath, projectMcp, integrationRootPath
2150
2207
  }
2151
2208
  const resolvedTargetPath = path.resolve(targetPath);
2152
2209
  const resolvedIntegrationRootPath = path.resolve(integrationRootPath);
2153
- const codexCommandArgs = [
2154
- "-y",
2155
- `@skillcap/gdh@${pinnedVersion}`,
2156
- "mcp",
2157
- "serve",
2158
- ];
2210
+ const codexCommandArgs = ["-y", `@skillcap/gdh@${pinnedVersion}`, "mcp", "serve"];
2159
2211
  if (resolvedTargetPath !== resolvedIntegrationRootPath) {
2160
2212
  codexCommandArgs.push("--target", resolvedTargetPath);
2161
2213
  }
@@ -2264,11 +2316,7 @@ function planClaudeInstallActions(targetPath, adapter, pinnedVersion) {
2264
2316
  targetPath,
2265
2317
  relativePath: CLAUDE_SETTINGS_RELATIVE_PATH,
2266
2318
  state: settingsIsUnchanged ? "unchanged" : "planned",
2267
- mode: settingsIsUnchanged
2268
- ? "unchanged"
2269
- : settingsExistedOnDisk
2270
- ? "replace"
2271
- : "create",
2319
+ mode: settingsIsUnchanged ? "unchanged" : settingsExistedOnDisk ? "replace" : "create",
2272
2320
  summary: settingsIsUnchanged
2273
2321
  ? "GDH SessionStart hook + statusline already registered in .claude/settings.json."
2274
2322
  : settingsExistedOnDisk
@@ -2428,8 +2476,7 @@ function isMatchingManagedMcpServerEntry(entry, expectedEntry) {
2428
2476
  if (entry === null) {
2429
2477
  return false;
2430
2478
  }
2431
- return (JSON.stringify(normalizeJson(entry)) ===
2432
- JSON.stringify(normalizeJson(expectedEntry)));
2479
+ return JSON.stringify(normalizeJson(entry)) === JSON.stringify(normalizeJson(expectedEntry));
2433
2480
  }
2434
2481
  function renderManagedMcpConfig(absolutePath, managedEntry) {
2435
2482
  const existing = readExistingMcpConfig(absolutePath);
@@ -2507,10 +2554,7 @@ function extractManagedCodexSection(content) {
2507
2554
  break;
2508
2555
  }
2509
2556
  }
2510
- return lines
2511
- .slice(start, end)
2512
- .join("\n")
2513
- .replace(/\s+$/, "");
2557
+ return lines.slice(start, end).join("\n").replace(/\s+$/, "");
2514
2558
  }
2515
2559
  function normalizeJson(value) {
2516
2560
  if (Array.isArray(value)) {
@@ -2653,12 +2697,7 @@ async function listCodexMcpServers() {
2653
2697
  function isMatchingCodexRegistration(registration, input) {
2654
2698
  const resolvedTargetPath = path.resolve(input.targetPath);
2655
2699
  const resolvedIntegrationRootPath = path.resolve(input.integrationRootPath);
2656
- const expectedArgs = [
2657
- "-y",
2658
- `@skillcap/gdh@${input.pinnedVersion}`,
2659
- "mcp",
2660
- "serve",
2661
- ];
2700
+ const expectedArgs = ["-y", `@skillcap/gdh@${input.pinnedVersion}`, "mcp", "serve"];
2662
2701
  if (resolvedTargetPath !== resolvedIntegrationRootPath) {
2663
2702
  expectedArgs.push("--target", resolvedTargetPath);
2664
2703
  }
@@ -2668,9 +2707,7 @@ function isMatchingCodexRegistration(registration, input) {
2668
2707
  }
2669
2708
  async function inspectProjectConfigLifecycleSurface(targetPath) {
2670
2709
  const relativePath = ".gdh/project.yaml";
2671
- const content = await fs
2672
- .readFile(path.join(targetPath, relativePath), "utf8")
2673
- .catch(() => null);
2710
+ const content = await fs.readFile(path.join(targetPath, relativePath), "utf8").catch(() => null);
2674
2711
  const detectedVersion = readYamlVersionHeader(content);
2675
2712
  const probes = [
2676
2713
  createVersionProbe({
@@ -2719,7 +2756,7 @@ async function inspectProjectConfigLifecycleSurface(targetPath) {
2719
2756
  action: {
2720
2757
  kind: "apply_migration",
2721
2758
  summary: "Run GDH migrate to rewrite the project config to the current schema.",
2722
- command: ["gdh", "migrate", targetPath],
2759
+ command: migrateApplyCommand(targetPath),
2723
2760
  autoApplicable: true,
2724
2761
  },
2725
2762
  });
@@ -2773,9 +2810,7 @@ async function inspectVerificationScenarioLifecycleSurface(targetPath) {
2773
2810
  }
2774
2811
  async function inspectRulesLifecycleSurface(targetPath) {
2775
2812
  const relativePath = ".gdh/rules.yaml";
2776
- const content = await fs
2777
- .readFile(path.join(targetPath, relativePath), "utf8")
2778
- .catch(() => null);
2813
+ const content = await fs.readFile(path.join(targetPath, relativePath), "utf8").catch(() => null);
2779
2814
  const detectedVersion = readYamlVersionHeader(content);
2780
2815
  const probes = [
2781
2816
  createVersionProbe({
@@ -2797,7 +2832,7 @@ async function inspectRulesLifecycleSurface(targetPath) {
2797
2832
  action: {
2798
2833
  kind: "apply_migration",
2799
2834
  summary: "Run GDH migrate to create the default rules file for this target.",
2800
- command: ["gdh", "migrate", targetPath],
2835
+ command: migrateApplyCommand(targetPath),
2801
2836
  autoApplicable: true,
2802
2837
  },
2803
2838
  });
@@ -2867,16 +2902,14 @@ function inspectAgentContractLifecycleSurface(targetPath, guidanceStatus) {
2867
2902
  action: {
2868
2903
  kind: "apply_migration",
2869
2904
  summary: "Run GDH migrate to merge or refresh the managed agent contract block.",
2870
- command: ["gdh", "migrate", targetPath],
2905
+ command: migrateApplyCommand(targetPath),
2871
2906
  autoApplicable: true,
2872
2907
  },
2873
2908
  });
2874
2909
  }
2875
2910
  async function inspectGuidanceIndexLifecycleSurface(targetPath) {
2876
2911
  const relativePath = "docs/agent/README.md";
2877
- const content = await fs
2878
- .readFile(path.join(targetPath, relativePath), "utf8")
2879
- .catch(() => null);
2912
+ const content = await fs.readFile(path.join(targetPath, relativePath), "utf8").catch(() => null);
2880
2913
  const detectedVersion = readTaggedVersion(content, /<!-- GDH GUIDANCE INDEX VERSION: (\d+) -->/);
2881
2914
  const probes = [
2882
2915
  createVersionProbe({
@@ -2898,7 +2931,7 @@ async function inspectGuidanceIndexLifecycleSurface(targetPath) {
2898
2931
  action: {
2899
2932
  kind: "apply_migration",
2900
2933
  summary: "Run GDH migrate to create the default guidance index for this target.",
2901
- command: ["gdh", "migrate", targetPath],
2934
+ command: migrateApplyCommand(targetPath),
2902
2935
  autoApplicable: true,
2903
2936
  },
2904
2937
  });
@@ -2924,7 +2957,7 @@ async function inspectGuidanceIndexLifecycleSurface(targetPath) {
2924
2957
  action: {
2925
2958
  kind: "apply_migration",
2926
2959
  summary: "Run GDH migrate to regenerate the guidance index with updated content.",
2927
- command: ["gdh", "migrate", targetPath],
2960
+ command: migrateApplyCommand(targetPath),
2928
2961
  autoApplicable: true,
2929
2962
  },
2930
2963
  });
@@ -2981,7 +3014,7 @@ async function inspectGuidanceUnitLifecycleSurface(targetPath, projectConfig) {
2981
3014
  action: {
2982
3015
  kind: "apply_migration",
2983
3016
  summary: "Run GDH migrate to create the missing default guidance unit files.",
2984
- command: ["gdh", "migrate", targetPath],
3017
+ command: migrateApplyCommand(targetPath),
2985
3018
  autoApplicable: true,
2986
3019
  },
2987
3020
  });
@@ -2996,7 +3029,7 @@ async function inspectGuidanceUnitLifecycleSurface(targetPath, projectConfig) {
2996
3029
  action: {
2997
3030
  kind: "apply_migration",
2998
3031
  summary: "Run GDH migrate to regenerate guidance units with updated content.",
2999
- command: ["gdh", "migrate", targetPath],
3032
+ command: migrateApplyCommand(targetPath),
3000
3033
  autoApplicable: true,
3001
3034
  },
3002
3035
  });
@@ -3084,9 +3117,7 @@ function inspectCursorRuleLifecycleSurface(targetPath, adapterStatus) {
3084
3117
  management: "managed",
3085
3118
  state: surface?.present ? "migration_available" : "migration_needed",
3086
3119
  summary: "Cursor rule file needs to be created or refreshed through the adapter install flow.",
3087
- reasons: surface?.present
3088
- ? ["cursor_rule_misconfigured"]
3089
- : ["cursor_rule_missing"],
3120
+ reasons: surface?.present ? ["cursor_rule_misconfigured"] : ["cursor_rule_missing"],
3090
3121
  probes,
3091
3122
  action: {
3092
3123
  kind: "run_repair",
@@ -3365,7 +3396,7 @@ async function inspectYamlSurfaceDirectory(input) {
3365
3396
  action: {
3366
3397
  kind: "apply_migration",
3367
3398
  summary: "Run GDH migrate to normalize legacy runtime surface directories.",
3368
- command: ["gdh", "migrate", input.targetPath],
3399
+ command: migrateApplyCommand(input.targetPath),
3369
3400
  autoApplicable: true,
3370
3401
  },
3371
3402
  });
@@ -3405,7 +3436,7 @@ async function inspectYamlSurfaceDirectory(input) {
3405
3436
  action: {
3406
3437
  kind: "apply_migration",
3407
3438
  summary: "Run GDH migrate to normalize the affected runtime surfaces.",
3408
- command: ["gdh", "migrate", input.targetPath],
3439
+ command: migrateApplyCommand(input.targetPath),
3409
3440
  autoApplicable: true,
3410
3441
  },
3411
3442
  });
@@ -3491,6 +3522,9 @@ function summarizeProjectLifecycleState(state, surfaces) {
3491
3522
  function createLifecycleSurfaceStatus(input) {
3492
3523
  return input;
3493
3524
  }
3525
+ function migrateApplyCommand(targetPath) {
3526
+ return ["gdh", "migrate", "--apply", targetPath];
3527
+ }
3494
3528
  function createVersionProbe(input) {
3495
3529
  return {
3496
3530
  relativePath: input.relativePath,
@@ -3533,8 +3567,7 @@ function readTaggedVersion(content, pattern) {
3533
3567
  function findAdapterSurface(adapterStatus, agent, kind) {
3534
3568
  return (adapterStatus.adapters
3535
3569
  .find((entry) => entry.agent === agent)
3536
- ?.surfaces.find((surface) => surface.kind === kind && surface.scope === "repo") ??
3537
- null);
3570
+ ?.surfaces.find((surface) => surface.kind === kind && surface.scope === "repo") ?? null);
3538
3571
  }
3539
3572
  async function pathExists(targetPath) {
3540
3573
  try {
@@ -3580,6 +3613,9 @@ async function addOperationalCapabilityStatus(capabilities, targetPath) {
3580
3613
  operationalAvailability: "available",
3581
3614
  operationalReason: null,
3582
3615
  operationalSummary: "Machine-local Godot editor path is configured, so managed authoring.lsp can launch or reuse an instance.",
3616
+ diagnosticAvailability: "available",
3617
+ diagnosticReason: null,
3618
+ diagnosticSummary: "Machine-local Godot editor path is configured. `gdh authoring check` can launch the GDScript LSP and scene/resource validators, but capability status alone is not diagnostic evidence.",
3583
3619
  };
3584
3620
  }
3585
3621
  return {
@@ -3587,6 +3623,9 @@ async function addOperationalCapabilityStatus(capabilities, targetPath) {
3587
3623
  operationalAvailability: "unavailable",
3588
3624
  operationalReason: "godot_editor_not_configured",
3589
3625
  operationalSummary: "Managed authoring.lsp is enabled for this target, but no machine-local Godot editor path is configured yet.",
3626
+ diagnosticAvailability: "unavailable",
3627
+ diagnosticReason: "godot_editor_not_configured",
3628
+ diagnosticSummary: "Authoring diagnostics require `gdh authoring check` plus a machine-local Godot editor path; declared `authoring.lsp` capability is not diagnostic evidence.",
3590
3629
  };
3591
3630
  });
3592
3631
  }
@@ -3615,9 +3654,9 @@ function deriveRepoState(context) {
3615
3654
  function normalizeChangedFiles(files) {
3616
3655
  return [...new Set(files.map((file) => file.trim()).filter((file) => file.length > 0))];
3617
3656
  }
3618
- export { bumpAndRebakePin, } from "./self-update-mechanics.js";
3619
- export { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH } from "./claude-update-hook-render.js";
3620
3657
  export { CLAUDE_STATUSLINE_RELATIVE_PATH } from "./claude-statusline-render.js";
3658
+ export { CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH } from "./claude-update-hook-render.js";
3659
+ export { bumpAndRebakePin, } from "./self-update-mechanics.js";
3621
3660
  // Internal aggregator exposed for Wave 0 unit tests
3622
3661
  // (packages/adapters/src/lifecycle-compatibility.test.ts). Callers outside this
3623
3662
  // package should continue to use inspectProjectLifecycleCompatibility, which