@skillcap/gdh 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/INSTALL-BUNDLE.json +1 -1
  2. package/README.md +53 -90
  3. package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts +74 -0
  4. package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts.map +1 -0
  5. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +158 -0
  6. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -0
  7. package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts +51 -0
  8. package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts.map +1 -0
  9. package/node_modules/@gdh/adapters/dist/claude-statusline-render.js +80 -0
  10. package/node_modules/@gdh/adapters/dist/claude-statusline-render.js.map +1 -0
  11. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts +35 -0
  12. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts.map +1 -0
  13. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js +76 -0
  14. package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js.map +1 -0
  15. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts +28 -0
  16. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts.map +1 -0
  17. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js +99 -0
  18. package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js.map +1 -0
  19. package/node_modules/@gdh/adapters/dist/index.d.ts +9 -0
  20. package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
  21. package/node_modules/@gdh/adapters/dist/index.js +224 -2
  22. package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
  23. package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts +51 -0
  24. package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts.map +1 -0
  25. package/node_modules/@gdh/adapters/dist/self-update-mechanics.js +155 -0
  26. package/node_modules/@gdh/adapters/dist/self-update-mechanics.js.map +1 -0
  27. package/node_modules/@gdh/adapters/package.json +8 -8
  28. package/node_modules/@gdh/authoring/dist/index.d.ts +1 -0
  29. package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
  30. package/node_modules/@gdh/authoring/dist/index.js +1 -0
  31. package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
  32. package/node_modules/@gdh/authoring/dist/writePinnedVersion.d.ts +17 -0
  33. package/node_modules/@gdh/authoring/dist/writePinnedVersion.d.ts.map +1 -0
  34. package/node_modules/@gdh/authoring/dist/writePinnedVersion.js +50 -0
  35. package/node_modules/@gdh/authoring/dist/writePinnedVersion.js.map +1 -0
  36. package/node_modules/@gdh/authoring/package.json +5 -2
  37. package/node_modules/@gdh/cli/dist/index.d.ts +15 -0
  38. package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
  39. package/node_modules/@gdh/cli/dist/index.js +68 -8
  40. package/node_modules/@gdh/cli/dist/index.js.map +1 -1
  41. package/node_modules/@gdh/cli/dist/self-update.d.ts +3 -0
  42. package/node_modules/@gdh/cli/dist/self-update.d.ts.map +1 -0
  43. package/node_modules/@gdh/cli/dist/self-update.js +235 -0
  44. package/node_modules/@gdh/cli/dist/self-update.js.map +1 -0
  45. package/node_modules/@gdh/cli/dist/update-banner.d.ts +42 -0
  46. package/node_modules/@gdh/cli/dist/update-banner.d.ts.map +1 -0
  47. package/node_modules/@gdh/cli/dist/update-banner.js +49 -0
  48. package/node_modules/@gdh/cli/dist/update-banner.js.map +1 -0
  49. package/node_modules/@gdh/cli/package.json +10 -10
  50. package/node_modules/@gdh/core/dist/dev-mode.d.ts +13 -0
  51. package/node_modules/@gdh/core/dist/dev-mode.d.ts.map +1 -0
  52. package/node_modules/@gdh/core/dist/dev-mode.js +21 -0
  53. package/node_modules/@gdh/core/dist/dev-mode.js.map +1 -0
  54. package/node_modules/@gdh/core/dist/index.d.ts +8 -2
  55. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  56. package/node_modules/@gdh/core/dist/index.js +8 -0
  57. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  58. package/node_modules/@gdh/core/dist/update-cache.d.ts +46 -0
  59. package/node_modules/@gdh/core/dist/update-cache.d.ts.map +1 -0
  60. package/node_modules/@gdh/core/dist/update-cache.js +90 -0
  61. package/node_modules/@gdh/core/dist/update-cache.js.map +1 -0
  62. package/node_modules/@gdh/core/dist/update-probe.d.ts +102 -0
  63. package/node_modules/@gdh/core/dist/update-probe.d.ts.map +1 -0
  64. package/node_modules/@gdh/core/dist/update-probe.js +195 -0
  65. package/node_modules/@gdh/core/dist/update-probe.js.map +1 -0
  66. package/node_modules/@gdh/core/package.json +1 -1
  67. package/node_modules/@gdh/docs/package.json +2 -2
  68. package/node_modules/@gdh/mcp/dist/index.d.ts +20 -0
  69. package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
  70. package/node_modules/@gdh/mcp/dist/index.js +39 -2
  71. package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
  72. package/node_modules/@gdh/mcp/package.json +8 -8
  73. package/node_modules/@gdh/observability/dist/guidance-audit.js +2 -1
  74. package/node_modules/@gdh/observability/dist/guidance-audit.js.map +1 -1
  75. package/node_modules/@gdh/observability/package.json +2 -2
  76. package/node_modules/@gdh/runtime/package.json +2 -2
  77. package/node_modules/@gdh/scan/package.json +3 -3
  78. package/node_modules/@gdh/verify/package.json +7 -7
  79. package/package.json +11 -11
