@skillcap/gdh 2.0.1 → 3.0.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 (88) hide show
  1. package/INSTALL-BUNDLE.json +1 -1
  2. package/RELEASE-SPAN-UPDATE-CONTRACTS.json +121 -0
  3. package/node_modules/@gdh/adapters/dist/authoring-hook-render.d.ts +3 -18
  4. package/node_modules/@gdh/adapters/dist/authoring-hook-render.d.ts.map +1 -1
  5. package/node_modules/@gdh/adapters/dist/authoring-hook-render.js +11 -6
  6. package/node_modules/@gdh/adapters/dist/authoring-hook-render.js.map +1 -1
  7. package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts +15 -3
  8. package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts.map +1 -1
  9. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +14 -2
  10. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -1
  11. package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts +18 -9
  12. package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts.map +1 -1
  13. package/node_modules/@gdh/adapters/dist/claude-statusline-render.js +18 -9
  14. package/node_modules/@gdh/adapters/dist/claude-statusline-render.js.map +1 -1
  15. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts +8 -2
  16. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts.map +1 -1
  17. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js +8 -2
  18. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js.map +1 -1
  19. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts +2 -2
  20. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js +2 -2
  21. package/node_modules/@gdh/adapters/dist/index.d.ts +2 -5
  22. package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
  23. package/node_modules/@gdh/adapters/dist/index.js +19 -75
  24. package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
  25. package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts.map +1 -1
  26. package/node_modules/@gdh/adapters/dist/skill-rendering.js +1 -0
  27. package/node_modules/@gdh/adapters/dist/skill-rendering.js.map +1 -1
  28. package/node_modules/@gdh/adapters/dist/templates/authoring-hook.js.tpl +49 -43
  29. package/node_modules/@gdh/adapters/package.json +8 -8
  30. package/node_modules/@gdh/authoring/dist/project.d.ts.map +1 -1
  31. package/node_modules/@gdh/authoring/dist/project.js +39 -12
  32. package/node_modules/@gdh/authoring/dist/project.js.map +1 -1
  33. package/node_modules/@gdh/authoring/package.json +2 -2
  34. package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
  35. package/node_modules/@gdh/cli/dist/index.js +121 -80
  36. package/node_modules/@gdh/cli/dist/index.js.map +1 -1
  37. package/node_modules/@gdh/cli/dist/self-update.d.ts.map +1 -1
  38. package/node_modules/@gdh/cli/dist/self-update.js +62 -1
  39. package/node_modules/@gdh/cli/dist/self-update.js.map +1 -1
  40. package/node_modules/@gdh/cli/dist/setup.d.ts +7 -0
  41. package/node_modules/@gdh/cli/dist/setup.d.ts.map +1 -1
  42. package/node_modules/@gdh/cli/dist/setup.js +43 -11
  43. package/node_modules/@gdh/cli/dist/setup.js.map +1 -1
  44. package/node_modules/@gdh/cli/package.json +10 -10
  45. package/node_modules/@gdh/core/dist/git-root.d.ts +8 -0
  46. package/node_modules/@gdh/core/dist/git-root.d.ts.map +1 -0
  47. package/node_modules/@gdh/core/dist/git-root.js +39 -0
  48. package/node_modules/@gdh/core/dist/git-root.js.map +1 -0
  49. package/node_modules/@gdh/core/dist/index.d.ts +19 -18
  50. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  51. package/node_modules/@gdh/core/dist/index.js +17 -2
  52. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  53. package/node_modules/@gdh/core/dist/migrations/entries/s3c21_to_s3c22_canonical_hook_paths.d.ts +3 -0
  54. package/node_modules/@gdh/core/dist/migrations/entries/s3c21_to_s3c22_canonical_hook_paths.d.ts.map +1 -0
  55. package/node_modules/@gdh/core/dist/migrations/entries/s3c21_to_s3c22_canonical_hook_paths.js +336 -0
  56. package/node_modules/@gdh/core/dist/migrations/entries/s3c21_to_s3c22_canonical_hook_paths.js.map +1 -0
  57. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts +13 -11
  58. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts.map +1 -1
  59. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js +13 -11
  60. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js.map +1 -1
  61. package/node_modules/@gdh/core/dist/migrations/registry.d.ts +1 -1
  62. package/node_modules/@gdh/core/dist/migrations/registry.d.ts.map +1 -1
  63. package/node_modules/@gdh/core/dist/migrations/registry.js +2 -0
  64. package/node_modules/@gdh/core/dist/migrations/registry.js.map +1 -1
  65. package/node_modules/@gdh/core/dist/state/codex-retrust-reminder.d.ts +40 -0
  66. package/node_modules/@gdh/core/dist/state/codex-retrust-reminder.d.ts.map +1 -0
  67. package/node_modules/@gdh/core/dist/state/codex-retrust-reminder.js +66 -0
  68. package/node_modules/@gdh/core/dist/state/codex-retrust-reminder.js.map +1 -0
  69. package/node_modules/@gdh/core/dist/state/migration-trace.d.ts +61 -0
  70. package/node_modules/@gdh/core/dist/state/migration-trace.d.ts.map +1 -0
  71. package/node_modules/@gdh/core/dist/state/migration-trace.js +103 -0
  72. package/node_modules/@gdh/core/dist/state/migration-trace.js.map +1 -0
  73. package/node_modules/@gdh/core/dist/update-probe.d.ts +1 -2
  74. package/node_modules/@gdh/core/dist/update-probe.d.ts.map +1 -1
  75. package/node_modules/@gdh/core/dist/update-probe.js +1 -2
  76. package/node_modules/@gdh/core/dist/update-probe.js.map +1 -1
  77. package/node_modules/@gdh/core/package.json +1 -1
  78. package/node_modules/@gdh/docs/package.json +2 -2
  79. package/node_modules/@gdh/mcp/package.json +8 -8
  80. package/node_modules/@gdh/observability/package.json +2 -2
  81. package/node_modules/@gdh/runtime/package.json +2 -2
  82. package/node_modules/@gdh/scan/package.json +3 -3
  83. package/node_modules/@gdh/verify/package.json +7 -7
  84. package/package.json +11 -11
  85. package/node_modules/@gdh/adapters/dist/authoring-hook-state-path.d.ts +0 -17
  86. package/node_modules/@gdh/adapters/dist/authoring-hook-state-path.d.ts.map +0 -1
  87. package/node_modules/@gdh/adapters/dist/authoring-hook-state-path.js +0 -23
  88. package/node_modules/@gdh/adapters/dist/authoring-hook-state-path.js.map +0 -1
