Problem
The long-lived daemons (serve / mcp) and the auto-spawned cli-daemon all want the same per-project Unix socket (/tmp/codedb-<uid>-<hash16>.sock), and the loser of the bind race simply gives up:
- An auto-spawned cli-daemon that loses the bind sets
shutdown and exits promptly (good).
- A long-lived
serve / mcp daemon that loses the bind permanently disables its CLI proxy (cliDaemonListen logs bind … failed — proxy disabled and returns; the serve/mcp daemons pass a shutdown flag they never watch).
So the common sequence — warm cli-daemon already running, then the user starts a long-lived codedb <root> serve or an MCP client spawns codedb mcp — leaves the older, idle-timeout-bound cli-daemon owning the socket while the newer long-lived daemon (with the freshest index and no idle exit) can never serve CLI calls. When the cli-daemon eventually idle-exits, the socket goes away entirely: the serve daemon never retries the bind, and every subsequent CLI call falls back to a cold re-index until something respawns a cli-daemon.
This is the "serve-vs-cli-daemon socket handover" item parked in the session todo.
Expected
Socket ownership should hand over to the longest-lived / freshest daemon:
- A starting
serve / mcp daemon that loses the bind should be able to ask the current owner to yield (e.g. a handover request over the socket; the cli-daemon unlinks + closes and exits, the new daemon retries the bind), and
- A long-lived daemon whose bind failed should retry periodically (cheap: on the existing 1 s watchdog tick) so it picks the socket up when the previous owner exits, instead of leaving CLI calls cold forever.
Failing test
Per the repo rule this needs a failing test before implementation; the testable seam today:
test "issue-XX: serve daemon retries the cli socket bind after the owner exits" {
// 1. bind the project socket from the test (stand-in for a live cli-daemon)
// 2. start cliDaemonListen for a serve-mode explorer -> bind fails, proxy disabled
// 3. close + unlink the test socket
// 4. expect cliDaemonListen to acquire the socket within ~2 watchdog ticks
// (currently: never — it returned at step 2)
}
(Requires extracting the bind/retry loop from cliDaemonListen enough to drive it from a test; the current single-shot shape returns before step 3 can be observed.)
Fix
Sketch in Expected. Retry-on-watchdog-tick (2) is the small, safe half and removes the cold-fallback cliff; explicit handover (1) is the full fix.
Problem
The long-lived daemons (
serve/mcp) and the auto-spawned cli-daemon all want the same per-project Unix socket (/tmp/codedb-<uid>-<hash16>.sock), and the loser of the bind race simply gives up:shutdownand exits promptly (good).serve/mcpdaemon that loses the bind permanently disables its CLI proxy (cliDaemonListenlogsbind … failed — proxy disabledand returns; the serve/mcp daemons pass ashutdownflag they never watch).So the common sequence — warm cli-daemon already running, then the user starts a long-lived
codedb <root> serveor an MCP client spawnscodedb mcp— leaves the older, idle-timeout-bound cli-daemon owning the socket while the newer long-lived daemon (with the freshest index and no idle exit) can never serve CLI calls. When the cli-daemon eventually idle-exits, the socket goes away entirely: the serve daemon never retries the bind, and every subsequent CLI call falls back to a cold re-index until something respawns a cli-daemon.This is the "serve-vs-cli-daemon socket handover" item parked in the session todo.
Expected
Socket ownership should hand over to the longest-lived / freshest daemon:
serve/mcpdaemon that loses the bind should be able to ask the current owner to yield (e.g. ahandoverrequest over the socket; the cli-daemon unlinks + closes and exits, the new daemon retries the bind), andFailing test
Per the repo rule this needs a failing test before implementation; the testable seam today:
(Requires extracting the bind/retry loop from
cliDaemonListenenough to drive it from a test; the current single-shot shape returns before step 3 can be observed.)Fix
Sketch in Expected. Retry-on-watchdog-tick (2) is the small, safe half and removes the cold-fallback cliff; explicit handover (1) is the full fix.