@@ -0,0 +1,155 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { resolvePinnedVersion, resolvePinnedVersionOrNull, writePinnedVersion, } from "@gdh/authoring";
4
+ import { resolveEffectiveDevRepoPath } from "@gdh/core";
5
+ // Dynamic import breaks the circular dependency with ./index.ts.
6
+ //
7
+ // self-update-mechanics.ts is re-exported from adapters/index.ts (the barrel).
8
+ // installSupportedAgentAdapters is defined in index.ts. A static import of
9
+ // index.ts from here creates a circular reference that Vite SSR resolves with
10
+ // a partial module object, making some exports undefined at call time.
11
+ //
12
+ // All imports from @gdh/authoring and @gdh/core remain static: the circular dep
13
+ // only applies to ./index.js within the same package. Vite's tsconfig path
14
+ // mapping correctly resolves cross-package static imports to source files.
15
+ // The dynamic import() for ./index.js is the only exception: it defers the
16
+ // intra-package circular resolution to call time, after all modules initialize.
17
+ async function loadInstallSupportedAgentAdapters() {
18
+ const { installSupportedAgentAdapters } = await import("./index.js");
19
+ return installSupportedAgentAdapters;
20
+ }
21
+ /**
22
+ * Phase 12 MIG-01 + MIG-02 orchestrator. Atomically bumps the .gdh/project.yaml
23
+ * `gdh_version` pin and re-bakes every managed surface at the new pin.
24
+ *
25
+ * Sequencing invariant (MIG-02): writePinnedVersion is called BEFORE
26
+ * installSupportedAgentAdapters. Because installSupportedAgentAdapters reads
27
+ * the pin from disk once per top-level call (adapters/index.ts:173), pinning
28
+ * first guarantees every renderer bakes the new value.
29
+ *
30
+ * Transactional invariant (MIG-02): on re-bake failure, every captured original
31
+ * is restored. Partial state is not acceptable.
32
+ *
33
+ * SELF-03 leak barrier: dev-mode check gates at the mechanics layer, not only at
34
+ * Phase 13 entry points. Single source of truth.
35
+ */
36
+ export async function bumpAndRebakePin(targetPath, options) {
37
+ // Step 1 (SELF-03 leak barrier): dev-mode short-circuit.
38
+ const devRepoPath = await resolveEffectiveDevRepoPath(targetPath);
39
+ if (devRepoPath !== null) {
40
+ return {
41
+ state: "skipped_dev_mode",
42
+ devRepoPath,
43
+ currentVersion: await resolvePinnedVersionOrNull(targetPath),
44
+ };
45
+ }
46
+ // Step 2: Read current pin (throws with gdh-migrate-apply hint if unonboarded).
47
+ const fromVersion = await resolvePinnedVersion(targetPath);
48
+ if (fromVersion === options.targetVersion) {
49
+ return { state: "noop", currentVersion: fromVersion };
50
+ }
51
+ // Step 3: Plan — dry-run to collect actions. File SET is determined by adapter
52
+ // status + guidance readiness, not by pin value; planning against current pin
53
+ // tells us which files to capture. Per research recommendation (c).
54
+ const installSupportedAgentAdapters = await loadInstallSupportedAgentAdapters();
55
+ const plan = await installSupportedAgentAdapters(targetPath, {
56
+ dryRun: true,
57
+ allowBootstrap: true,
58
+ });
59
+ // Step 4: Capture originals (including .gdh/project.yaml) before any mutation.
60
+ const configPath = path.join(targetPath, ".gdh/project.yaml");
61
+ const originals = await captureOriginals(plan.actions, configPath);
62
+ if (options.dryRun === true) {
63
+ return {
64
+ state: "updated",
65
+ fromVersion,
66
+ toVersion: options.targetVersion,
67
+ actions: plan.actions,
68
+ };
69
+ }
70
+ // Step 5: COMMIT POINT — write new pin first (MIG-02 sequencing).
71
+ // Phase 12 Check 43 asserts writePinnedVersion call textually precedes the
72
+ // final installSupportedAgentAdapters call in this source file. Both calls
73
+ // are inside bumpAndRebakePin; the grep/awk check targets the function body.
74
+ try {
75
+ await writePinnedVersion(targetPath, options.targetVersion);
76
+ }
77
+ catch (error) {
78
+ // Nothing else mutated yet — no rollback needed.
79
+ return { state: "blocked", reason: `Pin write failed: ${formatError(error)}` };
80
+ }
81
+ // Step 6: Re-bake — installSupportedAgentAdapters reads the new pin from disk.
82
+ try {
83
+ const rebake = await installSupportedAgentAdapters(targetPath, {
84
+ allowBootstrap: true,
85
+ });
86
+ const blocked = rebake.actions.filter((a) => a.state === "blocked");
87
+ if (blocked.length > 0) {
88
+ throw new Error(`Re-bake had ${blocked.length} blocked action(s): ${blocked
89
+ .map((a) => a.summary)
90
+ .join("; ")}`);
91
+ }
92
+ return {
93
+ state: "updated",
94
+ fromVersion,
95
+ toVersion: options.targetVersion,
96
+ actions: rebake.actions,
97
+ };
98
+ }
99
+ catch (error) {
100
+ const restoreFailures = await rollbackOriginals(originals);
101
+ return {
102
+ state: "rolled_back",
103
+ fromVersion,
104
+ attemptedToVersion: options.targetVersion,
105
+ failureReason: formatError(error),
106
+ restoreFailures,
107
+ };
108
+ }
109
+ }
110
+ /**
111
+ * Capture current content of every file the planned actions will touch, plus the
112
+ * pin config. A `null` value means the file did not exist — rollback is `fs.rm`.
113
+ * Skips actions with null absolutePath (run_command, write_local_hints abstract actions).
114
+ */
115
+ async function captureOriginals(plannedActions, pinConfigPath) {
116
+ const originals = new Map();
117
+ originals.set(pinConfigPath, await fs.readFile(pinConfigPath, "utf8"));
118
+ for (const action of plannedActions) {
119
+ if (action.absolutePath === null)
120
+ continue;
121
+ if (originals.has(action.absolutePath))
122
+ continue;
123
+ const existing = await fs
124
+ .readFile(action.absolutePath, "utf8")
125
+ .catch(() => null);
126
+ originals.set(action.absolutePath, existing);
127
+ }
128
+ return originals;
129
+ }
130
+ /**
131
+ * Best-effort restore. Iterates captured originals; restores content or rm's
132
+ * previously-absent files. Collects failure messages but continues (rollback-soldier
133
+ * pattern: partial recovery > aborting mid-rollback).
134
+ */
135
+ async function rollbackOriginals(originals) {
136
+ const failures = [];
137
+ for (const [absolutePath, content] of originals) {
138
+ try {
139
+ if (content === null) {
140
+ await fs.rm(absolutePath, { force: true });
141
+ }
142
+ else {
143
+ await fs.writeFile(absolutePath, content, "utf8");
144
+ }
145
+ }
146
+ catch (error) {
147
+ failures.push(`${absolutePath}: ${error instanceof Error ? error.message : String(error)}`);
148
+ }
149
+ }
150
+ return failures;
151
+ }
152
+ function formatError(error) {
153
+ return error instanceof Error ? error.message : String(error);
154
+ }
155
+ //# sourceMappingURL=self-update-mechanics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-update-mechanics.js","sourceRoot":"","sources":["../src/self-update-mechanics.ts"],"names":[],"mappings":"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"}
@@ -11,13 +11,13 @@
11
11
  }
