gsd-pi 2.60.0-dev.2580e65 → 2.60.0-dev.d9052f5
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/dist/resources/extensions/ask-user-questions.js +4 -7
- package/dist/resources/extensions/gsd/auto/phases.js +7 -15
- package/dist/resources/extensions/gsd/auto-dashboard.js +8 -21
- package/dist/resources/extensions/gsd/auto-dispatch.js +3 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +9 -58
- package/dist/resources/extensions/gsd/auto-post-unit.js +2 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +20 -36
- package/dist/resources/extensions/gsd/auto-recovery.js +18 -37
- package/dist/resources/extensions/gsd/auto-start.js +5 -9
- package/dist/resources/extensions/gsd/auto-timers.js +5 -11
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +3 -5
- package/dist/resources/extensions/gsd/auto-verification.js +2 -3
- package/dist/resources/extensions/gsd/auto-worktree.js +55 -120
- package/dist/resources/extensions/gsd/auto.js +17 -39
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +3 -6
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +10 -4
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +1 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +0 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -11
- package/dist/resources/extensions/gsd/commands/catalog.js +0 -2
- package/dist/resources/extensions/gsd/commands-codebase.js +21 -48
- package/dist/resources/extensions/gsd/commands-inspect.js +1 -2
- package/dist/resources/extensions/gsd/commands-maintenance.js +19 -32
- package/dist/resources/extensions/gsd/complexity-classifier.js +4 -8
- package/dist/resources/extensions/gsd/custom-verification.js +2 -3
- package/dist/resources/extensions/gsd/gsd-db.js +13 -33
- package/dist/resources/extensions/gsd/guided-flow.js +9 -19
- package/dist/resources/extensions/gsd/init-wizard.js +0 -12
- package/dist/resources/extensions/gsd/markdown-renderer.js +9 -11
- package/dist/resources/extensions/gsd/md-importer.js +4 -5
- package/dist/resources/extensions/gsd/milestone-actions.js +2 -3
- package/dist/resources/extensions/gsd/milestone-ids.js +1 -2
- package/dist/resources/extensions/gsd/model-router.js +121 -156
- package/dist/resources/extensions/gsd/parallel-merge.js +3 -5
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +14 -26
- package/dist/resources/extensions/gsd/preferences-types.js +0 -1
- package/dist/resources/extensions/gsd/preferences-validation.js +0 -45
- package/dist/resources/extensions/gsd/preferences.js +3 -15
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -3
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/rule-registry.js +6 -7
- package/dist/resources/extensions/gsd/safe-fs.js +8 -6
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +2 -3
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -3
- package/dist/resources/extensions/gsd/tools/complete-task.js +2 -3
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -3
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -3
- package/dist/resources/extensions/gsd/tools/plan-task.js +1 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +4 -4
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +1 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +1 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +1 -2
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +1 -2
- package/dist/resources/extensions/gsd/triage-resolution.js +4 -11
- package/dist/resources/extensions/gsd/workflow-events.js +1 -2
- package/dist/resources/extensions/gsd/workflow-logger.js +4 -37
- package/dist/resources/extensions/gsd/workflow-migration.js +12 -14
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -2
- package/dist/resources/extensions/gsd/workflow-reconcile.js +2 -2
- package/dist/resources/extensions/gsd/worktree-manager.js +14 -26
- package/dist/resources/extensions/shared/interview-ui.js +1 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +19 -19
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +19 -19
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +0 -5
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +0 -16
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +0 -26
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/config.js +1 -6
- package/packages/pi-coding-agent/dist/core/lsp/config.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/defaults.json +2 -2
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +0 -6
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +0 -19
- package/packages/pi-coding-agent/src/core/extensions/types.ts +0 -26
- package/packages/pi-coding-agent/src/core/lsp/config.ts +1 -7
- package/packages/pi-coding-agent/src/core/lsp/defaults.json +2 -2
- package/src/resources/extensions/ask-user-questions.ts +3 -7
- package/src/resources/extensions/gsd/auto/phases.ts +7 -17
- package/src/resources/extensions/gsd/auto-dashboard.ts +8 -22
- package/src/resources/extensions/gsd/auto-dispatch.ts +3 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +15 -77
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +20 -37
- package/src/resources/extensions/gsd/auto-recovery.ts +18 -38
- package/src/resources/extensions/gsd/auto-start.ts +9 -10
- package/src/resources/extensions/gsd/auto-timers.ts +5 -12
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +2 -6
- package/src/resources/extensions/gsd/auto-verification.ts +6 -3
- package/src/resources/extensions/gsd/auto-worktree.ts +55 -121
- package/src/resources/extensions/gsd/auto.ts +17 -40
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +3 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -4
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +1 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +0 -8
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +10 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +0 -2
- package/src/resources/extensions/gsd/commands-codebase.ts +20 -52
- package/src/resources/extensions/gsd/commands-inspect.ts +1 -2
- package/src/resources/extensions/gsd/commands-maintenance.ts +19 -28
- package/src/resources/extensions/gsd/complexity-classifier.ts +4 -9
- package/src/resources/extensions/gsd/custom-verification.ts +2 -3
- package/src/resources/extensions/gsd/gsd-db.ts +14 -12
- package/src/resources/extensions/gsd/guided-flow.ts +8 -9
- package/src/resources/extensions/gsd/init-wizard.ts +0 -12
- package/src/resources/extensions/gsd/markdown-renderer.ts +17 -11
- package/src/resources/extensions/gsd/md-importer.ts +4 -5
- package/src/resources/extensions/gsd/milestone-actions.ts +2 -3
- package/src/resources/extensions/gsd/milestone-ids.ts +1 -2
- package/src/resources/extensions/gsd/model-router.ts +173 -199
- package/src/resources/extensions/gsd/parallel-merge.ts +3 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +14 -18
- package/src/resources/extensions/gsd/preferences-types.ts +0 -13
- package/src/resources/extensions/gsd/preferences-validation.ts +0 -45
- package/src/resources/extensions/gsd/preferences.ts +3 -16
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -3
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/rule-registry.ts +6 -7
- package/src/resources/extensions/gsd/safe-fs.ts +5 -6
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +0 -63
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +2 -27
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/model-router.test.ts +3 -403
- package/src/resources/extensions/gsd/tests/preferences.test.ts +0 -62
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +0 -21
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +6 -6
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +6 -3
- package/src/resources/extensions/gsd/tools/complete-slice.ts +6 -3
- package/src/resources/extensions/gsd/tools/complete-task.ts +6 -3
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +6 -3
- package/src/resources/extensions/gsd/tools/plan-slice.ts +6 -3
- package/src/resources/extensions/gsd/tools/plan-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +6 -4
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +3 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +3 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -2
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +3 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +4 -11
- package/src/resources/extensions/gsd/types.ts +0 -1
- package/src/resources/extensions/gsd/workflow-events.ts +1 -2
- package/src/resources/extensions/gsd/workflow-logger.ts +5 -52
- package/src/resources/extensions/gsd/workflow-migration.ts +12 -14
- package/src/resources/extensions/gsd/workflow-projections.ts +2 -2
- package/src/resources/extensions/gsd/workflow-reconcile.ts +2 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +14 -16
- package/src/resources/extensions/shared/interview-ui.ts +1 -3
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts +0 -2
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.d.ts.map +0 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js +0 -47
- package/packages/pi-coding-agent/dist/core/lsp/lsp-legacy-alias.test.js.map +0 -1
- package/packages/pi-coding-agent/src/core/lsp/lsp-legacy-alias.test.ts +0 -70
- package/src/resources/extensions/gsd/tests/capability-router.test.ts +0 -347
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +0 -1188
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +0 -841
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +0 -284
- package/src/resources/extensions/gsd/tests/workflow-logger-audit.test.ts +0 -120
- package/src/resources/extensions/shared/tests/interview-notes-loop.test.ts +0 -144
- /package/dist/web/standalone/.next/static/{ogyMN7M-3bGGuRY08L5HR → JVkoVYumy0cDhOQISEYdG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ogyMN7M-3bGGuRY08L5HR → JVkoVYumy0cDhOQISEYdG}/_ssgManifest.js +0 -0
|
@@ -15,7 +15,6 @@ import { renderRoadmapFromDb } from "../markdown-renderer.js";
|
|
|
15
15
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
16
16
|
import { writeManifest } from "../workflow-manifest.js";
|
|
17
17
|
import { appendEvent } from "../workflow-events.js";
|
|
18
|
-
import { logWarning } from "../workflow-logger.js";
|
|
19
18
|
|
|
20
19
|
export interface PlanMilestoneSliceInput {
|
|
21
20
|
sliceId: string;
|
|
@@ -270,7 +269,9 @@ export async function handlePlanMilestone(
|
|
|
270
269
|
const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
|
|
271
270
|
roadmapPath = renderResult.roadmapPath;
|
|
272
271
|
} catch (renderErr) {
|
|
273
|
-
|
|
272
|
+
process.stderr.write(
|
|
273
|
+
`gsd-db: plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
|
|
274
|
+
);
|
|
274
275
|
invalidateStateCache();
|
|
275
276
|
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
276
277
|
}
|
|
@@ -291,7 +292,9 @@ export async function handlePlanMilestone(
|
|
|
291
292
|
trigger_reason: params.triggerReason,
|
|
292
293
|
});
|
|
293
294
|
} catch (hookErr) {
|
|
294
|
-
|
|
295
|
+
process.stderr.write(
|
|
296
|
+
`gsd: plan-milestone post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
297
|
+
);
|
|
295
298
|
}
|
|
296
299
|
|
|
297
300
|
return {
|
|
@@ -16,7 +16,6 @@ import { renderPlanFromDb } from "../markdown-renderer.js";
|
|
|
16
16
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
17
17
|
import { writeManifest } from "../workflow-manifest.js";
|
|
18
18
|
import { appendEvent } from "../workflow-events.js";
|
|
19
|
-
import { logWarning } from "../workflow-logger.js";
|
|
20
19
|
|
|
21
20
|
export interface PlanSliceTaskInput {
|
|
22
21
|
taskId: string;
|
|
@@ -230,7 +229,9 @@ export async function handlePlanSlice(
|
|
|
230
229
|
trigger_reason: params.triggerReason,
|
|
231
230
|
});
|
|
232
231
|
} catch (hookErr) {
|
|
233
|
-
|
|
232
|
+
process.stderr.write(
|
|
233
|
+
`gsd: plan-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
234
|
+
);
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
return {
|
|
@@ -240,7 +241,9 @@ export async function handlePlanSlice(
|
|
|
240
241
|
taskPlanPaths: renderResult.taskPlanPaths,
|
|
241
242
|
};
|
|
242
243
|
} catch (renderErr) {
|
|
243
|
-
|
|
244
|
+
process.stderr.write(
|
|
245
|
+
`gsd-db: plan_slice — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}\n`,
|
|
246
|
+
);
|
|
244
247
|
invalidateStateCache();
|
|
245
248
|
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
246
249
|
}
|
|
@@ -7,7 +7,6 @@ import { renderTaskPlanFromDb } from "../markdown-renderer.js";
|
|
|
7
7
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
8
8
|
import { writeManifest } from "../workflow-manifest.js";
|
|
9
9
|
import { appendEvent } from "../workflow-events.js";
|
|
10
|
-
import { logWarning } from "../workflow-logger.js";
|
|
11
10
|
|
|
12
11
|
export interface PlanTaskParams {
|
|
13
12
|
milestoneId: string;
|
|
@@ -136,7 +135,9 @@ export async function handlePlanTask(
|
|
|
136
135
|
trigger_reason: params.triggerReason,
|
|
137
136
|
});
|
|
138
137
|
} catch (hookErr) {
|
|
139
|
-
|
|
138
|
+
process.stderr.write(
|
|
139
|
+
`gsd: plan-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
140
|
+
);
|
|
140
141
|
}
|
|
141
142
|
|
|
142
143
|
return {
|
|
@@ -19,7 +19,6 @@ import { renderRoadmapFromDb, renderAssessmentFromDb } from "../markdown-rendere
|
|
|
19
19
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
20
20
|
import { writeManifest } from "../workflow-manifest.js";
|
|
21
21
|
import { appendEvent } from "../workflow-events.js";
|
|
22
|
-
import { logWarning } from "../workflow-logger.js";
|
|
23
22
|
|
|
24
23
|
export interface SliceChangeInput {
|
|
25
24
|
sliceId: string;
|
|
@@ -249,8 +248,9 @@ export async function handleReassessRoadmap(
|
|
|
249
248
|
);
|
|
250
249
|
try {
|
|
251
250
|
if (existsSync(validationFile)) unlinkSync(validationFile);
|
|
252
|
-
} catch
|
|
253
|
-
|
|
251
|
+
} catch {
|
|
252
|
+
// Best-effort: DB row is already deleted, so state derivation
|
|
253
|
+
// will not see the file-based verdict as authoritative.
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
|
|
@@ -271,7 +271,9 @@ export async function handleReassessRoadmap(
|
|
|
271
271
|
trigger_reason: params.triggerReason,
|
|
272
272
|
});
|
|
273
273
|
} catch (hookErr) {
|
|
274
|
-
|
|
274
|
+
process.stderr.write(
|
|
275
|
+
`gsd: reassess-roadmap post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
276
|
+
);
|
|
275
277
|
}
|
|
276
278
|
|
|
277
279
|
return {
|
|
@@ -24,7 +24,6 @@ import { isClosedStatus } from "../status-guards.js";
|
|
|
24
24
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
25
25
|
import { writeManifest } from "../workflow-manifest.js";
|
|
26
26
|
import { appendEvent } from "../workflow-events.js";
|
|
27
|
-
import { logWarning } from "../workflow-logger.js";
|
|
28
27
|
|
|
29
28
|
export interface ReopenSliceParams {
|
|
30
29
|
milestoneId: string;
|
|
@@ -114,7 +113,9 @@ export async function handleReopenSlice(
|
|
|
114
113
|
trigger_reason: params.triggerReason,
|
|
115
114
|
});
|
|
116
115
|
} catch (hookErr) {
|
|
117
|
-
|
|
116
|
+
process.stderr.write(
|
|
117
|
+
`gsd: reopen-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
118
|
+
);
|
|
118
119
|
}
|
|
119
120
|
|
|
120
121
|
return {
|
|
@@ -22,7 +22,6 @@ import { isClosedStatus } from "../status-guards.js";
|
|
|
22
22
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
23
23
|
import { writeManifest } from "../workflow-manifest.js";
|
|
24
24
|
import { appendEvent } from "../workflow-events.js";
|
|
25
|
-
import { logWarning } from "../workflow-logger.js";
|
|
26
25
|
|
|
27
26
|
export interface ReopenTaskParams {
|
|
28
27
|
milestoneId: string;
|
|
@@ -118,7 +117,9 @@ export async function handleReopenTask(
|
|
|
118
117
|
trigger_reason: params.triggerReason,
|
|
119
118
|
});
|
|
120
119
|
} catch (hookErr) {
|
|
121
|
-
|
|
120
|
+
process.stderr.write(
|
|
121
|
+
`gsd: reopen-task post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
122
|
+
);
|
|
122
123
|
}
|
|
123
124
|
|
|
124
125
|
return {
|
|
@@ -16,7 +16,6 @@ import { renderPlanFromDb, renderReplanFromDb } from "../markdown-renderer.js";
|
|
|
16
16
|
import { renderAllProjections } from "../workflow-projections.js";
|
|
17
17
|
import { writeManifest } from "../workflow-manifest.js";
|
|
18
18
|
import { appendEvent } from "../workflow-events.js";
|
|
19
|
-
import { logWarning } from "../workflow-logger.js";
|
|
20
19
|
|
|
21
20
|
export interface ReplanSliceTaskInput {
|
|
22
21
|
taskId: string;
|
|
@@ -227,7 +226,9 @@ export async function handleReplanSlice(
|
|
|
227
226
|
trigger_reason: params.triggerReason,
|
|
228
227
|
});
|
|
229
228
|
} catch (hookErr) {
|
|
230
|
-
|
|
229
|
+
process.stderr.write(
|
|
230
|
+
`gsd: replan-slice post-mutation hook warning: ${(hookErr as Error).message}\n`,
|
|
231
|
+
);
|
|
231
232
|
}
|
|
232
233
|
|
|
233
234
|
return {
|
|
@@ -22,7 +22,6 @@ import { saveFile, clearParseCache } from "../files.js";
|
|
|
22
22
|
import { invalidateStateCache } from "../state.js";
|
|
23
23
|
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
24
24
|
import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
|
|
25
|
-
import { logWarning } from "../workflow-logger.js";
|
|
26
25
|
|
|
27
26
|
export interface ValidateMilestoneParams {
|
|
28
27
|
milestoneId: string;
|
|
@@ -138,7 +137,9 @@ export async function handleValidateMilestone(
|
|
|
138
137
|
try {
|
|
139
138
|
await saveFile(validationPath, validationMd);
|
|
140
139
|
} catch (renderErr) {
|
|
141
|
-
|
|
140
|
+
process.stderr.write(
|
|
141
|
+
`gsd-db: validate_milestone — disk render failed, rolling back DB row: ${(renderErr as Error).message}\n`,
|
|
142
|
+
);
|
|
142
143
|
deleteAssessmentByScope(params.milestoneId, 'milestone-validation');
|
|
143
144
|
return { error: `disk render failed: ${(renderErr as Error).message}` };
|
|
144
145
|
}
|
|
@@ -148,17 +148,10 @@ export function executeBacktrack(
|
|
|
148
148
|
capture: CaptureEntry,
|
|
149
149
|
): string | null {
|
|
150
150
|
try {
|
|
151
|
-
// Extract target milestone from capture text or resolution
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
const allMatches = [...sourceText.matchAll(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/g)]
|
|
156
|
-
.map(m => m[1])
|
|
157
|
-
.filter(id => id !== currentMilestoneId);
|
|
158
|
-
// Reject ambiguous multi-target strings — if more than one distinct target remains,
|
|
159
|
-
// don't guess; let the user clarify.
|
|
160
|
-
const uniqueTargets = [...new Set(allMatches)];
|
|
161
|
-
const targetMilestoneId = uniqueTargets.length === 1 ? uniqueTargets[0] : null;
|
|
151
|
+
// Extract target milestone from capture text or resolution
|
|
152
|
+
const targetMatch = (capture.resolution ?? capture.text)
|
|
153
|
+
.match(/\b(M\d{3}(?:-[a-z0-9]{6})?)\b/);
|
|
154
|
+
const targetMilestoneId = targetMatch?.[1] ?? null;
|
|
162
155
|
|
|
163
156
|
const ts = new Date().toISOString();
|
|
164
157
|
const triggerPath = join(gsdRoot(basePath), "BACKTRACK-TRIGGER.md");
|
|
@@ -2,7 +2,6 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
2
2
|
import { appendFileSync, readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
5
|
-
import { logWarning } from "./workflow-logger.js";
|
|
6
5
|
|
|
7
6
|
// ─── Session ID ───────────────────────────────────────────────────────────
|
|
8
7
|
|
|
@@ -75,7 +74,7 @@ export function readEvents(logPath: string): WorkflowEvent[] {
|
|
|
75
74
|
try {
|
|
76
75
|
events.push(JSON.parse(line) as WorkflowEvent);
|
|
77
76
|
} catch {
|
|
78
|
-
|
|
77
|
+
process.stderr.write(`workflow-events: skipping corrupted event line: ${line.slice(0, 80)}\n`);
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
// Centralized warning/error accumulator for the workflow engine pipeline.
|
|
3
3
|
// Captures structured entries that the auto-loop can drain after each unit
|
|
4
4
|
// to surface root causes for stuck loops, silent degradation, and blocked writes.
|
|
5
|
-
//
|
|
6
|
-
// post-mortem analysis. Warnings are ephemeral (stderr + buffer only) to avoid
|
|
7
|
-
// log amplification from expected-control-flow catch paths.
|
|
5
|
+
// All entries are also persisted to .gsd/audit-log.jsonl for post-mortem analysis.
|
|
8
6
|
//
|
|
9
7
|
// Stderr policy: every logWarning/logError call writes immediately to stderr
|
|
10
8
|
// for terminal visibility. This is intentional — unlike debug-logger (which is
|
|
@@ -35,20 +33,7 @@ export type LogComponent =
|
|
|
35
33
|
| "compaction" // Event compaction
|
|
36
34
|
| "reconcile" // Worktree reconciliation
|
|
37
35
|
| "db" // Database operations (gsd-db)
|
|
38
|
-
| "dispatch"
|
|
39
|
-
| "recovery" // Auto-recovery and timeout recovery
|
|
40
|
-
| "session" // Session lock and session state I/O
|
|
41
|
-
| "prompt" // Prompt construction and context injection
|
|
42
|
-
| "dashboard" // Auto-dashboard rendering
|
|
43
|
-
| "timer" // Auto-timers (idle watchdog, hard timeout)
|
|
44
|
-
| "worktree" // Worktree lifecycle (create, sync, merge)
|
|
45
|
-
| "command" // Slash command execution and maintenance
|
|
46
|
-
| "parallel" // Parallel orchestrator and merge
|
|
47
|
-
| "fs" // Safe filesystem operations
|
|
48
|
-
| "bootstrap" // Extension bootstrap (system-context, agent-end)
|
|
49
|
-
| "guided" // Guided flow (discuss, plan wizards)
|
|
50
|
-
| "registry" // Rule registry hook state
|
|
51
|
-
| "renderer"; // Markdown renderer and projections
|
|
36
|
+
| "dispatch"; // Auto-dispatch rule evaluation
|
|
52
37
|
|
|
53
38
|
export interface LogEntry {
|
|
54
39
|
ts: string;
|
|
@@ -245,47 +230,15 @@ function _push(
|
|
|
245
230
|
_buffer.shift();
|
|
246
231
|
}
|
|
247
232
|
|
|
248
|
-
// Persist
|
|
249
|
-
|
|
250
|
-
// to avoid log amplification from expected-control-flow catch paths.
|
|
251
|
-
if (_auditBasePath && severity === "error") {
|
|
233
|
+
// Persist to .gsd/audit-log.jsonl so entries survive context resets
|
|
234
|
+
if (_auditBasePath) {
|
|
252
235
|
try {
|
|
253
236
|
const auditDir = join(_auditBasePath, ".gsd");
|
|
254
237
|
mkdirSync(auditDir, { recursive: true });
|
|
255
|
-
|
|
256
|
-
appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(sanitized) + "\n", "utf-8");
|
|
238
|
+
appendFileSync(join(auditDir, "audit-log.jsonl"), JSON.stringify(entry) + "\n", "utf-8");
|
|
257
239
|
} catch (auditErr) {
|
|
258
240
|
// Best-effort — never let audit write failures bubble up
|
|
259
241
|
process.stderr.write(`[gsd:audit] failed to persist log entry: ${(auditErr as Error).message}\n`);
|
|
260
242
|
}
|
|
261
243
|
}
|
|
262
244
|
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Sanitize a log entry before persisting to the audit JSONL file.
|
|
266
|
-
* Strips potentially sensitive context (raw paths, cwd, full error text)
|
|
267
|
-
* to avoid leaking local environment details into durable telemetry.
|
|
268
|
-
*/
|
|
269
|
-
function _sanitizeForAudit(entry: LogEntry): LogEntry {
|
|
270
|
-
const sanitized: LogEntry = {
|
|
271
|
-
ts: entry.ts,
|
|
272
|
-
severity: entry.severity,
|
|
273
|
-
component: entry.component,
|
|
274
|
-
// Truncate message to avoid persisting oversized raw error dumps
|
|
275
|
-
message: entry.message.length > 200 ? entry.message.slice(0, 200) + "…[truncated]" : entry.message,
|
|
276
|
-
};
|
|
277
|
-
if (entry.context) {
|
|
278
|
-
// Allowlist: only persist known-safe structured keys
|
|
279
|
-
const SAFE_KEYS = new Set(["fn", "tool", "mid", "sid", "tid", "worktree"]);
|
|
280
|
-
const filtered: Record<string, string> = {};
|
|
281
|
-
for (const [k, v] of Object.entries(entry.context)) {
|
|
282
|
-
if (SAFE_KEYS.has(k)) {
|
|
283
|
-
filtered[k] = v;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
if (Object.keys(filtered).length > 0) {
|
|
287
|
-
sanitized.context = filtered;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return sanitized;
|
|
291
|
-
}
|
|
@@ -7,7 +7,6 @@ import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { _getAdapter, transaction } from "./gsd-db.js";
|
|
9
9
|
import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
|
|
10
|
-
import { logWarning } from "./workflow-logger.js";
|
|
11
10
|
|
|
12
11
|
// ─── needsAutoMigration ───────────────────────────────────────────────────
|
|
13
12
|
|
|
@@ -24,8 +23,8 @@ export function needsAutoMigration(basePath: string): boolean {
|
|
|
24
23
|
try {
|
|
25
24
|
const row = db.prepare("SELECT COUNT(*) as cnt FROM milestones").get();
|
|
26
25
|
if (row && (row["cnt"] as number) > 0) return false;
|
|
27
|
-
} catch
|
|
28
|
-
|
|
26
|
+
} catch {
|
|
27
|
+
// Table might not exist yet — that's fine, we can still migrate
|
|
29
28
|
return false;
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -72,7 +71,7 @@ export function migrateFromMarkdown(basePath: string): void {
|
|
|
72
71
|
.filter(e => e.isDirectory())
|
|
73
72
|
.map(e => e.name);
|
|
74
73
|
} catch {
|
|
75
|
-
|
|
74
|
+
process.stderr.write("workflow-migration: failed to read milestones directory\n");
|
|
76
75
|
return;
|
|
77
76
|
}
|
|
78
77
|
|
|
@@ -142,7 +141,7 @@ export function migrateFromMarkdown(basePath: string): void {
|
|
|
142
141
|
risk: s.risk || "low",
|
|
143
142
|
}));
|
|
144
143
|
} catch (err) {
|
|
145
|
-
|
|
144
|
+
process.stderr.write(`workflow-migration: failed to parse ROADMAP.md for ${mId}: ${(err as Error).message}\n`);
|
|
146
145
|
// Still add milestone with ID as title
|
|
147
146
|
milestoneInserts.push({ id: mId, title: mId, status: milestoneStatus });
|
|
148
147
|
}
|
|
@@ -192,7 +191,7 @@ export function migrateFromMarkdown(basePath: string): void {
|
|
|
192
191
|
});
|
|
193
192
|
}
|
|
194
193
|
} catch (err) {
|
|
195
|
-
|
|
194
|
+
process.stderr.write(`workflow-migration: failed to parse ${slice.id}-PLAN.md for ${mId}: ${(err as Error).message}\n`);
|
|
196
195
|
}
|
|
197
196
|
}
|
|
198
197
|
}
|
|
@@ -207,8 +206,8 @@ export function migrateFromMarkdown(basePath: string): void {
|
|
|
207
206
|
process.stderr.write(`workflow-migration: orphaned summary file ${summaryFile} in ${mId} (slice not found in ROADMAP.md), skipping\n`);
|
|
208
207
|
}
|
|
209
208
|
}
|
|
210
|
-
} catch
|
|
211
|
-
|
|
209
|
+
} catch {
|
|
210
|
+
// Non-fatal
|
|
212
211
|
}
|
|
213
212
|
}
|
|
214
213
|
|
|
@@ -309,18 +308,17 @@ export function validateMigration(basePath: string): { discrepancies: string[] }
|
|
|
309
308
|
const planContent = readFileSync(planPath, "utf-8");
|
|
310
309
|
const plan = parsePlan(planContent);
|
|
311
310
|
mdTaskCount += plan.tasks.length;
|
|
312
|
-
} catch
|
|
313
|
-
|
|
311
|
+
} catch {
|
|
312
|
+
// Skip unreadable plan
|
|
314
313
|
}
|
|
315
314
|
}
|
|
316
315
|
}
|
|
317
|
-
} catch
|
|
318
|
-
|
|
316
|
+
} catch {
|
|
317
|
+
// Skip unreadable roadmap
|
|
319
318
|
}
|
|
320
319
|
}
|
|
321
320
|
}
|
|
322
|
-
} catch
|
|
323
|
-
logWarning("migration", `Validation failed to read markdown: ${(e as Error).message}`);
|
|
321
|
+
} catch {
|
|
324
322
|
return { discrepancies: ["Failed to read markdown for validation"] };
|
|
325
323
|
}
|
|
326
324
|
|
|
@@ -423,7 +423,7 @@ export function regenerateIfMissing(
|
|
|
423
423
|
renderSummaryProjection(basePath, milestoneId, sliceId, task.id);
|
|
424
424
|
regenerated++;
|
|
425
425
|
} catch (err) {
|
|
426
|
-
|
|
426
|
+
console.error(`[projections] regenerateIfMissing SUMMARY failed for ${task.id}:`, err);
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
429
|
}
|
|
@@ -452,7 +452,7 @@ export function regenerateIfMissing(
|
|
|
452
452
|
}
|
|
453
453
|
return true;
|
|
454
454
|
} catch (err) {
|
|
455
|
-
|
|
455
|
+
console.error(`[projections] regenerateIfMissing ${fileType} failed:`, err);
|
|
456
456
|
return false;
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -455,8 +455,8 @@ function parseEventBlock(block: string): WorkflowEvent[] {
|
|
|
455
455
|
if (paramsMatch) {
|
|
456
456
|
try {
|
|
457
457
|
params = JSON.parse(paramsMatch[1]!) as Record<string, unknown>;
|
|
458
|
-
} catch
|
|
459
|
-
|
|
458
|
+
} catch {
|
|
459
|
+
// Keep empty params on parse error
|
|
460
460
|
}
|
|
461
461
|
i++; // consume params line
|
|
462
462
|
}
|
|
@@ -95,8 +95,8 @@ export function resolveGitDir(basePath: string): string {
|
|
|
95
95
|
if (content.startsWith("gitdir: ")) {
|
|
96
96
|
return resolve(basePath, content.slice(8));
|
|
97
97
|
}
|
|
98
|
-
} catch
|
|
99
|
-
|
|
98
|
+
} catch {
|
|
99
|
+
// Not a file or unreadable — fall through to default
|
|
100
100
|
}
|
|
101
101
|
return join(basePath, ".git");
|
|
102
102
|
}
|
|
@@ -308,9 +308,8 @@ export function findNestedGitDirs(rootPath: string): string[] {
|
|
|
308
308
|
let entries: string[];
|
|
309
309
|
try {
|
|
310
310
|
entries = readdirSync(dir);
|
|
311
|
-
} catch
|
|
312
|
-
|
|
313
|
-
return;
|
|
311
|
+
} catch {
|
|
312
|
+
return; // Permission denied, broken symlink, etc.
|
|
314
313
|
}
|
|
315
314
|
|
|
316
315
|
for (const entry of entries) {
|
|
@@ -322,8 +321,7 @@ export function findNestedGitDirs(rootPath: string): string[] {
|
|
|
322
321
|
let stat;
|
|
323
322
|
try {
|
|
324
323
|
stat = lstatSync(fullPath);
|
|
325
|
-
} catch
|
|
326
|
-
logWarning("worktree", `lstatSync failed for ${fullPath}: ${(e as Error).message}`);
|
|
324
|
+
} catch {
|
|
327
325
|
continue;
|
|
328
326
|
}
|
|
329
327
|
if (!stat.isDirectory()) continue;
|
|
@@ -339,8 +337,8 @@ export function findNestedGitDirs(rootPath: string): string[] {
|
|
|
339
337
|
// Don't recurse into the nested repo — we found what we need
|
|
340
338
|
continue;
|
|
341
339
|
}
|
|
342
|
-
} catch
|
|
343
|
-
|
|
340
|
+
} catch {
|
|
341
|
+
// No .git here — continue scanning
|
|
344
342
|
}
|
|
345
343
|
|
|
346
344
|
walk(fullPath, depth + 1);
|
|
@@ -376,7 +374,7 @@ export function removeWorktree(
|
|
|
376
374
|
if (entry?.path) {
|
|
377
375
|
wtPath = entry.path;
|
|
378
376
|
}
|
|
379
|
-
} catch
|
|
377
|
+
} catch { /* fall back to computed path */ }
|
|
380
378
|
|
|
381
379
|
const resolvedWtPath = existsSync(wtPath) ? realpathSync(wtPath) : wtPath;
|
|
382
380
|
|
|
@@ -390,7 +388,7 @@ export function removeWorktree(
|
|
|
390
388
|
if (!existsSync(wtPath)) {
|
|
391
389
|
nativeWorktreePrune(basePath);
|
|
392
390
|
if (deleteBranch) {
|
|
393
|
-
try { nativeBranchDelete(basePath, branch, true); } catch
|
|
391
|
+
try { nativeBranchDelete(basePath, branch, true); } catch { /* branch may not exist */ }
|
|
394
392
|
}
|
|
395
393
|
return;
|
|
396
394
|
}
|
|
@@ -424,8 +422,8 @@ export function removeWorktree(
|
|
|
424
422
|
logWarning("reconcile", `Submodule changes detected — stash failed, changes may be lost during force removal`, { worktree: name, path: resolvedWtPath });
|
|
425
423
|
}
|
|
426
424
|
}
|
|
427
|
-
} catch
|
|
428
|
-
|
|
425
|
+
} catch {
|
|
426
|
+
// submodule status failed — proceed with normal removal
|
|
429
427
|
}
|
|
430
428
|
}
|
|
431
429
|
|
|
@@ -456,11 +454,11 @@ export function removeWorktree(
|
|
|
456
454
|
// Remove worktree: try non-force first when submodules have changes,
|
|
457
455
|
// falling back to force only after submodule state has been preserved.
|
|
458
456
|
const useForce = hasSubmoduleChanges ? false : force;
|
|
459
|
-
try { nativeWorktreeRemove(basePath, resolvedWtPath, useForce); } catch
|
|
457
|
+
try { nativeWorktreeRemove(basePath, resolvedWtPath, useForce); } catch { /* may fail */ }
|
|
460
458
|
|
|
461
459
|
// If the directory is still there (e.g. locked), try harder with force
|
|
462
460
|
if (existsSync(resolvedWtPath)) {
|
|
463
|
-
try { nativeWorktreeRemove(basePath, resolvedWtPath, true); } catch
|
|
461
|
+
try { nativeWorktreeRemove(basePath, resolvedWtPath, true); } catch { /* may fail */ }
|
|
464
462
|
}
|
|
465
463
|
|
|
466
464
|
// (#2821) If the worktree directory STILL exists after both native removal
|
|
@@ -490,7 +488,7 @@ export function removeWorktree(
|
|
|
490
488
|
nativeWorktreePrune(basePath);
|
|
491
489
|
|
|
492
490
|
if (deleteBranch) {
|
|
493
|
-
try { nativeBranchDelete(basePath, branch, true); } catch
|
|
491
|
+
try { nativeBranchDelete(basePath, branch, true); } catch { /* branch may not exist */ }
|
|
494
492
|
}
|
|
495
493
|
}
|
|
496
494
|
|
|
@@ -298,9 +298,7 @@ export async function showInterviewRound(
|
|
|
298
298
|
// Auto-open the notes field when "None of the above" is selected
|
|
299
299
|
// so the user can immediately provide a free-text explanation
|
|
300
300
|
// instead of being trapped in a re-asking loop (bug #2715).
|
|
301
|
-
|
|
302
|
-
// otherwise Enter from notes mode loops back here endlessly.
|
|
303
|
-
if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx) && !states[currentIdx].notes) {
|
|
301
|
+
if (!isMultiSelect(currentIdx) && states[currentIdx].cursorIndex === noneOrDoneIdx(currentIdx)) {
|
|
304
302
|
states[currentIdx].notesVisible = true;
|
|
305
303
|
focusNotes = true;
|
|
306
304
|
loadStateToEditor();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lsp-legacy-alias.test.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/lsp-legacy-alias.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// GSD2 — Regression test for LSP legacy server key aliases
|
|
2
|
-
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
3
|
-
/**
|
|
4
|
-
* When a default server key is renamed (e.g., kotlin-language-server → kotlin-lsp),
|
|
5
|
-
* user overrides referencing the old key must still merge correctly via LEGACY_ALIASES.
|
|
6
|
-
*
|
|
7
|
-
* This test exercises the merge path through loadConfig() with a temp project
|
|
8
|
-
* containing an lsp.json that uses the legacy key.
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, beforeEach, afterEach } from "node:test";
|
|
11
|
-
import assert from "node:assert/strict";
|
|
12
|
-
import * as fs from "node:fs";
|
|
13
|
-
import * as path from "node:path";
|
|
14
|
-
import * as os from "node:os";
|
|
15
|
-
import { loadConfig } from "./config.js";
|
|
16
|
-
describe("LSP legacy server key aliases", () => {
|
|
17
|
-
let tmpDir;
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "lsp-alias-test-"));
|
|
20
|
-
});
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
23
|
-
});
|
|
24
|
-
it("merges user override with legacy key 'kotlin-language-server' into 'kotlin-lsp'", () => {
|
|
25
|
-
// Write an lsp.json that uses the old key name with a command that exists (node)
|
|
26
|
-
// so resolveCommand doesn't filter it out.
|
|
27
|
-
const overrideConfig = {
|
|
28
|
-
servers: {
|
|
29
|
-
"kotlin-language-server": {
|
|
30
|
-
command: "node",
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
fs.writeFileSync(path.join(tmpDir, "lsp.json"), JSON.stringify(overrideConfig));
|
|
35
|
-
// Also add root markers so the server is detected
|
|
36
|
-
fs.writeFileSync(path.join(tmpDir, "build.gradle.kts"), "");
|
|
37
|
-
const config = loadConfig(tmpDir);
|
|
38
|
-
// The merged config should have kotlin-lsp (new key) with the user's command override
|
|
39
|
-
const kotlinServer = config.servers["kotlin-lsp"];
|
|
40
|
-
assert.ok(kotlinServer, "kotlin-lsp should exist in merged config");
|
|
41
|
-
assert.equal(kotlinServer.command, "node", "command should be overridden from user config via legacy alias");
|
|
42
|
-
assert.ok(kotlinServer.fileTypes.includes(".kt"), "fileTypes should be inherited from defaults");
|
|
43
|
-
// The old key should NOT appear as a separate entry
|
|
44
|
-
assert.equal(config.servers["kotlin-language-server"], undefined, "legacy key should not appear as separate server");
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
//# sourceMappingURL=lsp-legacy-alias.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lsp-legacy-alias.test.js","sourceRoot":"","sources":["../../../src/core/lsp/lsp-legacy-alias.test.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,4DAA4D;AAE5D;;;;;;GAMG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC9C,IAAI,MAAc,CAAC;IAEnB,UAAU,CAAC,GAAG,EAAE;QACf,MAAM,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QAC1F,iFAAiF;QACjF,2CAA2C;QAC3C,MAAM,cAAc,GAAG;YACtB,OAAO,EAAE;gBACR,wBAAwB,EAAE;oBACzB,OAAO,EAAE,MAAM;iBACf;aACD;SACD,CAAC;QACF,EAAE,CAAC,aAAa,CACf,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,EAC7B,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAC9B,CAAC;QAEF,kDAAkD;QAClD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,EAAE,EAAE,CAAC,CAAC;QAE5D,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAElC,sFAAsF;QACtF,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAClD,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,0CAA0C,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CACX,YAAY,CAAC,OAAO,EACpB,MAAM,EACN,gEAAgE,CAChE,CAAC;QACF,MAAM,CAAC,EAAE,CACR,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EACtC,6CAA6C,CAC7C,CAAC;QAEF,oDAAoD;QACpD,MAAM,CAAC,KAAK,CACX,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,EACxC,SAAS,EACT,iDAAiD,CACjD,CAAC;IACH,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["// GSD2 — Regression test for LSP legacy server key aliases\n// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>\n\n/**\n * When a default server key is renamed (e.g., kotlin-language-server → kotlin-lsp),\n * user overrides referencing the old key must still merge correctly via LEGACY_ALIASES.\n *\n * This test exercises the merge path through loadConfig() with a temp project\n * containing an lsp.json that uses the legacy key.\n */\n\nimport { describe, it, beforeEach, afterEach } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { loadConfig } from \"./config.js\";\n\ndescribe(\"LSP legacy server key aliases\", () => {\n\tlet tmpDir: string;\n\n\tbeforeEach(() => {\n\t\ttmpDir = fs.mkdtempSync(path.join(os.tmpdir(), \"lsp-alias-test-\"));\n\t});\n\n\tafterEach(() => {\n\t\tfs.rmSync(tmpDir, { recursive: true, force: true });\n\t});\n\n\tit(\"merges user override with legacy key 'kotlin-language-server' into 'kotlin-lsp'\", () => {\n\t\t// Write an lsp.json that uses the old key name with a command that exists (node)\n\t\t// so resolveCommand doesn't filter it out.\n\t\tconst overrideConfig = {\n\t\t\tservers: {\n\t\t\t\t\"kotlin-language-server\": {\n\t\t\t\t\tcommand: \"node\",\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t\tfs.writeFileSync(\n\t\t\tpath.join(tmpDir, \"lsp.json\"),\n\t\t\tJSON.stringify(overrideConfig),\n\t\t);\n\n\t\t// Also add root markers so the server is detected\n\t\tfs.writeFileSync(path.join(tmpDir, \"build.gradle.kts\"), \"\");\n\n\t\tconst config = loadConfig(tmpDir);\n\n\t\t// The merged config should have kotlin-lsp (new key) with the user's command override\n\t\tconst kotlinServer = config.servers[\"kotlin-lsp\"];\n\t\tassert.ok(kotlinServer, \"kotlin-lsp should exist in merged config\");\n\t\tassert.equal(\n\t\t\tkotlinServer.command,\n\t\t\t\"node\",\n\t\t\t\"command should be overridden from user config via legacy alias\",\n\t\t);\n\t\tassert.ok(\n\t\t\tkotlinServer.fileTypes.includes(\".kt\"),\n\t\t\t\"fileTypes should be inherited from defaults\",\n\t\t);\n\n\t\t// The old key should NOT appear as a separate entry\n\t\tassert.equal(\n\t\t\tconfig.servers[\"kotlin-language-server\"],\n\t\t\tundefined,\n\t\t\t\"legacy key should not appear as separate server\",\n\t\t);\n\t});\n});\n"]}
|