lsp-probe keeps one warm ruby-lsp daemon per worktree root, with warm and stop commands #600
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#600
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Branch lsp-probe-cli (ADR-0197) added bin/lsp-probe, a Thor CLI that spawns ruby-lsp over stdio per call (lib/os_sdlc/lsp_probe/query_runner.rb:21, Open3.popen3). Measured 2026-09-16: one lsp-probe call 4-9 s;
bin/evidence collect --root plugins/os-sdlc/lib Model::Db209 s because lib/os_sdlc/evidence/fingerprint.rb:83-91 runs one LSP query, and so one spawn, per method with no ast-grep sender. Daemon lifecycle management reduces per-call spawn overhead.Owner sketch
Cases
Daemon.connecton a root with no.cc-os/lsp/spawns once and writes sock and pid files (spawner double).Daemon.connecton the same root spawns nothing and attaches to the existing socket.connectremoves the files and spawns fresh.lsp-probe stop --root Xkills the pid and removes the two files; running it twice is a no-op with exit 0.lsp-probe warm --root Xreturns within 1 s and a followinglsp-probe defscall completes without a spawn.Origin
Work started via os-sdlc pipeline on branch ticket-600 (worktree off lsp-probe-cli, after #599
cab8b5ea). ADR-0198 recorded. Session 01153d94.Resolution
Done: LspProbe::Daemon with Paths/Spawner/Server/Query/Client/Connection/Idle/Stopper; Server routes defs/refs/symbols/outline through Daemon.connect; CLI gains warm, stop, hidden serve; Fingerprint's SharedRunner uses the daemon; QueryRunner deleted. Commit
4a348c3fon ticket-600, merges to lsp-probe-cli. ADR-0198 amended (hashed path, spawn not fork, abandoned-socket exit, TERM/KILL stop).Evidence: Suite 1295 green, rubocop clean. Measured: symbols 4.0 s cold -> 0.26 s warm; evidence collect Model::Db 10.5 s -> 5.2 s warm; after stop no ruby-lsp process and hashed dir empty. Pipeline impl 24: 15 dispatches, ended unexpected_pass escalation; pipeline output was a placeholder daemon (fork+sleep, empty sock file, connect returned nil, QueryRunner untouched); real daemon hand-finished. See #604.
Follow-ups: Kill the daemon process group (Spawner already sets pgroup: true; Stopper should signal -pid) so a hung ruby-lsp child cannot outlive lsp-probe serve: filed as a line here, ticket after user review. Daemon exit when the root tree disappears, not only the socket: dropped, abandoned-socket check covers the observed case. lsp-probe stop --all reaper for crashed daemons: dropped until seen. SessionEnd hook to stop daemons: covered by #601 worktree finish for pipeline roots; main-checkout daemons rely on idle exit.
jared referenced this issue2026-09-17 14:39:57 +00:00