12
12
  },
13
13
  "dependencies": {
14
- "@gdh/authoring": "0.5.0",
15
- "@gdh/core": "0.5.0",
16
- "@gdh/docs": "0.5.0",
17
- "@gdh/observability": "0.5.0",
18
- "@gdh/runtime": "0.5.0",
19
- "@gdh/scan": "0.5.0",
20
- "@gdh/verify": "0.5.0"
14
+ "@gdh/authoring": "0.6.0",
15
+ "@gdh/core": "0.6.0",
16
+ "@gdh/docs": "0.6.0",
17
+ "@gdh/observability": "0.6.0",
18
+ "@gdh/runtime": "0.6.0",
19
+ "@gdh/scan": "0.6.0",
20
+ "@gdh/verify": "0.6.0"
21
21
  },
22
- "version": "0.5.0"
22
+ "version": "0.6.0"
23
23
  }
@@ -6,6 +6,7 @@ export declare function runAuthoringCheck(input: {
6
6
  readonly projectConfig: GdhProjectConfig | null;
7
7
  }): Promise<GdhAuthoringCheckResult>;
8
8
  export { hasCompleteOnboardingSurface, parseProjectConfigYaml, readProjectConfig, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, resolveConfiguredCapabilities, resolveTargetGodotDocsVersion, } from "./project.js";
9
+ export { writePinnedVersion } from "./writePinnedVersion.js";
9
10
  export { getManagedLspStatus, resetManagedLspTestState, runManagedAuthoringCheck, } from "./lsp.js";
10
11
  export { inspectCacheState, pruneCacheState, resolveCacheNamespace } from "./cache.js";
