Final review pass on the local provider: - Tear the instance down when `initialize` REJECTS (utf-8 negotiation, malformed result), not only on abort, so a permanently-rejecting `ready` is never pooled. - Use the group-aware SIGKILL on a framing failure so helpers are reached. - Validate maxMessageBytes and maxDocumentBytes positive at load alongside the other byte caps. - Fix the location renderer's outside-workspace check to match a `..` segment exactly, so an in-workspace path like `..generated/a.ts` stays relative. - Document the accepted ancestor-directory symlink-swap TOCTOU under the trusted-host model (O_NOFOLLOW guards only the final component).
lsp/ - LSP capability family
The language-server capability seam: an abstract LSP interface, a generic stdio provider, and the model-facing lsp tool. All product packages.
| Package | Role | ctx key |
|---|---|---|
lsp/ |
Abstract LSP seam (provider registry by branded id + extension mapping, per-query selection, vocabulary, LspError) |
ctx.lsp |
lsp-local/ |
Generic stdio language-server provider (spawn, JSON-RPC, transient-open queries) | (registers on ctx.lsp) |
tool-lsp/ |
Model-facing lsp tool (four operations, one-based UTF-16 cursor coordinates) |
(registers on ctx.tools) |
The interface lives at lsp/lsp/. The seam exposes exactly four semantic operations — definition, references, implementation, hover — and no generic JSON-RPC escape hatch, so a provider swap does not change how the model asks for navigation and no protocol payload or unreviewed mutation reaches the model contract. Providers register capabilities, not tools; tool-lsp is the only owner of the model-facing name, schema, prompt guidance, and presentation.
See the LSP capability seam RFC for the design rationale, including why documents open transiently per query, why the local host reads through Node APIs rather than ctx.fs, and why extension ownership is exclusive within one runtime.