@skillcap/gdh 0.25.5 → 0.26.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 (62) 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/claude-settings-patch.d.ts.map +1 -1
  4. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js +38 -15
  5. package/node_modules/@gdh/adapters/dist/claude-settings-patch.js.map +1 -1
  6. package/node_modules/@gdh/adapters/dist/index.d.ts +12 -0
  7. package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
  8. package/node_modules/@gdh/adapters/dist/index.js +21 -0
  9. package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
  10. package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts +5 -2
  11. package/node_modules/@gdh/adapters/dist/skill-rendering.d.ts.map +1 -1
  12. package/node_modules/@gdh/adapters/dist/skill-rendering.js +39 -0
  13. package/node_modules/@gdh/adapters/dist/skill-rendering.js.map +1 -1
  14. package/node_modules/@gdh/adapters/dist/templates/authoring-hook.js.tpl +196 -5
  15. package/node_modules/@gdh/adapters/package.json +8 -8
  16. package/node_modules/@gdh/authoring/dist/diagnostics-broker-contract.d.ts +1 -0
  17. package/node_modules/@gdh/authoring/dist/diagnostics-broker-contract.d.ts.map +1 -1
  18. package/node_modules/@gdh/authoring/dist/diagnostics-broker-contract.js +1 -0
  19. package/node_modules/@gdh/authoring/dist/diagnostics-broker-contract.js.map +1 -1
  20. package/node_modules/@gdh/authoring/dist/diagnostics-broker.d.ts +2 -1
  21. package/node_modules/@gdh/authoring/dist/diagnostics-broker.d.ts.map +1 -1
  22. package/node_modules/@gdh/authoring/dist/diagnostics-broker.js +90 -11
  23. package/node_modules/@gdh/authoring/dist/diagnostics-broker.js.map +1 -1
  24. package/node_modules/@gdh/authoring/dist/index.d.ts +1 -1
  25. package/node_modules/@gdh/authoring/dist/index.d.ts.map +1 -1
  26. package/node_modules/@gdh/authoring/dist/index.js +1 -1
  27. package/node_modules/@gdh/authoring/dist/index.js.map +1 -1
  28. package/node_modules/@gdh/authoring/dist/lsp-warmup.d.ts +30 -0
  29. package/node_modules/@gdh/authoring/dist/lsp-warmup.d.ts.map +1 -0
  30. package/node_modules/@gdh/authoring/dist/lsp-warmup.js +213 -0
  31. package/node_modules/@gdh/authoring/dist/lsp-warmup.js.map +1 -0
  32. package/node_modules/@gdh/authoring/dist/lsp.d.ts +7 -1
  33. package/node_modules/@gdh/authoring/dist/lsp.d.ts.map +1 -1
  34. package/node_modules/@gdh/authoring/dist/lsp.js +223 -121
  35. package/node_modules/@gdh/authoring/dist/lsp.js.map +1 -1
  36. package/node_modules/@gdh/authoring/package.json +2 -2
  37. package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
  38. package/node_modules/@gdh/cli/dist/index.js +73 -8
  39. package/node_modules/@gdh/cli/dist/index.js.map +1 -1
  40. package/node_modules/@gdh/cli/package.json +10 -10
  41. package/node_modules/@gdh/core/dist/index.d.ts +177 -5
  42. package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
  43. package/node_modules/@gdh/core/dist/index.js +43 -3
  44. package/node_modules/@gdh/core/dist/index.js.map +1 -1
  45. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts +15 -0
  46. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.d.ts.map +1 -1
  47. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js +18 -0
  48. package/node_modules/@gdh/core/dist/migrations/managed-surface-classes.js.map +1 -1
  49. package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.d.ts.map +1 -1
  50. package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js +2 -0
  51. package/node_modules/@gdh/core/dist/migrations/managed-target-surface-inventory.js.map +1 -1
  52. package/node_modules/@gdh/core/package.json +1 -1
  53. package/node_modules/@gdh/docs/package.json +2 -2
  54. package/node_modules/@gdh/mcp/dist/index.d.ts.map +1 -1
  55. package/node_modules/@gdh/mcp/dist/index.js +30 -1
  56. package/node_modules/@gdh/mcp/dist/index.js.map +1 -1
  57. package/node_modules/@gdh/mcp/package.json +8 -8
  58. package/node_modules/@gdh/observability/package.json +2 -2
  59. package/node_modules/@gdh/runtime/package.json +2 -2
  60. package/node_modules/@gdh/scan/package.json +3 -3
  61. package/node_modules/@gdh/verify/package.json +7 -7
  62. package/package.json +11 -11