11
12
  export { runImportRefresh, runTargetPrepare } from "./prepare.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAOnB,eAAO,MAAM,gBAAgB,wCAM3B,CAAC;AAEH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjD,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAqBnC;AAED,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EACtB,MAAM,WAAW,CAAC;AAOnB,eAAO,MAAM,gBAAgB,wCAM3B,CAAC;AAEH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,QAAQ,CAAC,aAAa,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjD,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAqBnC;AAED,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -30,6 +30,7 @@ export async function runAuthoringCheck(input) {
30
30
  });
31
31
  }
32
32
  export { hasCompleteOnboardingSurface, parseProjectConfigYaml, readProjectConfig, resolvePinnedVersion, resolvePinnedVersionOrNull, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, resolveConfiguredCapabilities, resolveTargetGodotDocsVersion, } from "./project.js";
33
+ export { writePinnedVersion } from "./writePinnedVersion.js";
33
34
  export { getManagedLspStatus, resetManagedLspTestState, runManagedAuthoringCheck, } from "./lsp.js";
34
35
  export { inspectCacheState, pruneCacheState, resolveCacheNamespace } from "./cache.js";
35
36
  export { runImportRefresh, runTargetPrepare } from "./prepare.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAItB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;IACpD,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY;IACnB,cAAc,EACZ,kGAAkG;IACpG,2BAA2B,EAAE,CAAC,WAAW,CAAC;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAIvC;IACC,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC;QAC1C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,qBAAqB;KAC7B,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,wBAAwB,CAAC;QAChD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS;KACV,CAAC,CAAC;IAEH,OAAO,0BAA0B,CAAC;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,UAAU;KACnB,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,GAItB,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AACnG,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAEzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,qBAAqB,CAAC;IACpD,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,YAAY;IACnB,cAAc,EACZ,kGAAkG;IACpG,2BAA2B,EAAE,CAAC,WAAW,CAAC;CAC3C,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAIvC;IACC,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC;QAC1C,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,KAAK,EAAE,qBAAqB;KAC7B,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,MAAM,wBAAwB,CAAC;QAChD,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,SAAS;KACV,CAAC,CAAC;IAEH,OAAO,0BAA0B,CAAC;QAChC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,MAAM,EAAE,UAAU;KACnB,CAAC,CAAC;AACL,CAAC;AAED,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,EAC7B,6BAA6B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Replaces the EXISTING `gdh_version` line in `.gdh/project.yaml` with a new pin.
