@skillcap/gdh 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL-BUNDLE.json +1 -1
- package/README.md +66 -85
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts +74 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +158 -0
- package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts +51 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.js +80 -0
- package/node_modules/@gdh/adapters/dist/claude-statusline-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts +35 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js +76 -0
- package/node_modules/@gdh/adapters/dist/claude-update-hook-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts +28 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js +99 -0
- package/node_modules/@gdh/adapters/dist/claude-update-worker-render.js.map +1 -0
- package/node_modules/@gdh/adapters/dist/index.d.ts +12 -2
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +382 -244
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts +51 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts.map +1 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js +155 -0
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js.map +1 -0
- package/node_modules/@gdh/adapters/package.json +8 -8
- package/node_modules/@gdh/authoring/dist/index.d.ts +1 -0
- package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/index.js +1 -0
- package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.d.ts +17 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.d.ts.map +1 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.js +50 -0
- package/node_modules/@gdh/authoring/dist/writePinnedVersion.js.map +1 -0
- package/node_modules/@gdh/authoring/package.json +5 -2
- package/node_modules/@gdh/cli/dist/index.d.ts +15 -0
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +119 -20
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.js +44 -3
- package/node_modules/@gdh/cli/dist/migrate.js.map +1 -1
- package/node_modules/@gdh/cli/dist/self-update.d.ts +3 -0
- package/node_modules/@gdh/cli/dist/self-update.d.ts.map +1 -0
- package/node_modules/@gdh/cli/dist/self-update.js +235 -0
- package/node_modules/@gdh/cli/dist/self-update.js.map +1 -0
- package/node_modules/@gdh/cli/dist/update-banner.d.ts +42 -0
- package/node_modules/@gdh/cli/dist/update-banner.d.ts.map +1 -0
- package/node_modules/@gdh/cli/dist/update-banner.js +49 -0
- package/node_modules/@gdh/cli/dist/update-banner.js.map +1 -0
- package/node_modules/@gdh/cli/package.json +10 -10
- package/node_modules/@gdh/core/dist/dev-mode.d.ts +13 -0
- package/node_modules/@gdh/core/dist/dev-mode.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/dev-mode.js +21 -0
- package/node_modules/@gdh/core/dist/dev-mode.js.map +1 -0
- package/node_modules/@gdh/core/dist/index.d.ts +9 -4
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +8 -5
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/dist/update-cache.d.ts +46 -0
- package/node_modules/@gdh/core/dist/update-cache.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/update-cache.js +90 -0
- package/node_modules/@gdh/core/dist/update-cache.js.map +1 -0
- package/node_modules/@gdh/core/dist/update-probe.d.ts +102 -0
- package/node_modules/@gdh/core/dist/update-probe.d.ts.map +1 -0
- package/node_modules/@gdh/core/dist/update-probe.js +195 -0
- package/node_modules/@gdh/core/dist/update-probe.js.map +1 -0
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/package.json +2 -2
- package/node_modules/@gdh/mcp/dist/index.d.ts +20 -0
- package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/mcp/dist/index.js +39 -2
- package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
- package/node_modules/@gdh/mcp/package.json +8 -8
- package/node_modules/@gdh/observability/dist/guidance-audit.js +2 -1
- package/node_modules/@gdh/observability/dist/guidance-audit.js.map +1 -1
- package/node_modules/@gdh/observability/package.json +2 -2
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/package.json +3 -3
- package/node_modules/@gdh/verify/package.json +7 -7
- 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.
|
|
15
|
-
"@gdh/core": "0.
|
|
16
|
-
"@gdh/docs": "0.
|
|
17
|
-
"@gdh/observability": "0.
|
|
18
|
-
"@gdh/runtime": "0.
|
|
19
|
-
"@gdh/scan": "0.
|
|
20
|
-
"@gdh/verify": "0.
|
|
14
|
+
"@gdh/authoring": "0.7.0",
|
|
15
|
+
"@gdh/core": "0.7.0",
|
|
16
|
+
"@gdh/docs": "0.7.0",
|
|
17
|
+
"@gdh/observability": "0.7.0",
|
|
18
|
+
"@gdh/runtime": "0.7.0",
|
|
19
|
+
"@gdh/scan": "0.7.0",
|
|
20
|
+
"@gdh/verify": "0.7.0"
|
|
21
21
|
},
|
|
22
|
-
"version": "0.
|
|
22
|
+
"version": "0.7.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"}
|
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA2EA,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;AAy+ID,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,10 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
1
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import fsSync from "node:fs";
|
|
2
4
|
import os from "node:os";
|
|
3
5
|
import path from "node:path";
|
|
4
|
-
import {
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
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, } from "@gdh/adapters";
|
|
5
8
|
import { getManagedLspStatus, hasCompleteOnboardingSurface, inspectCacheState, pruneCacheState, readProjectConfig, resolvePinnedVersion, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, resolveTargetGodotDocsVersion, runAuthoringCheck, runImportRefresh, runTargetPrepare, runWarmup, } from "@gdh/authoring";
|
|
6
9
|
import { definePackageBoundary, GDH_AUTHORING_DOGFOOD_VERSION, GDH_AUTHORING_SLICE_REPORT_VERSION, GDH_PRODUCT_NAME, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
|
|
7
10
|
import { fetchOfficialGodotDoc, getGuidanceStatus, resolveGuidanceQuery, searchOfficialGodotDocs, } from "@gdh/docs";
|
|
@@ -12,7 +15,9 @@ import { applyRepairableOnboardingWrites, onboardGodotProject, persistInventoryF
|
|
|
12
15
|
import { evaluateDonePolicy, exerciseRuntimeCorpusEntry, inspectRuntimeCorpusStatus, inspectRuntimeVerificationBundleState, inspectRuntimeVerificationReadiness, listRuntimeScenarios, materializeRuntimeCorpusEntry, recommendValidationForChange, recordRuntimeCorpusValidation, runRuntimeVerificationScenario, showRuntimeScenario, } from "@gdh/verify";
|
|
13
16
|
import { migrateProjectLifecycleSurface } from "./migrate.js";
|
|
14
17
|
import { presentPublicRuntimeTerms } from "./public-terms.js";
|
|
18
|
+
import { runSelfUpdateCommand } from "./self-update.js";
|
|
15
19
|
import { executeSetupCommand, isSetupCanceledError, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
|
|
20
|
+
import { emitUpdateBannerIfStale } from "./update-banner.js";
|
|
16
21
|
export const cliPackage = definePackageBoundary({
|
|
17
22
|
name: "@gdh/cli",
|
|
18
23
|
layer: "surface",
|
|
@@ -102,6 +107,9 @@ export async function runCli(args, io = { stdout: process.stdout, stderr: proces
|
|
|
102
107
|
if (command === "migrate") {
|
|
103
108
|
return runMigrateCommand(rest, io);
|
|
104
109
|
}
|
|
110
|
+
if (command === "self-update") {
|
|
111
|
+
return runSelfUpdateCommand(rest, io);
|
|
112
|
+
}
|
|
105
113
|
if (command === "cache") {
|
|
106
114
|
return runCacheCommand(rest, io);
|
|
107
115
|
}
|
|
@@ -111,7 +119,7 @@ export async function runCli(args, io = { stdout: process.stdout, stderr: proces
|
|
|
111
119
|
io.stderr.write(`Unknown command: ${command}\n\n${renderHelp()}`);
|
|
112
120
|
return 1;
|
|
113
121
|
}
|
|
114
|
-
function writeJsonResult(io, value, options = {}) {
|
|
122
|
+
export function writeJsonResult(io, value, options = {}) {
|
|
115
123
|
const output = options.presentRuntimeTerms ? presentPublicRuntimeTerms(value) : value;
|
|
116
124
|
io.stdout.write(`${JSON.stringify(output, null, 2)}\n`);
|
|
117
125
|
}
|
|
@@ -386,6 +394,11 @@ async function runStatusCommand(args, io) {
|
|
|
386
394
|
}
|
|
387
395
|
const targetPath = parsedTarget.targetPath;
|
|
388
396
|
const commandStartedAtMs = Date.now();
|
|
397
|
+
// UPD-04: emit the update banner to stderr BEFORE primary work so the
|
|
398
|
+
// stderr prelude precedes any stdout JSON payload. D-13 scopes the banner
|
|
399
|
+
// to `gdh status` and `gdh verify` only. Silent when cache is null /
|
|
400
|
+
// current / offline / dev-mode (D-06).
|
|
401
|
+
await emitUpdateBannerIfStale(targetPath, io);
|
|
389
402
|
try {
|
|
390
403
|
const status = await buildGdhStatusResult(targetPath);
|
|
391
404
|
await recordSessionEvent(targetPath, {
|
|
@@ -1249,7 +1262,7 @@ async function runVerifyCommand(args, io) {
|
|
|
1249
1262
|
" corpus <status|record>",
|
|
1250
1263
|
" Inspect or record runtime corpus release-readiness evidence as JSON.",
|
|
1251
1264
|
" drift [target]",
|
|
1252
|
-
" Check whether baked `@skillcap/gdh@<version>` literals (
|
|
1265
|
+
" Check whether baked `@skillcap/gdh@<version>` literals (skills + commands) match .gdh/project.yaml gdh_version.",
|
|
1253
1266
|
" recommend [target] --files <path> [--files <path>...]",
|
|
1254
1267
|
" Recommend authoring-first validation requirements for the supplied change set.",
|
|
1255
1268
|
" done [target] --files <path> [--files <path>...] [--performed <kind>]",
|
|
@@ -1257,6 +1270,16 @@ async function runVerifyCommand(args, io) {
|
|
|
1257
1270
|
].join("\n") + "\n");
|
|
1258
1271
|
return 0;
|
|
1259
1272
|
}
|
|
1273
|
+
// UPD-04: emit the update banner to stderr BEFORE dispatching to verify
|
|
1274
|
+
// subcommands so the stderr prelude precedes any stdout JSON payload. D-13
|
|
1275
|
+
// scopes the banner to `gdh status` and `gdh verify` only. Target for the
|
|
1276
|
+
// banner's pre-onboard re-check is the first non-flag positional arg
|
|
1277
|
+
// after the subcommand (falling back to "."). The cache itself is per-user,
|
|
1278
|
+
// not per-target, so any resolvable path suffices for the dev-mode check.
|
|
1279
|
+
{
|
|
1280
|
+
const verifyTargetPath = rest.find((arg) => !arg.startsWith("--")) ?? ".";
|
|
1281
|
+
await emitUpdateBannerIfStale(verifyTargetPath, io);
|
|
1282
|
+
}
|
|
1260
1283
|
if (subcommand === "recommend") {
|
|
1261
1284
|
return runVerifyRecommendCommand(rest, io);
|
|
1262
1285
|
}
|
|
@@ -2078,29 +2101,30 @@ async function runMcpManifestCommand(args, io) {
|
|
|
2078
2101
|
async function runMcpServeCommand(args, io) {
|
|
2079
2102
|
if (args.includes("--help")) {
|
|
2080
2103
|
io.stdout.write([
|
|
2081
|
-
"Usage: gdh mcp serve --target <path>",
|
|
2104
|
+
"Usage: gdh mcp serve [--target <path>]",
|
|
2082
2105
|
"",
|
|
2083
|
-
"Run the real GDH stdio MCP server
|
|
2106
|
+
"Run the real GDH stdio MCP server. When --target is omitted, defaults to",
|
|
2107
|
+
"the current working directory and walks up to find the nearest .gdh/project.yaml.",
|
|
2084
2108
|
].join("\n") + "\n");
|
|
2085
2109
|
return 0;
|
|
2086
2110
|
}
|
|
2087
2111
|
const unsupportedOptionsError = findUnsupportedOptionsError(args, {
|
|
2088
|
-
usage: "Usage: gdh mcp serve --target <path
|
|
2112
|
+
usage: "Usage: gdh mcp serve [--target <path>]\n",
|
|
2089
2113
|
optionsWithValues: ["--target"],
|
|
2090
2114
|
});
|
|
2091
2115
|
if (unsupportedOptionsError !== null) {
|
|
2092
2116
|
io.stderr.write(unsupportedOptionsError);
|
|
2093
2117
|
return 1;
|
|
2094
2118
|
}
|
|
2095
|
-
const targetPath = readSingleOptionValue(args, "--target");
|
|
2096
|
-
if (targetPath === null) {
|
|
2097
|
-
io.stderr.write("Usage error: gdh mcp serve requires --target <path>.\n");
|
|
2098
|
-
return 1;
|
|
2099
|
-
}
|
|
2100
2119
|
if (extractPositionalArgs(args, new Set(["--target"])).length > 0) {
|
|
2101
2120
|
io.stderr.write("Usage error: gdh mcp serve accepts only --target <path>.\n");
|
|
2102
2121
|
return 1;
|
|
2103
2122
|
}
|
|
2123
|
+
const targetPath = readSingleOptionValue(args, "--target") ?? process.cwd();
|
|
2124
|
+
const devRepoExitCode = maybeReexecIntoDevRepo(targetPath);
|
|
2125
|
+
if (devRepoExitCode !== null) {
|
|
2126
|
+
return devRepoExitCode;
|
|
2127
|
+
}
|
|
2104
2128
|
try {
|
|
2105
2129
|
await serveMcpOverStdio(targetPath);
|
|
2106
2130
|
return 0;
|
|
@@ -2110,6 +2134,42 @@ async function runMcpServeCommand(args, io) {
|
|
|
2110
2134
|
return 1;
|
|
2111
2135
|
}
|
|
2112
2136
|
}
|
|
2137
|
+
function maybeReexecIntoDevRepo(targetPath) {
|
|
2138
|
+
if (process.env["GDH_MCP_DEV_REEXEC"] === "1") {
|
|
2139
|
+
// Already running under a dev-repo re-exec; skip to avoid a loop.
|
|
2140
|
+
return null;
|
|
2141
|
+
}
|
|
2142
|
+
const envDevRepoPath = process.env["GDH_DEV_REPO"]?.trim() || null;
|
|
2143
|
+
const hintsPath = path.join(path.resolve(targetPath), ".gdh-state", "local-paths.json");
|
|
2144
|
+
let hintDevRepoPath = null;
|
|
2145
|
+
try {
|
|
2146
|
+
const raw = fsSync.readFileSync(hintsPath, "utf8");
|
|
2147
|
+
const parsed = JSON.parse(raw);
|
|
2148
|
+
if (typeof parsed.gdhDevRepoPath === "string" && parsed.gdhDevRepoPath.length > 0) {
|
|
2149
|
+
hintDevRepoPath = parsed.gdhDevRepoPath;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
catch {
|
|
2153
|
+
// No hints file or unparseable — fall through.
|
|
2154
|
+
}
|
|
2155
|
+
const devRepoPath = envDevRepoPath || hintDevRepoPath;
|
|
2156
|
+
if (devRepoPath === null) {
|
|
2157
|
+
return null;
|
|
2158
|
+
}
|
|
2159
|
+
const devCliEntry = path.join(devRepoPath, "packages/cli/dist/cli.js");
|
|
2160
|
+
if (!fsSync.existsSync(devCliEntry)) {
|
|
2161
|
+
return null;
|
|
2162
|
+
}
|
|
2163
|
+
const currentCliPath = path.resolve(fileURLToPath(import.meta.url));
|
|
2164
|
+
const resolvedDevRepoPath = path.resolve(devRepoPath);
|
|
2165
|
+
// Avoid loop if the currently-running CLI source already lives inside the
|
|
2166
|
+
// dev repo (e.g. contributor running the dev CLI directly via tsx).
|
|
2167
|
+
if (currentCliPath.startsWith(`${resolvedDevRepoPath}${path.sep}`)) {
|
|
2168
|
+
return null;
|
|
2169
|
+
}
|
|
2170
|
+
const result = spawnSync(process.execPath, [devCliEntry, "mcp", "serve", "--target", path.resolve(targetPath)], { stdio: "inherit", env: { ...process.env, GDH_MCP_DEV_REEXEC: "1" } });
|
|
2171
|
+
return result.status ?? 1;
|
|
2172
|
+
}
|
|
2113
2173
|
async function runMcpInvokeCommand(args, io) {
|
|
2114
2174
|
if (args.includes("--help")) {
|
|
2115
2175
|
io.stdout.write([
|
|
@@ -2522,7 +2582,6 @@ async function runVerifyReadinessCommand(args, io) {
|
|
|
2522
2582
|
}
|
|
2523
2583
|
}
|
|
2524
2584
|
const VERIFY_DRIFT_SCANNED_FILES = [
|
|
2525
|
-
{ relativePath: MCP_LAUNCHER_RELATIVE_PATH, description: "managed MCP launcher" },
|
|
2526
2585
|
{ relativePath: CODEX_ONBOARD_SKILL_RELATIVE_PATH, description: "Codex gdh-onboard skill" },
|
|
2527
2586
|
{ relativePath: CODEX_STATUS_SKILL_RELATIVE_PATH, description: "Codex gdh-status skill" },
|
|
2528
2587
|
{ relativePath: CODEX_MIGRATE_SKILL_RELATIVE_PATH, description: "Codex gdh-migrate skill" },
|
|
@@ -2541,6 +2600,46 @@ const VERIFY_DRIFT_SCANNED_FILES = [
|
|
|
2541
2600
|
{ relativePath: CLAUDE_CHECK_COMMAND_RELATIVE_PATH, description: "Claude gdh/check command" },
|
|
2542
2601
|
{ relativePath: CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, description: "Claude gdh/prepare command" },
|
|
2543
2602
|
{ relativePath: CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, description: "Claude gdh/verify command" },
|
|
2603
|
+
// Phase 12 extension — close the Phase 11 coverage gap (research §Baked Version Surface Inventory rows 26-28).
|
|
2604
|
+
// These files are re-baked at pin time and must be audited by MIG-02's post-condition invariant.
|
|
2605
|
+
//
|
|
2606
|
+
// SessionStart hook: bakes `GDH_PINNED_VERSION: "<semver>"` (not an npx literal). Uses a
|
|
2607
|
+
// dedicated versionRegex to extract the pin from that env-injection pattern.
|
|
2608
|
+
{
|
|
2609
|
+
relativePath: CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH,
|
|
2610
|
+
description: "Claude SessionStart update hook",
|
|
2611
|
+
// The hook body sets GDH_PINNED_VERSION: "<semver>" in the spawned worker's env.
|
|
2612
|
+
// VERIFY_DRIFT_BAKED_VERSION_REGEX matches `@skillcap/gdh@<v>` npx literals; this
|
|
2613
|
+
// supplementary regex extracts the pin from the env-injection literal instead.
|
|
2614
|
+
versionRegex: /GDH_PINNED_VERSION:\s*"(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?)"/,
|
|
2615
|
+
},
|
|
2616
|
+
// Intentionally excluded: the Claude background worker (gdh-check-update-worker.js) — the
|
|
2617
|
+
// worker script body reads GDH_PINNED_VERSION from process.env at runtime and does NOT contain
|
|
2618
|
+
// an `@skillcap/gdh@<v>` literal or any other baked-version pattern. Adding it would cause
|
|
2619
|
+
// VERIFY_DRIFT_BAKED_VERSION_REGEX to report `no_baked_version` → false positive. Worker drift
|
|
2620
|
+
// is audited via the `// gdh-hook-version: N` marker through the renderer-layer contract, not
|
|
2621
|
+
// via this version-literal scanner. Covered in integration tests at
|
|
2622
|
+
// packages/adapters/src/claude-update-install-integration.test.ts.
|
|
2623
|
+
//
|
|
2624
|
+
// Intentionally excluded: the Claude statusline (gdh-statusline.js) — the statusline renderer
|
|
2625
|
+
// produces a version-agnostic script (reads the update cache at runtime; no semver literal baked
|
|
2626
|
+
// in the output). Adding it would permanently report `no_baked_version` → false positive. The
|
|
2627
|
+
// statusline IS re-baked on every `gdh adapters install` via the renderer pipeline, which ensures
|
|
2628
|
+
// it stays current with the hook version; pin-literal drift detection is not applicable here.
|
|
2629
|
+
//
|
|
2630
|
+
// Intentionally excluded: the Claude /gdh-update command (.claude/commands/gdh/update.md) —
|
|
2631
|
+
// the rendered command shells out to `npx -y @skillcap/gdh@latest self-update` (LITERAL @latest,
|
|
2632
|
+
// not @<pinnedVersion>). The shellout MUST bake @latest so the NEW CLI performs the update,
|
|
2633
|
+
// not the OLD (potentially buggy) pinned one. Because @latest is not a semver literal, the
|
|
2634
|
+
// VERIFY_DRIFT_BAKED_VERSION_REGEX finds no pinned-version match and would permanently report
|
|
2635
|
+
// `no_baked_version` → false positive. Phase 13 D-13 locks this exclusion; Check 44 in
|
|
2636
|
+
// scripts/validate-docs.mjs enforces both the @latest invariant and the exclusion.
|
|
2637
|
+
//
|
|
2638
|
+
// Intentionally excluded: the Codex gdh-update skill (.codex/skills/gdh-update/SKILL.md) —
|
|
2639
|
+
// same rationale: renders @skillcap/gdh@latest, not @<pinnedVersion>. Phase 13 D-13.
|
|
2640
|
+
//
|
|
2641
|
+
// Intentionally excluded: the Cursor gdh-update skill (.cursor/skills/gdh-update/SKILL.md) —
|
|
2642
|
+
// same rationale: renders @skillcap/gdh@latest, not @<pinnedVersion>. Phase 13 D-13.
|
|
2544
2643
|
];
|
|
2545
2644
|
// Mirrors EXACT_SEMVER_PATTERN in @gdh/authoring so only well-formed SemVer
|
|
2546
2645
|
// values match — drift check does not pick up unrelated doc prose.
|
|
@@ -2551,8 +2650,8 @@ async function runVerifyDriftCommand(args, io) {
|
|
|
2551
2650
|
"Usage: gdh verify drift [target]",
|
|
2552
2651
|
"",
|
|
2553
2652
|
"Compares every baked `@skillcap/gdh@<version>` literal across the managed",
|
|
2554
|
-
"surfaces (
|
|
2555
|
-
"
|
|
2653
|
+
"surfaces (regenerated Codex/Cursor/Claude skill + command files) against",
|
|
2654
|
+
".gdh/project.yaml gdh_version. Exits 1 and",
|
|
2556
2655
|
"emits a structured JSON result when ANY file's baked version diverges from",
|
|
2557
2656
|
"the pinned value. Covers ROADMAP Success Criterion #3 (one source of truth).",
|
|
2558
2657
|
"",
|
|
@@ -2608,7 +2707,7 @@ async function runVerifyDriftCommand(args, io) {
|
|
|
2608
2707
|
reason: "file_missing",
|
|
2609
2708
|
};
|
|
2610
2709
|
}
|
|
2611
|
-
const match = content.match(VERIFY_DRIFT_BAKED_VERSION_REGEX);
|
|
2710
|
+
const match = content.match(file.versionRegex ?? VERIFY_DRIFT_BAKED_VERSION_REGEX);
|
|
2612
2711
|
const baked = match?.[1] ?? null;
|
|
2613
2712
|
const reason = baked === null
|
|
2614
2713
|
? "no_baked_version"
|
|
@@ -3733,7 +3832,7 @@ function renderHelp() {
|
|
|
3733
3832
|
"Run `gdh <command> --help` for command-specific usage.",
|
|
3734
3833
|
].join("\n") + "\n");
|
|
3735
3834
|
}
|
|
3736
|
-
function formatCliError(error) {
|
|
3835
|
+
export function formatCliError(error) {
|
|
3737
3836
|
return error instanceof Error ? error.message : String(error);
|
|
3738
3837
|
}
|
|
3739
3838
|
function resolveCachePruneScope(args) {
|
|
@@ -3791,7 +3890,7 @@ function collectAssignmentOptionValues(args, optionName) {
|
|
|
3791
3890
|
}
|
|
3792
3891
|
return assignments;
|
|
3793
3892
|
}
|
|
3794
|
-
function readSingleOptionValue(args, optionName) {
|
|
3893
|
+
export function readSingleOptionValue(args, optionName) {
|
|
3795
3894
|
const index = args.indexOf(optionName);
|
|
3796
3895
|
if (index === -1) {
|
|
3797
3896
|
return null;
|
|
@@ -3802,7 +3901,7 @@ function readSingleOptionValue(args, optionName) {
|
|
|
3802
3901
|
}
|
|
3803
3902
|
return value;
|
|
3804
3903
|
}
|
|
3805
|
-
function findUnsupportedOptionsError(args, options) {
|
|
3904
|
+
export function findUnsupportedOptionsError(args, options) {
|
|
3806
3905
|
const supportedOptions = new Set([
|
|
3807
3906
|
...(options.optionsWithValues ?? []),
|
|
3808
3907
|
...(options.booleanOptions ?? []),
|
|
@@ -3864,7 +3963,7 @@ function buildGuidanceSnapshot(result) {
|
|
|
3864
3963
|
recommendedUnitIds: result.recommendedUnits.map((unit) => unit.id),
|
|
3865
3964
|
};
|
|
3866
3965
|
}
|
|
3867
|
-
async function recordSessionEvent(targetPath, input) {
|
|
3966
|
+
export async function recordSessionEvent(targetPath, input) {
|
|
3868
3967
|
try {
|
|
3869
3968
|
const { commandStartedAtMs, ...eventInput } = input;
|
|
3870
3969
|
const startedAt = typeof commandStartedAtMs === "number" && Number.isFinite(commandStartedAtMs)
|
|
@@ -3939,7 +4038,7 @@ function extractGuidanceResolvePositionalArgs(args) {
|
|
|
3939
4038
|
function extractRecipePositionalArgs(args) {
|
|
3940
4039
|
return extractPositionalArgs(args, new Set(["--provider", "--param", "--feature", "--no-feature", "--env"]));
|
|
3941
4040
|
}
|
|
3942
|
-
function extractPositionalArgs(args, optionsWithValues) {
|
|
4041
|
+
export function extractPositionalArgs(args, optionsWithValues) {
|
|
3943
4042
|
const positionalArgs = [];
|
|
3944
4043
|
for (let index = 0; index < args.length; index += 1) {
|
|
3945
4044
|
const arg = args[index];
|