| id | 231 |
|---|---|
| title | LSP newest-wins workspace singleton |
| status | ✅ |
| summary | A leaked editor extension host can outlive its window while staying alive and holding the LSP server's stdin open, so neither the stdin-EOF exit nor the processId watchdog fires and an orphaned `mdsmith lsp` keeps running beside the one a reload spawned. Add a newest-wins workspace singleton: each server records its workspace root in a shared registry under a per-process id; once a newer server claims the same root, the older one sends `mdsmith/superseded` and exits, and the VS Code extension suppresses the restart so exactly one server stays live per workspace. |
| model | |
| depends-on |
The processId watchdog
(internal/lsp/parentwatch.go)
reaps an mdsmith lsp server whose editor host has
died. It cannot reap one whose host is alive but
orphaned — a VS Code / code-server extension host
that survives its own window after an abrupt
reload. That host keeps the server's stdin pipe open
(so no EOF arrives) and still reports as alive (so
the watchdog stays quiet), and its language client
even respawns the server if it is killed. The result
is two servers for one workspace where the user wants
one.
Add a newest-wins workspace singleton so the older server steps aside on its own, leaving exactly one live server per workspace root.
- Add the registry and watcher in
internal/lsp/singleton.go:
a per-workspace owner file under the OS cache dir
(atomic claim, plain read), a
watchSingletonpoll loop mirroringwatchParentProcess, and astartSingletonWatchthat claims the workspace and steps aside when a newer owner appears. - On step-aside, send the
mdsmith/supersededserver-to-client notification, then exit — so the client knows the close is intentional. - Gate it behind
Options.EnableWorkspaceSingletonin internal/lsp/server.go; callstartSingletonWatchfromhandleInitialize; enable it in cmd/mdsmith/lsp.go. - In the VS Code extension, suppress the restart on
mdsmith/superseded: adecideClosepolicy in editors/vscode/src/wiring.ts and amarkSupersededhook on the error handler in editors/vscode/src/extension.ts. - Document the behavior and the
mdsmith/supersededcontract in the troubleshooting section of the VS Code guide.
- A second server started for the same workspace
root makes the older one send
mdsmith/supersededand exit, leaving one live server. - The feature is off by default so unit tests neither write to the real cache dir nor leak a watcher goroutine; the singleton tests drive the seams directly.
- The VS Code error handler does not restart the
server after
mdsmith/superseded. -
go test ./...andgo tool golangci-lint runpass. -
go run ./cmd/mdsmith check .passes.