zooqueenandHanzo Dev 0060fa0179 lsp: reap before announcing a death, and report how it died
0.1.9 taught stopped() to carry the server's last words and then reported none,
because it read them too early. attach's handshake path already says why: Close
kills the process AND WAITS, which is what drains the copy of its stderr, and
reading the tail before that races the words away. The reader's own exit path
had exactly that bug — it closed done first, so every mid-session death was
published with nothing attached.

done now means the reader has stopped AND the process is reaped, so anything
read after it is final. Both endings go through one reap, guarded by its own
Once: two concurrent Waits on one process is a race with no useful outcome.

And the exit STATUS, which is the part that matters here. A process killed by
the kernel — a seccomp verdict, the OOM killer, an rlimit — says nothing on
stderr at all, so the status is the only account of it that exists, and it was
being discarded. It now lands in the same tail as the words, so "server stopped"
can never again be the whole story.

This is diagnosis, not a cure. TypeScript answers its first query and then dies,
on EVERY tree shape — pure source, package.json, lockfile, .js/.mjs/.cjs alike
— which rules out the lockfile as the trigger and rules out my own earlier
reading of it. What is left is a silent death, and this is what makes it speak.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-09 23:41:24 -07:00

lsp

The jailed language-server daemon. It holds immutable per-(org, repo, commit) working trees, runs a language server over each one inside a jail with no network, and answers position questions about them.

The answer it exists for is a definition that leaves the repository and lands in a dependency — which a static symbol index structurally cannot give you.

POST /root       {org, repo, rev, files}       → {ready, cold, langs}
POST /root/warm  same body, only for a held repo
POST /ask        {org, repo, rev, op, path, line, character, relation}
                                               → the answer, or 409 {"need":"tree"}
GET  /healthz    liveness
GET  /readyz     readiness — green only once the jail proved out on this host

Everything else — the wire contract in full, the two-phase security model, the deployment, and what phase 2 is — is in LLM.md.

S
Description
Jailed language-server daemon: immutable per-(org,repo,commit) roots, gopls behind a seccomp jail with no network. Backs /v1/code/lsp.
Readme Apache-2.0
192 KiB
Languages
Go 93%
Dockerfile 7%