@@ -4,9 +4,9 @@ import fs from "node:fs/promises";
4
4
  import os from "node:os";
5
5
  import path from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
- import { buildGdhStatusResult, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_MIGRATE_SKILL_RELATIVE_PATH, CLAUDE_ONBOARD_SKILL_RELATIVE_PATH, CLAUDE_PREPARE_SKILL_RELATIVE_PATH, CLAUDE_STATUS_SKILL_RELATIVE_PATH, CODEX_MIGRATE_SKILL_RELATIVE_PATH, CODEX_ONBOARD_SKILL_RELATIVE_PATH, CODEX_PREPARE_SKILL_RELATIVE_PATH, CODEX_STATUS_SKILL_RELATIVE_PATH, createGsdSnapshot, getSupportedAgentAdaptersStatus, installSupportedAgentAdapters, } from "@gdh/adapters";
7
+ import { buildGdhStatusResult, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_MIGRATE_SKILL_RELATIVE_PATH, CLAUDE_ONBOARD_SKILL_RELATIVE_PATH, CLAUDE_PREPARE_SKILL_RELATIVE_PATH, CLAUDE_STATUS_SKILL_RELATIVE_PATH, CODEX_MIGRATE_SKILL_RELATIVE_PATH, CODEX_ONBOARD_SKILL_RELATIVE_PATH, CODEX_PREPARE_SKILL_RELATIVE_PATH, CODEX_STATUS_SKILL_RELATIVE_PATH, getSupportedAgentAdaptersStatus, installSupportedAgentAdapters, } from "@gdh/adapters";
8
8
  import { checkManagedLsp, doctorAuthoringDiagnostics, doctorManagedLsp, getAuthoringDiagnosticsStatus, getCurrentAuthoringDiagnostics, getManagedLspStatus, hasCompleteOnboardingSurface, inspectCacheState, pruneAuthoringDiagnostics, pruneCacheState, pruneManagedLsp, readProjectConfig, readWorktreeState, refreshAuthoringDiagnostics, resolveAuthoringStatus, resolveEffectiveTargetPath, resolvePinnedVersion, resolveProjectRoot, resolveTargetGodotDocsVersion, restartManagedLsp, runAuthoringCheck, runImportRefresh, runTargetPrepare, runWarmup, stopManagedLsp, warmupManagedLsp, } from "@gdh/authoring";