3
+ * Distinct from `rewriteProjectConfig` (packages/cli/src/migrate.ts:843), which
4
+ * ONLY adds the field when missing. Phase 12 MIG-01: self-update needs the
5
+ * update-existing path; `gdh migrate` stays pin-preserving.
6
+ *
7
+ * Atomicity: writes temp file + fs.rename. POSIX guarantees rename atomicity
8
+ * within a single filesystem. Keep `.tmp-<pid>` sibling to the final path so
9
+ * both live in `.gdh/` — crossing filesystems fails with EXDEV.
10
+ *
11
+ * Throws:
12
+ * - Error (/exact SemVer/) when newVersion does not match EXACT_SEMVER_PATTERN
13
+ * - Error (/gdh migrate --apply/) when .gdh/project.yaml is missing gdh_version
14
+ * - underlying fs errors (ENOENT on missing .gdh/project.yaml, EACCES, etc.)
15
+ */
16
+ export declare function writePinnedVersion(targetPath: string, newVersion: string): Promise<void>;
17
+ //# sourceMappingURL=writePinnedVersion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writePinnedVersion.d.ts","sourceRoot":"","sources":["../src/writePinnedVersion.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC9F"}
@@ -0,0 +1,50 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { EXACT_SEMVER_PATTERN } from "./project.js";
4
+ /**
5
+ * Replaces the EXISTING `gdh_version` line in `.gdh/project.yaml` with a new pin.
6
+ * Distinct from `rewriteProjectConfig` (packages/cli/src/migrate.ts:843), which
7
+ * ONLY adds the field when missing. Phase 12 MIG-01: self-update needs the
8
+ * update-existing path; `gdh migrate` stays pin-preserving.
9
+ *
10
+ * Atomicity: writes temp file + fs.rename. POSIX guarantees rename atomicity
11
+ * within a single filesystem. Keep `.tmp-<pid>` sibling to the final path so
12
+ * both live in `.gdh/` — crossing filesystems fails with EXDEV.
13
+ *
14
+ * Throws:
15
+ * - Error (/exact SemVer/) when newVersion does not match EXACT_SEMVER_PATTERN
16
+ * - Error (/gdh migrate --apply/) when .gdh/project.yaml is missing gdh_version
17
+ * - underlying fs errors (ENOENT on missing .gdh/project.yaml, EACCES, etc.)
18
+ */
19
+ export async function writePinnedVersion(targetPath, newVersion) {
20
+ if (!EXACT_SEMVER_PATTERN.test(newVersion)) {
21
+ throw new Error(`Cannot pin \`gdh_version\`: ${JSON.stringify(newVersion)} is not an exact SemVer. ` +
22
+ "Ranges (^, ~), dist-tags (latest, next), and local paths are rejected.");
23
+ }
24
+ const configPath = path.join(targetPath, ".gdh/project.yaml");
25
+ const original = await fs.readFile(configPath, "utf8");
26
+ // Mirror the EXACT regex migrate.ts:843 uses to DETECT the pin; inverted guard here.
27
+ if (!/^gdh_version:/m.test(original)) {
28
+ throw new Error(".gdh/project.yaml is missing the `gdh_version` field. " +
29
+ "Run `gdh migrate --apply` to bootstrap the pin before invoking self-update.");
30
+ }
31
+ // JSON.stringify produces "<v>" (double-quoted) — matches migrate.ts:845 wire format
32
+ // and parseProjectConfigYaml expectations (project.ts:461 parseYamlStringValue).
33
+ const updated = original.replace(/^gdh_version:.*\n/m, `gdh_version: ${JSON.stringify(newVersion)}\n`);
34
+ if (updated === original) {
35
+ // Defense-in-depth no-op: caller (bumpAndRebakePin in Plan 02) must detect
36
+ // this upstream via resolvePinnedVersion comparison to emit state: "noop".
37
+ return;
38
+ }
39
+ const tempPath = `${configPath}.tmp-${process.pid}`;
40
+ await fs.writeFile(tempPath, updated, "utf8");
41
+ try {
42
+ await fs.rename(tempPath, configPath);
43
+ }
44
+ catch (error) {
45
+ // Best-effort temp-file cleanup on rename failure; swallow secondary errors.
46
+ await fs.rm(tempPath, { force: true }).catch(() => { });
47
+ throw error;
48
+ }
49
+ }
50
+ //# sourceMappingURL=writePinnedVersion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writePinnedVersion.js","sourceRoot":"","sources":["../src/writePinnedVersion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,UAAkB,EAAE,UAAkB;IAC7E,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,+BAA+B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,2BAA2B;YAClF,wEAAwE,CAC3E,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEvD,qFAAqF;IACrF,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,wDAAwD;YACtD,6EAA6E,CAChF,CAAC;IACJ,CAAC;IAED,qFAAqF;IACrF,iFAAiF;IACjF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAC9B,oBAAoB,EACpB,gBAAgB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAC/C,CAAC;IAEF,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,2EAA2E;QAC3E,2EAA2E;QAC3E,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,UAAU,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;IACpD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,6EAA6E;QAC7E,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACvD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -10,8 +10,11 @@
10
10
  "import": "./dist/index.js"
11
11
  }
12
12
  },
13
+ "scripts": {
14
+ "test": "vitest run"
15
+ },
13
16
  "dependencies": {
14
- "@gdh/core": "0.5.0"
17
+ "@gdh/core": "0.6.0"
15
18
  },
16
- "version": "0.5.0"
19
+ "version": "0.6.0"
17
20
  }
@@ -1,7 +1,22 @@
1
+ import { recordAuthoringSessionEvent } from "@gdh/observability";
1
2
  export declare const cliPackage: import("@gdh/core").GdhPackageBoundary;
2
3
  export interface CliIo {
3
4
  readonly stdout: Pick<NodeJS.WriteStream, "write">;
4
5
  readonly stderr: Pick<NodeJS.WriteStream, "write">;
5
6
  }
6
7
  export declare function runCli(args: readonly string[], io?: CliIo): Promise<number>;
