(A1) terminate()/dispose()/service teardown keyed on direct-child settlement could leak a TERM-trapping descendant that outlived the leader (Codex reproduced it with a disowned trap-SIGTERM helper). kill()/terminate() now gate on tree liveness instead of outcome settlement; the SIGKILL escalation timer survives settle (unref'd, re-probing the tree); dispose's tier quiescence is whole-tree exit via a bounded waitForExit; the service's live set releases handles only when their tree is gone, and its teardown awaits tree exit. Three new suites pin the survivor scenarios end to end (terminate, dispose, service teardown). (A2) the escalation branch is now real tested behavior — its ignore is gone; the one remaining signalTree guard ignore states why it is unreachable through the handle verbs. (A3) docs contradictions fixed: the impl README's stale POSIX-only bullet now states the contained best-effort Windows tree story; the lsp-local README no longer claims taskkill failures stay visible (containment + the tree-liveness wait is the actual contract); the architecture tables (en+zh) list all three consumer families. (B1) OutputCollector keeps a byte-exact tail across uneven chunk boundaries (trim the head chunk instead of dropping it whole) — the LSP diagnostic-tail contract; pinned by a cross-chunk test. (B2) the subagent-acp coverage ignore is narrowed to exactly the never-settling success arm.
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 multi-server local backend (spawn, JSON-RPC, transient-open queries) | (registers providers 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 — goToDefinition, findReferences, goToImplementation, 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 Agent Note 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.