9
- import { definePackageBoundary, GDH_AUTHORING_DOGFOOD_VERSION, GDH_AUTHORING_SLICE_REPORT_VERSION, GDH_PRODUCT_NAME, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
9
+ import { CODEX_RETRUST_REMINDER_TEXT, clearCodexRetrustReminder, definePackageBoundary, GDH_AUTHORING_DOGFOOD_VERSION, GDH_AUTHORING_SLICE_REPORT_VERSION, GDH_PRODUCT_NAME, readCodexRetrustReminder, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
10
10
  import { fetchOfficialGodotDoc, getGuidanceStatus, resolveGuidanceQuery, searchOfficialGodotDocs, } from "@gdh/docs";
11
11
  import { createMcpManifest, invokeMcpTool, serveMcpOverStdio } from "@gdh/mcp";
12
12
  import { inspectAuthoringEffectiveness, inspectAuthoringSessions, inspectGuidanceAudit, recordAuthoringSessionEvent, } from "@gdh/observability";
@@ -28,7 +28,7 @@ import { runSelfUpdateCommand as runSelfUpdateCommandImpl } from "./self-update.
28
28
  export async function runSelfUpdateCommand(args, io) {
29
29
  return runSelfUpdateCommandImpl(args, io);
30
30
  }
31
- import { executeSetupCommand, isSetupCanceledError, renderDurableTruthCollisionHint, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
31
+ import { executeSetupCommand, isSetupCanceledError, renderDurableTruthCollisionHint, renderGitRequiredHint, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
32
32
  import { emitUpdateBannerIfStale } from "./update-banner.js";
33
33
  export const cliPackage = definePackageBoundary({
34
34
  name: "@gdh/cli",
@@ -390,6 +390,17 @@ async function runSetupCommand(args, io) {
390
390
  });
391
391
  return 1;
392
392
  }
393
+ if (renderGitRequiredHint(error, io.stderr)) {
394
+ await recordSessionEvent(targetPath, {
395
+ commandStartedAtMs,
396
+ kind: "onboard",
397
+ command: "gdh setup",
398
+ state: "blocked",
399
+ summary: "GDH setup blocked because the target is not in a git working tree (RFC 0010 D1).",
400
+ errorMessage: formatCliError(error),
401
+ });
402
+ return 1;
403
+ }
393
404
  await recordSessionEvent(targetPath, {
394
405
  commandStartedAtMs,
395
406
  kind: "onboard",
@@ -466,6 +477,19 @@ async function runOnboardCommand(args, io) {
466
477
  return 0;
467
478
  }
468
479
  catch (error) {
480
+ if (renderGitRequiredHint(error, io.stderr)) {
481
+ if (!dryRun) {
482
+ await recordSessionEvent(targetPath, {
483
+ commandStartedAtMs,
484
+ kind: "onboard",
485
+ command: "gdh onboard",
486
+ state: "blocked",
487
+ summary: "GDH onboard blocked because the target is not in a git working tree (RFC 0010 D1).",
488
+ errorMessage: formatCliError(error),
489
+ });
490
+ }
491
+ return 1;
492
+ }
469
493
  if (!dryRun) {
470
494
  await recordSessionEvent(targetPath, {
471
495
  commandStartedAtMs,
@@ -505,6 +529,18 @@ async function runStatusCommand(args, io) {
505
529
  // to `gdh status` and `gdh verify` only. Silent when cache is null /
506
530
  // current / offline / dev-mode (D-06).
507
531
  await emitUpdateBannerIfStale(targetPath, io);
532
+ // RFC 0010 / CPATH-16 (PR-1). One-shot Codex re-trust reminder. Set by the
533
+ // v3.0.0 canonical-path migration when the `.codex/config.toml` envelope is
534
+ // rewritten. `gdh self-update` already surfaced it once on the apply path;
535
+ // this is the second-half delivery — first post-migration `gdh status`
536
+ // call also emits the reminder, then clears the marker.
537
+ const codexReminder = await readCodexRetrustReminder(targetPath);
538
+ if (codexReminder !== null) {
539
+ const tty = Boolean(io.stderr.isTTY ?? process.stderr.isTTY);
540
+ const yellow = (text) => (tty ? `\x1b[33m${text}\x1b[0m` : text);
541
+ io.stderr.write(`${yellow("⚠ " + CODEX_RETRUST_REMINDER_TEXT)}\n`);
542
+ await clearCodexRetrustReminder(targetPath);
543
+ }
508
544
  try {
509
545
  const status = await buildGdhStatusResult(targetPath);
510
546
  io.stdout.write(`${JSON.stringify(status, null, 2)}\n`);
@@ -1578,7 +1614,6 @@ async function runAdaptersCommand(args, io) {
1578
1614
  " Inspect supported-agent reinforcement status as JSON.",
1579
1615
  " install [target] [--dry-run] [--agent <name>] [--user] [--dev-repo <path>] [--integration-root <path>]",
1580
1616
  " Install or repair supported-agent reinforcement surfaces.",
1581
- " gsd snapshot [target] [--files <path>] Export a read-mostly GSD projection as JSON.",
1582
1617
  "",
1583
1618
  "Supported agents: codex, claude",
1584
1619
  ].join("\n") + "\n");
@@ -1590,36 +1625,11 @@ async function runAdaptersCommand(args, io) {
1590
1625
  if (subcommand === "install") {
1591
1626
  return runAdaptersInstallCommand(rest, io);
1592
1627
  }
1593
- if (subcommand === "gsd") {
1594
- return runGsdAdapterCommand(rest, io);
1595
- }
1596
1628
  io.stderr.write([
1597
1629
  `Unknown adapters command: ${subcommand}`,
1598
1630
  "",
1599
1631
  "Usage: gdh adapters status [target] [--user] [--integration-root <path>]",
1600
1632
  "Usage: gdh adapters install [target] [--dry-run] [--agent <name>] [--user] [--dev-repo <path>] [--integration-root <path>]",
1601
- "Usage: gdh adapters gsd snapshot [target] [--files <path>]",
1602
- ].join("\n") + "\n");
1603
- return 1;
1604
- }
1605
- async function runGsdAdapterCommand(args, io) {
1606
- const [subcommand, ...rest] = args;
1607
- if (!subcommand || subcommand === "--help" || subcommand === "help") {
1608
- io.stdout.write([
1609
- "Usage: gdh adapters gsd <command> [target]",
1610
- "",
1611
- "Commands:",
1612
- " snapshot [target] [--files <path>] Export a read-mostly GSD projection as JSON.",
1613
- ].join("\n") + "\n");
1614
- return 0;
1615
- }
1616
- if (subcommand === "snapshot") {
1617
- return runGsdSnapshotCommand(rest, io);
1618
- }
1619
- io.stderr.write([
1620
- `Unknown adapters gsd command: ${subcommand}`,
1621
- "",
1622
- "Usage: gdh adapters gsd snapshot [target] [--files <path>]",
1623
1633
  ].join("\n") + "\n");
1624
1634
  return 1;
1625
1635
  }
@@ -2888,43 +2898,6 @@ async function runAdaptersInstallCommand(args, io) {
2888
2898
  return 1;
2889
2899
  }
2890
2900
  }
2891
- async function runGsdSnapshotCommand(args, io) {
2892
- if (args.includes("--help")) {
2893
- io.stdout.write([
2894
- "Usage: gdh adapters gsd snapshot [target] [--files <path>]",
2895
- "",
2896
- "Export a read-mostly GSD projection over current GDH status, guidance, and validation surfaces as JSON.",
2897
- ].join("\n") + "\n");
2898
- return 0;
2899
- }
2900
- const unsupportedOptionsError = findUnsupportedOptionsError(args, {
2901
- usage: "Usage: gdh adapters gsd snapshot [target] [--files <path>]\n",
2902
- optionsWithValues: ["--files"],
2903
- });
2904
- if (unsupportedOptionsError !== null) {
2905
- io.stderr.write(unsupportedOptionsError);
2906
- return 1;
2907
- }
2908
- const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
2909
- usage: "Usage: gdh adapters gsd snapshot [target] [--files <path>]\n",
2910
- additionalOptionsWithValues: new Set(["--files"]),
2911
- });
2912
- if (targetPathError !== null) {
2913
- io.stderr.write(targetPathError);
2914
- return 1;
2915
- }
2916
- try {
2917
- const result = await createGsdSnapshot(targetPath, {
2918
- files: collectOptionValues(args, "--files"),
2919
- });
2920
- io.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
2921
- return 0;
2922
- }
2923
- catch (error) {
2924
- io.stderr.write(`Failed to create a GSD snapshot for "${targetPath}": ${formatCliError(error)}\n`);
2925
- return 1;
2926
- }
2927
- }
2928
2901
  async function runMcpManifestCommand(args, io) {
2929
2902
  if (args.includes("--help")) {
2930
2903
  io.stdout.write(["Usage: gdh mcp manifest", "", "Print the thin GDH MCP manifest as JSON."].join("\n") + "\n");
@@ -3322,6 +3295,49 @@ async function runVerifyReadinessCommand(args, io) {
3322
3295
  return 1;
3323
3296
  }
3324
3297
  }
3298
+ const VERIFY_DRIFT_LEGACY_HOOK_PATHS = [
3299
+ ".claude/hooks/gdh-authoring-guard.js",
3300
+ ".claude/hooks/gdh-check-update.js",
3301
+ ".claude/hooks/gdh-check-update-worker.js",
3302
+ ".claude/hooks/gdh-statusline.js",
3303
+ ".codex/hooks/gdh-authoring-guard.js",
3304
+ ];
3305
+ const VERIFY_DRIFT_NEW_HOOK_PATHS = [
3306
+ ".gdh/hooks/authoring-guard.js",
3307
+ ".gdh/hooks/check-update.js",
3308
+ ".gdh/hooks/check-update-worker.js",
3309
+ ".gdh/hooks/statusline.js",
3310
+ ];
3311
+ async function inspectVerifyDriftLegacyLayout(targetPath) {
3312
+ const legacyFiles = [];
3313
+ for (const relativePath of VERIFY_DRIFT_LEGACY_HOOK_PATHS) {
3314
+ const absolutePath = path.join(targetPath, relativePath);
3315
+ const exists = await fs
3316
+ .access(absolutePath)
3317
+ .then(() => true)
3318
+ .catch(() => false);
3319
+ if (exists)
3320
+ legacyFiles.push(relativePath);
3321
+ }
3322
+ const newLayoutFiles = [];
3323
+ for (const relativePath of VERIFY_DRIFT_NEW_HOOK_PATHS) {
3324
+ const absolutePath = path.join(targetPath, relativePath);
3325
+ const exists = await fs
3326
+ .access(absolutePath)
3327
+ .then(() => true)
3328
+ .catch(() => false);
3329
+ if (exists)
3330
+ newLayoutFiles.push(relativePath);
3331
+ }
3332
+ if (legacyFiles.length === 0) {
3333
+ return { state: "absent", legacyFiles, newLayoutFiles };
3334
+ }
3335
+ return {
3336
+ state: newLayoutFiles.length > 0 ? "partially_migrated" : "migration_pending",
3337
+ legacyFiles,
3338
+ newLayoutFiles,
3339
+ };
3340
+ }
3325
3341
  const VERIFY_DRIFT_SCANNED_FILES = [
3326
3342
  { relativePath: CODEX_ONBOARD_SKILL_RELATIVE_PATH, description: "Codex gdh-onboard skill" },
3327
3343
  { relativePath: CODEX_STATUS_SKILL_RELATIVE_PATH, description: "Codex gdh-status skill" },
@@ -3389,6 +3405,11 @@ async function runVerifyDriftCommand(args, io) {
3389
3405
  ".gdh/project.yaml gdh_version. Exits 1 and",
3390
3406
  "emits a structured JSON result when ANY file's baked version diverges from",
3391
3407
  "the pinned value. Covers ROADMAP Success Criterion #3 (one source of truth).",
3408
+ "Also recognises the pre-v3.0.0 hook layout (RFC 0010 / CPATH-10): when",
3409
+ "`.claude/hooks/gdh-*.js` or `.codex/hooks/gdh-authoring-guard.js` is still on",
3410
+ "disk, the result emits `legacyLayout.state: \"migration_pending\"` (legacy only)",
3411
+ "or `\"partially_migrated\"` (legacy + canonical present) and points the",
3412
+ "remediation action at `gdh self-update` rather than `gdh adapters install`.",
3392
3413
  "This command does NOT validate runtime bridge, project lifecycle, or authoring health.",
3393
3414
  "",
3394
3415
  ].join("\n"));
@@ -3458,33 +3479,54 @@ async function runVerifyDriftCommand(args, io) {
3458
3479
  }));
3459
3480
  const driftFiles = fileResults.filter((file) => file.drift);
3460
3481
  const overallDrift = driftFiles.length > 0;
3461
- const result = {
3462
- ok: !overallDrift,
3463
- drift: overallDrift,
3464
- pinned: pinnedVersion,
3465
- scannedFileCount: fileResults.length,
3466
- driftFileCount: driftFiles.length,
3467
- files: fileResults,
3468
- action: overallDrift
3482
+ // RFC 0010 CPATH-10 — recognise the pre-v3.0.0 hook layout as migration
3483
+ // input. When legacy hook scripts are still on disk, route operators to
3484
+ // `gdh self-update` instead of `gdh adapters install`; the migration entry
3485
+ // owns the legacy-file cleanup that re-bake cannot perform.
3486
+ const legacyLayout = await inspectVerifyDriftLegacyLayout(targetPath);
3487
+ const action = legacyLayout.state === "migration_pending" ||
3488
+ legacyLayout.state === "partially_migrated"
3489
+ ? {
3490
+ kind: "run_migration",
3491
+ summary: legacyLayout.state === "migration_pending"
3492
+ ? `Detected legacy v2.x hook layout (${legacyLayout.legacyFiles.length} script(s) under .claude/hooks/ or .codex/hooks/). Run \`gdh self-update\` to migrate to the v3.0.0 canonical layout.`
3493
+ : `Detected partially-migrated hook layout (${legacyLayout.legacyFiles.length} legacy script(s) AND ${legacyLayout.newLayoutFiles.length} canonical script(s) coexisting). Re-run \`gdh self-update\` to converge.`,
3494
+ command: ["gdh", "self-update", targetPath],
3495
+ autoApplicable: true,
3496
+ }
3497
+ : overallDrift
3469
3498
  ? {
3470
3499
  kind: "run_repair",
3471
3500
  summary: `${driftFiles.length} managed-surface file(s) have a baked version that does not match .gdh/project.yaml gdh_version. Run \`gdh adapters install\` to regenerate them.`,
3472
3501
  command: ["gdh", "adapters", "install", targetPath],
3473
3502
  autoApplicable: true,
3474
3503
  }
3475
- : null,
3504
+ : null;
3505
+ const result = {
3506
+ ok: !overallDrift && legacyLayout.state === "absent",
3507
+ drift: overallDrift || legacyLayout.state !== "absent",
3508
+ pinned: pinnedVersion,
3509
+ scannedFileCount: fileResults.length,
3510
+ driftFileCount: driftFiles.length,
3511
+ files: fileResults,
3512
+ action,
3513
+ legacyLayout,
3476
3514
  };
3477
3515
  await recordSessionEvent(targetPath, {
3478
3516
  commandStartedAtMs,
3479
3517
  kind: "verify_drift",
3480
3518
  command: "gdh verify drift",
3481
- state: overallDrift ? "failed" : "succeeded",
3482
- summary: overallDrift
3483
- ? `Detected ${driftFiles.length} managed-surface file(s) with a baked version drifted from gdh_version.`
3519
+ state: result.ok ? "succeeded" : "failed",
3520
+ summary: !result.ok
3521
+ ? legacyLayout.state === "migration_pending"
3522
+ ? `Detected pre-v3.0.0 hook layout (${legacyLayout.legacyFiles.length} legacy script(s)). Run \`gdh self-update\` to migrate.`
3523
+ : legacyLayout.state === "partially_migrated"
3524
+ ? `Detected partially-migrated hook layout (${legacyLayout.legacyFiles.length} legacy + ${legacyLayout.newLayoutFiles.length} canonical script(s)). Re-run \`gdh self-update\` to converge.`
3525
+ : `Detected ${driftFiles.length} managed-surface file(s) with a baked version drifted from gdh_version.`
3484
3526
  : `All ${fileResults.length} managed-surface file(s) match .gdh/project.yaml gdh_version.`,
3485
3527
  });
3486
3528
  writeJsonResult(io, result);
3487
- return overallDrift ? 1 : 0;
3529
+ return result.ok ? 0 : 1;
3488
3530
  }
3489
3531
  async function runVerifyCorpusStatusCommand(args, io) {
3490
3532
  if (args.includes("--help")) {
@@ -4489,7 +4531,6 @@ function renderHelp() {
4489
4531
  " docs fetch <ref-or-url> [target] [--project <relative-path>] Fetch one official version-aware Godot docs page or section.",
4490
4532
  " adapters status [target] [--user] [--integration-root <path>] Inspect supported-agent reinforcement status.",
4491
4533
  " adapters install [target] [--dry-run] [--agent <name>] [--user] [--dev-repo <path>] [--integration-root <path>] Install or repair supported-agent reinforcement.",
4492
- " adapters gsd snapshot [target] [--files <path>] Export a read-only GSD projection.",
4493
4534
  " authoring check [target] Run the current authoring-check entrypoint.",
4494
4535
  " authoring diagnostics <status|current|refresh|doctor|prune> [target] Inspect current Godot authoring diagnostics snapshots.",
4495
4536
  " lsp <status|warmup|check|stop|restart|prune|doctor> [target] Manage authoring.lsp lifecycle state.",