@@ -1 +1 @@
1
- {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../src/lsp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../src/lsp.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import fs from "node:fs/promises";
5
5
  import net from "node:net";
6
6
  import path from "node:path";
7
7
  import { fileURLToPath, pathToFileURL } from "node:url";
8
- import { GDH_MANAGED_LSP_SURFACE_VERSION, resolveConfiguredGodotEditorBin } from "@gdh/core";
8
+ import { GDH_MANAGED_LSP_MIN_GODOT_VERSION, GDH_MANAGED_LSP_SURFACE_VERSION, resolveConfiguredGodotEditorBin, } from "@gdh/core";
9
9
  import { connectGodotLspClient, GdhLspClientError, } from "./lsp-client.js";
10
10
  import { summarizeBlockingDiagnostics } from "./diagnostics-summary.js";
11
11
  import { classifyDiagnosticsFreshness, DIAGNOSTICS_BROKER_DEFAULT_FRESHNESS_STALE_AFTER_MS, resolveDiagnosticsBrokerPaths, } from "./diagnostics-broker-contract.js";
@@ -122,149 +122,190 @@ export async function getManagedLspStatus(input) {
122
122
  return unavailable;
123
123
  }
124
124
  try {
125
- return await withManagedLspStateLock(worktree, input.owner ?? "gdh lsp status", async (stateLock) => await withLease(worktree, input.owner ?? "gdh lsp status", async (lease, activeLeaseCount) => {
126
- let cleanedStaleInstance = false;
127
- let cleanupReasons = [];
125
+ return await withManagedLspStateLock(worktree, input.owner ?? "gdh lsp status", async (stateLock) => {
128
126
  const projectPath = path.resolve(input.targetPath, input.status.primaryProjectPath ?? ".");
129
127
  const expectedIdentity = await resolveCurrentManagedLspIdentity(worktree, projectPath);
130
- const existing = await readPersistedInstance(worktree);
131
- if (existing !== null) {
132
- const validation = await validatePersistedInstance(existing.instance, expectedIdentity);
133
- if (validation.reusable) {
134
- const reusedInstance = {
135
- ...existing.instance,
136
- lastValidatedAt: new Date().toISOString(),
137
- trust: validation.trust,
138
- };
139
- await persistInstance(worktree, {
140
- ...existing,
141
- instance: reusedInstance,
142
- rawPayload: validation.rawPayload ?? existing.rawPayload,
128
+ // Phase 81 / LSP-08 / D-17: refuse-to-launch when the configured
129
+ // Godot version is below the managed-LSP floor. Short-circuits
130
+ // BEFORE lsp-leases.json acquisition (withLease) and BEFORE
131
+ // persisted-instance reads — but executes inside the lsp.lock
132
+ // (stateLock) so identity resolution is serialized with other
133
+ // lifecycle mutations. Misconfigured 4.5.0/4.5.1 setups never
134
+ // acquire a lease or block other waiters.
135
+ if (expectedIdentity.editorVersionReason === "godot_editor_version_unsupported_for_lsp") {
136
+ return createUnavailableStatus({
137
+ targetPath: input.targetPath,
138
+ readiness: input.status.readiness,
139
+ worktree,
140
+ inventoryObservedAt: input.status.inventoryObservedAt,
141
+ projectConfigPresent: input.projectConfig !== null,
142
+ availability: "unavailable",
143
+ reasons: dedupe([
144
+ ...stateLock.recoveredReasons,
145
+ "godot_editor_version_unsupported_for_lsp",
146
+ ]),
147
+ summary: "The configured Godot editor version does not meet the minimum version required for the managed authoring.lsp. Upgrade to Godot 4.5.2 or later.",
148
+ versionFloorAdvisory: {
149
+ detectedVersion: expectedIdentity.editorVersion,
150
+ minimumVersion: GDH_MANAGED_LSP_MIN_GODOT_VERSION,
151
+ recommendedVersions: ["4.5.2", "4.6.x"],
152
+ },
153
+ });
154
+ }
155
+ return await withLease(worktree, input.owner ?? "gdh lsp status", async (lease, activeLeaseCount) => {
156
+ let cleanedStaleInstance = false;
157
+ let cleanupReasons = [];
158
+ const existing = await readPersistedInstance(worktree);
159
+ if (existing !== null) {
160
+ const validation = await validatePersistedInstance(existing.instance, expectedIdentity);
161
+ if (validation.reusable) {
162
+ const reusedInstance = {
163
+ ...existing.instance,
164
+ lastValidatedAt: new Date().toISOString(),
165
+ trust: validation.trust,
166
+ };
167
+ await persistInstance(worktree, {
168
+ ...existing,
169
+ instance: reusedInstance,
170
+ rawPayload: validation.rawPayload ?? existing.rawPayload,
171
+ });
172
+ return createStatusResult({
173
+ targetPath: input.targetPath,
174
+ readiness: input.status.readiness,
175
+ availability: "available",
176
+ status: validation.trust === "trusted" ? "ready" : "degraded",
177
+ validationMode: existing.validationMode,
178
+ summary: validation.trust === "trusted"
179
+ ? "Reused the managed authoring.lsp instance for this worktree."
180
+ : "Reused the managed authoring.lsp instance, but trust is degraded and the instance should be treated cautiously.",
181
+ reasons: dedupe([
182
+ ...stateLock.recoveredReasons,
183
+ ...(validation.trust === "trusted" ? [] : ["lsp_instance_degraded"]),
184
+ ]),
185
+ worktree,
186
+ lease,
187
+ activeLeaseCount,
188
+ reusedInstance: true,
189
+ cleanedStaleInstance,
190
+ instance: reusedInstance,
191
+ inventoryObservedAt: input.status.inventoryObservedAt,
192
+ projectConfigPresent: input.projectConfig !== null,
193
+ rawPayload: validation.rawPayload ?? existing.rawPayload,
194
+ });
195
+ }
196
+ cleanedStaleInstance = true;
197
+ cleanupReasons = validation.reasons;
198
+ await cleanupPersistedInstance(worktree, existing.instance, validation.reason, {
199
+ expectedIdentity,
143
200
  });
144
- return createStatusResult({
201
+ // Phase 81 / LSP-04 / D-11 / Pitfall 7: when the LSP instance
202
+ // identity has changed, the broker snapshot referenced the
203
+ // now-defunct instance. Prune so the next read returns
204
+ // broker_metadata_missing instead of lsp_instance_identity_mismatch.
205
+ {
206
+ const { pruneAuthoringDiagnostics } = await import("./diagnostics-broker.js");
207
+ await pruneAuthoringDiagnostics({
208
+ targetPath: input.targetPath,
209
+ status: input.status,
210
+ projectConfig: input.projectConfig,
211
+ });
212
+ }
213
+ }
214
+ if (input.launchPolicy === "reuse_existing") {
215
+ return createUnavailableStatus({
145
216
  targetPath: input.targetPath,
146
217
  readiness: input.status.readiness,
147
- availability: "available",
148
- status: validation.trust === "trusted" ? "ready" : "degraded",
149
- validationMode: existing.validationMode,
150
- summary: validation.trust === "trusted"
151
- ? "Reused the managed authoring.lsp instance for this worktree."
152
- : "Reused the managed authoring.lsp instance, but trust is degraded and the instance should be treated cautiously.",
218
+ worktree,
219
+ inventoryObservedAt: input.status.inventoryObservedAt,
220
+ projectConfigPresent: input.projectConfig !== null,
221
+ availability: lspCapability?.availability ?? "available",
153
222
  reasons: dedupe([
154
223
  ...stateLock.recoveredReasons,
155
- ...(validation.trust === "trusted" ? [] : ["lsp_instance_degraded"]),
224
+ ...(cleanedStaleInstance ? ["stale_lsp_instance_cleaned"] : []),
225
+ ...cleanupReasons,
226
+ "lsp_instance_not_running",
227
+ "post_edit_fast_path_did_not_launch_lsp",
156
228
  ]),
157
- worktree,
229
+ summary: "No reusable managed authoring.lsp instance is currently running; post-edit fast check did not launch Godot.",
158
230
  lease,
159
231
  activeLeaseCount,
160
- reusedInstance: true,
161
232
  cleanedStaleInstance,
162
- instance: reusedInstance,
233
+ rawPayload: {
234
+ launchPolicy: "reuse_existing",
235
+ projectPath,
236
+ cleanedStaleInstance,
237
+ cleanupReasons,
238
+ },
239
+ });
240
+ }
241
+ const launchResult = await launchManagedInstance(worktree, projectPath);
242
+ if ("unavailable" in launchResult) {
243
+ return createUnavailableStatus({
244
+ targetPath: input.targetPath,
245
+ readiness: input.status.readiness,
246
+ worktree,
163
247
  inventoryObservedAt: input.status.inventoryObservedAt,
164
248
  projectConfigPresent: input.projectConfig !== null,
165
- rawPayload: validation.rawPayload ?? existing.rawPayload,
249
+ availability: "unavailable",
250
+ reasons: [
251
+ ...stateLock.recoveredReasons,
252
+ ...(cleanedStaleInstance ? ["stale_lsp_instance_cleaned"] : []),
253
+ ...cleanupReasons,
254
+ ...launchResult.unavailable.reasons,
255
+ ],
256
+ summary: launchResult.unavailable.summary,
257
+ lease,
258
+ activeLeaseCount,
259
+ cleanedStaleInstance,
260
+ rawPayload: launchResult.unavailable.rawPayload,
166
261
  });
167
262
  }
168
- cleanedStaleInstance = true;
169
- cleanupReasons = validation.reasons;
170
- await cleanupPersistedInstance(worktree, existing.instance, validation.reason, {
171
- expectedIdentity,
263
+ const launchedInstance = {
264
+ instanceId: launchResult.instanceId,
265
+ launcher: launchResult.launcher,
266
+ port: launchResult.port,
267
+ pid: launchResult.pid,
268
+ projectPath,
269
+ command: launchResult.command,
270
+ trust: launchResult.trust,
271
+ launchedAt: new Date().toISOString(),
272
+ lastValidatedAt: new Date().toISOString(),
273
+ identity: launchResult.identity,
274
+ };
275
+ await persistInstance(worktree, {
276
+ schemaVersion: LSP_INSTANCE_SCHEMA_VERSION,
277
+ instance: launchedInstance,
278
+ validationMode: launchResult.validationMode,
279
+ diagnostics: launchResult.diagnostics,
280
+ rawPayload: launchResult.rawPayload,
172
281
  });
173
- }
174
- if (input.launchPolicy === "reuse_existing") {
175
- return createUnavailableStatus({
282
+ return createStatusResult({
176
283
  targetPath: input.targetPath,
177
284
  readiness: input.status.readiness,
178
- worktree,
179
- inventoryObservedAt: input.status.inventoryObservedAt,
180
- projectConfigPresent: input.projectConfig !== null,
181
- availability: lspCapability?.availability ?? "available",
285
+ availability: "available",
286
+ status: launchResult.trust === "trusted" ? "ready" : "degraded",
287
+ validationMode: launchResult.validationMode,
288
+ summary: launchResult.trust === "trusted"
289
+ ? "Started a managed authoring.lsp instance for this worktree."
290
+ : "Started a managed authoring.lsp instance, but trust is degraded and validation should be treated cautiously.",
182
291
  reasons: dedupe([
183
292
  ...stateLock.recoveredReasons,
184
293
  ...(cleanedStaleInstance ? ["stale_lsp_instance_cleaned"] : []),
185
294
  ...cleanupReasons,
186
- "lsp_instance_not_running",
187
- "post_edit_fast_path_did_not_launch_lsp",
295
+ ...(launchResult.trust === "trusted" ? [] : ["lsp_instance_degraded"]),
188
296
  ]),
189
- summary: "No reusable managed authoring.lsp instance is currently running; post-edit fast check did not launch Godot.",
297
+ worktree,
190
298
  lease,
191
299
  activeLeaseCount,
300
+ reusedInstance: false,
192
301
  cleanedStaleInstance,
193
- rawPayload: {
194
- launchPolicy: "reuse_existing",
195
- projectPath,
196
- cleanedStaleInstance,
197
- cleanupReasons,
198
- },
199
- });
200
- }
201
- const launchResult = await launchManagedInstance(worktree, projectPath);
202
- if ("unavailable" in launchResult) {
203
- return createUnavailableStatus({
204
- targetPath: input.targetPath,
205
- readiness: input.status.readiness,
206
- worktree,
302
+ instance: launchedInstance,
207
303
  inventoryObservedAt: input.status.inventoryObservedAt,
208
304
  projectConfigPresent: input.projectConfig !== null,
209
- availability: "unavailable",
210
- reasons: [
211
- ...stateLock.recoveredReasons,
212
- ...(cleanedStaleInstance ? ["stale_lsp_instance_cleaned"] : []),
213
- ...cleanupReasons,
214
- ...launchResult.unavailable.reasons,
215
- ],
216
- summary: launchResult.unavailable.summary,
217
- lease,
218
- activeLeaseCount,
219
- cleanedStaleInstance,
220
- rawPayload: launchResult.unavailable.rawPayload,
305
+ rawPayload: launchResult.rawPayload,
221
306
  });
222
- }
223
- const launchedInstance = {
224
- instanceId: launchResult.instanceId,
225
- launcher: launchResult.launcher,
226
- port: launchResult.port,
227
- pid: launchResult.pid,
228
- projectPath,
229
- command: launchResult.command,
230
- trust: launchResult.trust,
231
- launchedAt: new Date().toISOString(),
232
- lastValidatedAt: new Date().toISOString(),
233
- identity: launchResult.identity,
234
- };
235
- await persistInstance(worktree, {
236
- schemaVersion: LSP_INSTANCE_SCHEMA_VERSION,
237
- instance: launchedInstance,
238
- validationMode: launchResult.validationMode,
239
- diagnostics: launchResult.diagnostics,
240
- rawPayload: launchResult.rawPayload,
241
307
  });
242
- return createStatusResult({
243
- targetPath: input.targetPath,
244
- readiness: input.status.readiness,
245
- availability: "available",
246
- status: launchResult.trust === "trusted" ? "ready" : "degraded",
247
- validationMode: launchResult.validationMode,
248
- summary: launchResult.trust === "trusted"
249
- ? "Started a managed authoring.lsp instance for this worktree."
250
- : "Started a managed authoring.lsp instance, but trust is degraded and validation should be treated cautiously.",
251
- reasons: dedupe([
252
- ...stateLock.recoveredReasons,
253
- ...(cleanedStaleInstance ? ["stale_lsp_instance_cleaned"] : []),
254
- ...cleanupReasons,
255
- ...(launchResult.trust === "trusted" ? [] : ["lsp_instance_degraded"]),
256
- ]),
257
- worktree,
258
- lease,
259
- activeLeaseCount,
260
- reusedInstance: false,
261
- cleanedStaleInstance,
262
- instance: launchedInstance,
263
- inventoryObservedAt: input.status.inventoryObservedAt,
264
- projectConfigPresent: input.projectConfig !== null,
265
- rawPayload: launchResult.rawPayload,
266
- });
267
- }));
308
+ });
268
309
  }
269
310
  catch (error) {
270
311
  if (error instanceof GdhManagedLspStateLockError) {
@@ -282,6 +323,36 @@ export async function getManagedLspStatus(input) {
282
323
  throw error;
283
324
  }
284
325
  }
326
+ // ─────────────────────────────────────────────────────────────────────────────
327
+ // Phase 82 / LSP-02 / LSP-07 — managed-LSP warmup surface.
328
+ //
329
+ // `warmupManagedLsp` is the in-process entry point that the post-edit hook
330
+ // detach-spawns (via `gdh lsp warmup`) and the MCP `authoring.warmup` tool
331
+ // invokes. It is idempotent: concurrent callers fan in via a single-attempt
332
+ // `<targetPath>/.gdh-state/lsp.lock` acquire so the underlying Godot launch
333
+ // happens at most once.
334
+ //
335
+ // The implementation lives in `./lsp-warmup.js`. That sibling module imports
336
+ // `getManagedLspStatus` from `./lsp.js`, which is the documented vitest
337
+ // workaround for the "vi.mock cannot intercept same-module internal calls"
338
+ // pitfall (https://vitest.dev/guide/mocking/modules — Internal Method Calls).
339
+ //
340
+ // IMPORTANT: this is a thin wrapper that DEFERS to the impl via dynamic
341
+ // `await import("./lsp-warmup.js")`. The deferral guarantees `lsp-warmup.ts`
342
+ // is NOT a static dependency of `lsp.ts`. Were it static (a re-export), it
343
+ // would be evaluated as part of `./lsp.js`'s module graph, with its
344
+ // `import { getManagedLspStatus } from "./lsp.js"` resolving against the
345
+ // partially-evaluated original module record — so the unit-test mock
346
+ // (`vi.mock("./lsp.js", ...)`) would never reach the warmup impl. By
347
+ // keeping it deferred, the test's `await import("./lsp-warmup.js")` is
348
+ // the FIRST point at which lsp-warmup.ts loads, and at that time the mock
349
+ // is already registered, so the `./lsp.js` import resolves to the mocked
350
+ // module. See `./lsp-warmup.ts` and `./lsp-warmup.test.ts` for context.
351
+ // ─────────────────────────────────────────────────────────────────────────────
352
+ export async function warmupManagedLsp(input) {
353
+ const { warmupManagedLsp: impl } = await import("./lsp-warmup.js");
354
+ return impl(input);
355
+ }
285
356
  export async function checkManagedLsp(input) {
286
357
  const worktree = resolveWorktreeIdentity(input.targetPath, input.status, input.projectConfig);
287
358
  return await withManagedLspLifecycleLock(worktree, "check", "gdh lsp check", async (stateLock) => {
@@ -404,6 +475,19 @@ export async function stopManagedLsp(input) {
404
475
  killProcess: true,
405
476
  expectedIdentity,
406
477
  });
478
+ // Phase 81 / LSP-04 / D-11: prune the broker snapshot inside the lifecycle
479
+ // lock so concurrent readers cannot observe a stale snapshot pointing at
480
+ // the just-stopped LSP instance. The .primed marker is intentionally
481
+ // preserved (D-10) — broker absence remains "broker_metadata_missing"
482
+ // until the next refresh, distinct from "broker_not_yet_primed".
483
+ {
484
+ const { pruneAuthoringDiagnostics } = await import("./diagnostics-broker.js");
485
+ await pruneAuthoringDiagnostics({
486
+ targetPath: input.targetPath,
487
+ status: input.status,
488
+ projectConfig: input.projectConfig,
489
+ });
490
+ }
407
491
  return createLifecycleCommandResult({
408
492
  targetPath: input.targetPath,
409
493
  command: "stop",
@@ -1152,13 +1236,20 @@ function resolveWorktreeIdentity(targetPath, status, projectConfig) {
1152
1236
  async function resolveCurrentManagedLspIdentity(worktree, projectPath) {
1153
1237
  const testMode = process.env["GDH_TEST_LSP_MODE"];
1154
1238
  if (testMode) {
1239
+ const syntheticVersion = normalizeTestMode(testMode);
1240
+ // Phase 81 / LSP-08 / D-15: honor the version floor for synthetic test versions
1241
+ // so unit tests can exercise the floor-blocked path via GDH_TEST_LSP_MODE.
1242
+ const syntheticFloorViolation = typeof syntheticVersion === "string" &&
1243
+ (syntheticVersion.startsWith("4.5.0") || syntheticVersion.startsWith("4.5.1"));
1155
1244
  return await createManagedLspInstanceIdentity({
1156
1245
  worktree,
1157
1246
  projectPath,
1158
1247
  launcher: "test_fake",
1159
- editorBinPath: `test_fake:${normalizeTestMode(testMode)}`,
1160
- editorVersion: normalizeTestMode(testMode),
1161
- editorVersionReason: null,
1248
+ editorBinPath: `test_fake:${syntheticVersion}`,
1249
+ editorVersion: syntheticVersion,
1250
+ editorVersionReason: syntheticFloorViolation
1251
+ ? "godot_editor_version_unsupported_for_lsp"
1252
+ : null,
1162
1253
  });
1163
1254
  }
1164
1255
  const godotBin = await resolveConfiguredGodotEditorBin({
@@ -1166,15 +1257,25 @@ async function resolveCurrentManagedLspIdentity(worktree, projectPath) {
1166
1257
  environment: process.env,
1167
1258
  });
1168
1259
  const version = godotBin === null ? null : await probeGodotEditorVersion(godotBin);
1260
+ const versionStr = version?.version ?? null;
1261
+ // Phase 81 / LSP-08 / D-15 / Pitfall 4: Godot reports versions like
1262
+ // "4.5.0.stable" or "4.5.1.stable.official"; use a startsWith prefix match
1263
+ // on the 3-part version prefix to handle every suffix form. No semver
1264
+ // dependency is added — the floor check is intentionally narrow.
1265
+ const isFloorViolation = versionStr !== null &&
1266
+ (versionStr.startsWith("4.5.0") || versionStr.startsWith("4.5.1"));
1267
+ const editorVersionReason = godotBin === null
1268
+ ? "godot_editor_not_configured"
1269
+ : isFloorViolation
1270
+ ? "godot_editor_version_unsupported_for_lsp"
1271
+ : (version?.reason ?? null);
1169
1272
  return await createManagedLspInstanceIdentity({
1170
1273
  worktree,
1171
1274
  projectPath,
1172
1275
  launcher: "godot_editor",
1173
1276
  editorBinPath: godotBin,
1174
- editorVersion: version?.version ?? null,
1175
- editorVersionReason: godotBin === null
1176
- ? "godot_editor_not_configured"
1177
- : (version?.reason ?? "godot_editor_version_unavailable"),
1277
+ editorVersion: versionStr,
1278
+ editorVersionReason,
1178
1279
  });
1179
1280
  }
1180
1281
  async function createManagedLspInstanceIdentity(input) {
@@ -2026,6 +2127,7 @@ function createUnavailableStatus(input) {
2026
2127
  stateRootPath: input.worktree.stateRootPath,
2027
2128
  rawPayload: input.rawPayload ?? null,
2028
2129
  },
2130
+ versionFloorAdvisory: input.versionFloorAdvisory ?? null,
2029
2131
  };
2030
2132
  }
2031
2133
  function isPidAlive(pid) {