8
+ export declare function writeJsonResult(io: CliIo, value: unknown, options?: {
9
+ readonly presentRuntimeTerms?: boolean;
10
+ }): void;
11
+ export declare function formatCliError(error: unknown): string;
12
+ export declare function readSingleOptionValue(args: readonly string[], optionName: string): string | null;
13
+ export declare function findUnsupportedOptionsError(args: readonly string[], options: {
14
+ readonly usage: string;
15
+ readonly optionsWithValues?: readonly string[];
16
+ readonly booleanOptions?: readonly string[];
17
+ }): string | null;
18
+ export declare function recordSessionEvent(targetPath: string, input: Parameters<typeof recordAuthoringSessionEvent>[1] & {
19
+ readonly commandStartedAtMs?: number;
20
+ }): Promise<void>;
21
+ export declare function extractPositionalArgs(args: readonly string[], optionsWithValues: ReadonlySet<string>): readonly string[];
7
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAsHA,eAAO,MAAM,UAAU,wCAerB,CAAC;AAEH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACpD;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAE,KAA0D,GAC7D,OAAO,CAAC,MAAM,CAAC,CA2GjB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyEA,OAAO,EAIL,2BAA2B,EAC5B,MAAM,oBAAoB,CAAC;AA2C5B,eAAO,MAAM,UAAU,wCAerB,CAAC;AAEH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACpD;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,GAAE,KAA0D,GAC7D,OAAO,CAAC,MAAM,CAAC,CA+GjB;AAED,wBAAgB,eAAe,CAC7B,EAAE,EAAE,KAAK,EACT,KAAK,EAAE,OAAO,EACd,OAAO,GAAE;IAAE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAO,GACvD,IAAI,CAGN;AAg8ID,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAkFD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAchG;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;IACP,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C,GACA,MAAM,GAAG,IAAI,CAcf;AA8ED,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,UAAU,CAAC,OAAO,2BAA2B,CAAC,CAAC,CAAC,CAAC,GAAG;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC,GACA,OAAO,CAAC,IAAI,CAAC,CAef;AAwFD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAAC,GACrC,SAAS,MAAM,EAAE,CAuBnB"}
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
- import { buildGdhStatusResult, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, CODEX_CHECK_SKILL_RELATIVE_PATH, CODEX_MIGRATE_SKILL_RELATIVE_PATH, CODEX_ONBOARD_SKILL_RELATIVE_PATH, CODEX_PREPARE_SKILL_RELATIVE_PATH, CODEX_STATUS_SKILL_RELATIVE_PATH, CODEX_VERIFY_SKILL_RELATIVE_PATH, createGsdSnapshot, CURSOR_CHECK_SKILL_RELATIVE_PATH, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, CURSOR_PREPARE_SKILL_RELATIVE_PATH, CURSOR_STATUS_SKILL_RELATIVE_PATH, CURSOR_VERIFY_SKILL_RELATIVE_PATH, getSupportedAgentAdaptersStatus, installSupportedAgentAdapters, MCP_LAUNCHER_RELATIVE_PATH, } from "@gdh/adapters";
4
+ import { buildGdhStatusResult, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, CODEX_CHECK_SKILL_RELATIVE_PATH, CODEX_MIGRATE_SKILL_RELATIVE_PATH, CODEX_ONBOARD_SKILL_RELATIVE_PATH, CODEX_PREPARE_SKILL_RELATIVE_PATH, CODEX_STATUS_SKILL_RELATIVE_PATH, CODEX_VERIFY_SKILL_RELATIVE_PATH, createGsdSnapshot, CURSOR_CHECK_SKILL_RELATIVE_PATH, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, CURSOR_PREPARE_SKILL_RELATIVE_PATH, CURSOR_STATUS_SKILL_RELATIVE_PATH, CURSOR_VERIFY_SKILL_RELATIVE_PATH, getSupportedAgentAdaptersStatus, installSupportedAgentAdapters, MCP_LAUNCHER_RELATIVE_PATH, } from "@gdh/adapters";
5
5
  import { getManagedLspStatus, hasCompleteOnboardingSurface, inspectCacheState, pruneCacheState, readProjectConfig, resolvePinnedVersion, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, resolveTargetGodotDocsVersion, runAuthoringCheck, runImportRefresh, runTargetPrepare, runWarmup, } from "@gdh/authoring";
