weaverd backgrounds itself using daemonize-me and manages runtime artefacts
under the same directory as the Unix socket (for example
$XDG_RUNTIME_DIR/weaver). Launching the daemon creates a lock file
(weaverd.lock), a PID file (weaverd.pid), and a health snapshot
(weaverd.health). PID and health files are written atomically, so observers
never see a partially written payload. Attempts to start a second copy while
one is running fail fast with an "already running" error that reports the
existing PID. When the original launch is still initializing and has not yet
published a PID, the second invocation now reports "launch already in progress"
instead of removing the lock. If the daemon exited uncleanly, the new instance
removes the stale files before continuing.
The daemon now binds a socket listener as part of startup. It binds to the
configured --daemon-socket endpoint and accepts multiple client connections
concurrently. On Unix targets, stale socket files are removed only after
confirming no listener responds, while actively used sockets cause the daemon
to fail fast with a clear error. The listener removes the Unix socket file on
shutdown to avoid lingering bind failures.
The daemon implements a JSONL request dispatch loop that reads CommandRequest
messages from connected clients, routes them to the appropriate domain handler,
and streams DaemonMessage responses back. Request parsing validates the JSONL
structure and rejects malformed input with structured error messages. Domain
routing supports observe, act, and verify commands. Unknown domains or
operations return structured errors with exit status 1.
The observe get-definition, observe get-card, and observe graph-slice
operations are fully implemented. get-definition accepts --uri and
--position, infers the language from the file extension, initializes the
appropriate language server, and returns definition locations as JSON.
get-card accepts the same location arguments plus --detail, reads the
target file locally, and returns a Tree-sitter-backed symbol card for supported
Rust, Python, and TypeScript files. graph-slice accepts the same location
arguments plus traversal, detail, and budget options, and returns a stable
same-file graph-slice envelope. Missing or malformed arguments return
structured error messages with exit status 1. Operations outside the implemented
observe subcommands, and outside the implemented act and verify flows,
may return "not yet implemented" responses while backend wiring is being
completed.
The health snapshot is a single-line JSON document describing the current state, enabling operators and automation to poll readiness without speaking the daemon protocol. Example:
{"status":"ready","pid":12345,"timestamp":1713356400}
The status transitions through starting, ready, and stopping before the
files are removed on shutdown. Sending SIGTERM, SIGINT, SIGQUIT, or
SIGHUP prompts the daemon to log the request and complete its shutdown
sequence within a ten-second budget. For interactive debugging or CI jobs, set
WEAVER_FOREGROUND=1 to keep the daemon attached to the terminal while
preserving the same lock, PID, and health semantics.