6
6
  import { definePackageBoundary, GDH_AUTHORING_DOGFOOD_VERSION, GDH_AUTHORING_SLICE_REPORT_VERSION, GDH_PRODUCT_NAME, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
7
7
  import { fetchOfficialGodotDoc, getGuidanceStatus, resolveGuidanceQuery, searchOfficialGodotDocs, } from "@gdh/docs";
@@ -12,7 +12,9 @@ import { applyRepairableOnboardingWrites, onboardGodotProject, persistInventoryF
12
12
  import { evaluateDonePolicy, exerciseRuntimeCorpusEntry, inspectRuntimeCorpusStatus, inspectRuntimeVerificationBundleState, inspectRuntimeVerificationReadiness, listRuntimeScenarios, materializeRuntimeCorpusEntry, recommendValidationForChange, recordRuntimeCorpusValidation, runRuntimeVerificationScenario, showRuntimeScenario, } from "@gdh/verify";
13
13
  import { migrateProjectLifecycleSurface } from "./migrate.js";
14
14
  import { presentPublicRuntimeTerms } from "./public-terms.js";
15
+ import { runSelfUpdateCommand } from "./self-update.js";
15
16
  import { executeSetupCommand, isSetupCanceledError, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
17
+ import { emitUpdateBannerIfStale } from "./update-banner.js";
16
18
  export const cliPackage = definePackageBoundary({
17
19
  name: "@gdh/cli",
18
20
  layer: "surface",
@@ -102,6 +104,9 @@ export async function runCli(args, io = { stdout: process.stdout, stderr: proces
102
104
  if (command === "migrate") {
103
105
  return runMigrateCommand(rest, io);
104
106
  }
107
+ if (command === "self-update") {
108
+ return runSelfUpdateCommand(rest, io);
109
+ }
105
110
  if (command === "cache") {
106
111
  return runCacheCommand(rest, io);
107
112
  }
@@ -111,7 +116,7 @@ export async function runCli(args, io = { stdout: process.stdout, stderr: proces
111
116
  io.stderr.write(`Unknown command: ${command}\n\n${renderHelp()}`);
112
117
  return 1;
113
118
  }
114
- function writeJsonResult(io, value, options = {}) {
119
+ export function writeJsonResult(io, value, options = {}) {
115
120
  const output = options.presentRuntimeTerms ? presentPublicRuntimeTerms(value) : value;
116
121
  io.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
117
122
  }
@@ -386,6 +391,11 @@ async function runStatusCommand(args, io) {
386
391
  }
387
392
  const targetPath = parsedTarget.targetPath;
388
393
  const commandStartedAtMs = Date.now();
394
+ // UPD-04: emit the update banner to stderr BEFORE primary work so the
395
+ // stderr prelude precedes any stdout JSON payload. D-13 scopes the banner
396
+ // to `gdh status` and `gdh verify` only. Silent when cache is null /
397
+ // current / offline / dev-mode (D-06).
398
+ await emitUpdateBannerIfStale(targetPath, io);
389
399
  try {
390
400
  const status = await buildGdhStatusResult(targetPath);
391
401
  await recordSessionEvent(targetPath, {
@@ -1257,6 +1267,16 @@ async function runVerifyCommand(args, io) {
1257
1267
  ].join("\n") + "\n");
1258
1268
  return 0;
1259
1269
  }
1270
+ // UPD-04: emit the update banner to stderr BEFORE dispatching to verify
1271
+ // subcommands so the stderr prelude precedes any stdout JSON payload. D-13
1272
+ // scopes the banner to `gdh status` and `gdh verify` only. Target for the
1273
+ // banner's pre-onboard re-check is the first non-flag positional arg
1274
+ // after the subcommand (falling back to "."). The cache itself is per-user,
1275
+ // not per-target, so any resolvable path suffices for the dev-mode check.
1276
+ {
1277
+ const verifyTargetPath = rest.find((arg) => !arg.startsWith("--")) ?? ".";
1278
+ await emitUpdateBannerIfStale(verifyTargetPath, io);
1279
+ }
1260
1280
  if (subcommand === "recommend") {
1261
1281
  return runVerifyRecommendCommand(rest, io);
1262
1282
  }
@@ -2541,6 +2561,46 @@ const VERIFY_DRIFT_SCANNED_FILES = [
2541
2561
  { relativePath: CLAUDE_CHECK_COMMAND_RELATIVE_PATH, description: "Claude gdh/check command" },
2542
2562
  { relativePath: CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, description: "Claude gdh/prepare command" },
2543
2563
  { relativePath: CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, description: "Claude gdh/verify command" },
2564
+ // Phase 12 extension — close the Phase 11 coverage gap (research §Baked Version Surface Inventory rows 26-28).
2565
+ // These files are re-baked at pin time and must be audited by MIG-02's post-condition invariant.
2566
+ //
2567
+ // SessionStart hook: bakes `GDH_PINNED_VERSION: "<semver>"` (not an npx literal). Uses a
2568
+ // dedicated versionRegex to extract the pin from that env-injection pattern.
2569
+ {
2570
+ relativePath: CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH,
2571
+ description: "Claude SessionStart update hook",
2572
+ // The hook body sets GDH_PINNED_VERSION: "<semver>" in the spawned worker's env.
2573
+ // VERIFY_DRIFT_BAKED_VERSION_REGEX matches `@skillcap/gdh@<v>` npx literals; this
2574
+ // supplementary regex extracts the pin from the env-injection literal instead.
2575
+ versionRegex: /GDH_PINNED_VERSION:\s*"(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)"/,
2576
+ },
2577
+ // Intentionally excluded: the Claude background worker (gdh-check-update-worker.js) — the
2578
+ // worker script body reads GDH_PINNED_VERSION from process.env at runtime and does NOT contain
2579
+ // an `@skillcap/gdh@<v>` literal or any other baked-version pattern. Adding it would cause
2580
+ // VERIFY_DRIFT_BAKED_VERSION_REGEX to report `no_baked_version` → false positive. Worker drift
2581
+ // is audited via the `// gdh-hook-version: N` marker through the renderer-layer contract, not
2582
+ // via this version-literal scanner. Covered in integration tests at
2583
+ // packages/adapters/src/claude-update-install-integration.test.ts.
2584
+ //
2585
+ // Intentionally excluded: the Claude statusline (gdh-statusline.js) — the statusline renderer
2586
+ // produces a version-agnostic script (reads the update cache at runtime; no semver literal baked
2587
+ // in the output). Adding it would permanently report `no_baked_version` → false positive. The
2588
+ // statusline IS re-baked on every `gdh adapters install` via the renderer pipeline, which ensures
2589
+ // it stays current with the hook version; pin-literal drift detection is not applicable here.
2590
+ //
2591
+ // Intentionally excluded: the Claude /gdh-update command (.claude/commands/gdh/update.md) —
2592
+ // the rendered command shells out to `npx -y @skillcap/gdh@latest self-update` (LITERAL @latest,
2593
+ // not @<pinnedVersion>). The shellout MUST bake @latest so the NEW CLI performs the update,
2594
+ // not the OLD (potentially buggy) pinned one. Because @latest is not a semver literal, the
2595
+ // VERIFY_DRIFT_BAKED_VERSION_REGEX finds no pinned-version match and would permanently report
2596
+ // `no_baked_version` → false positive. Phase 13 D-13 locks this exclusion; Check 44 in
2597
+ // scripts/validate-docs.mjs enforces both the @latest invariant and the exclusion.
2598
+ //
2599
+ // Intentionally excluded: the Codex gdh-update skill (.codex/skills/gdh-update/SKILL.md) —
2600
+ // same rationale: renders @skillcap/gdh@latest, not @<pinnedVersion>. Phase 13 D-13.
2601
+ //
2602
+ // Intentionally excluded: the Cursor gdh-update skill (.cursor/skills/gdh-update/SKILL.md) —
2603
+ // same rationale: renders @skillcap/gdh@latest, not @<pinnedVersion>. Phase 13 D-13.
2544
2604
  ];
2545
2605
  // Mirrors EXACT_SEMVER_PATTERN in @gdh/authoring so only well-formed SemVer
2546
2606
  // values match — drift check does not pick up unrelated doc prose.
@@ -2608,7 +2668,7 @@ async function runVerifyDriftCommand(args, io) {
2608
2668
  reason: "file_missing",
2609
2669
  };
2610
2670
  }
2611
- const match = content.match(VERIFY_DRIFT_BAKED_VERSION_REGEX);
2671
+ const match = content.match(file.versionRegex ?? VERIFY_DRIFT_BAKED_VERSION_REGEX);
2612
2672
  const baked = match?.[1] ?? null;
2613
2673
  const reason = baked === null
2614
2674
  ? "no_baked_version"
@@ -3733,7 +3793,7 @@ function renderHelp() {
3733
3793
  "Run `gdh <command> --help` for command-specific usage.",
3734
3794
  ].join("\n") + "\n");
3735
3795
  }
3736
- function formatCliError(error) {
3796
+ export function formatCliError(error) {
3737
3797
  return error instanceof Error ? error.message : String(error);
3738
3798
  }
3739
3799
  function resolveCachePruneScope(args) {
@@ -3791,7 +3851,7 @@ function collectAssignmentOptionValues(args, optionName) {
3791
3851
  }
3792
3852
  return assignments;
3793
3853
  }
3794
- function readSingleOptionValue(args, optionName) {
3854
+ export function readSingleOptionValue(args, optionName) {
3795
3855
  const index = args.indexOf(optionName);
3796
3856
  if (index === -1) {
3797
3857
  return null;
@@ -3802,7 +3862,7 @@ function readSingleOptionValue(args, optionName) {
3802
3862
  }
3803
3863
  return value;
3804
3864
  }
3805
- function findUnsupportedOptionsError(args, options) {
3865
+ export function findUnsupportedOptionsError(args, options) {
3806
3866
  const supportedOptions = new Set([
3807
3867
  ...(options.optionsWithValues ?? []),
3808
3868
  ...(options.booleanOptions ?? []),
@@ -3864,7 +3924,7 @@ function buildGuidanceSnapshot(result) {
3864
3924
  recommendedUnitIds: result.recommendedUnits.map((unit) => unit.id),
3865
3925
  };
3866
3926
  }
3867
- async function recordSessionEvent(targetPath, input) {
3927
+ export async function recordSessionEvent(targetPath, input) {
3868
3928
  try {
3869
3929
  const { commandStartedAtMs, ...eventInput } = input;
3870
3930
  const startedAt = typeof commandStartedAtMs === "number" && Number.isFinite(commandStartedAtMs)
@@ -3939,7 +3999,7 @@ function extractGuidanceResolvePositionalArgs(args) {
3939
3999
  function extractRecipePositionalArgs(args) {
3940
4000
  return extractPositionalArgs(args, new Set(["--provider", "--param", "--feature", "--no-feature", "--env"]));
3941
4001
  }
3942
- function extractPositionalArgs(args, optionsWithValues) {
4002
+ export function extractPositionalArgs(args, optionsWithValues) {
3943
4003
  const positionalArgs = [];
3944
4004
  for (let index = 0; index < args.length; index += 1) {
3945
4005
  const arg = args[index];