1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! `sqry-daemon` — long-lived code-graph service.
//!
//! The daemon (`sqryd` binary) owns one or more loaded code graphs in memory,
//! watches source trees for changes, and serves CLI / LSP / MCP clients over a
//! shared Unix-domain socket (named pipe on Windows). The goal is to amortise
//! graph-load cost across every sqry invocation on a machine while preserving
//! the semantic guarantees of direct-mode sqry (bijective per-file buckets,
//! tombstone compaction, `ArcSwap` publish, etc.).
//!
//! # Architecture at a glance
//!
//! - [`config`] — parses `~/.config/sqry/daemon.toml` into a [`config::DaemonConfig`]
//! with every tuning knob from the Amendment-2 design (memory limits, working-set
//! multipliers, stale-serve age cap, debounce timing, interner compaction
//! threshold, log rotation, socket path).
//! - [`workspace`] *(Task 6)* — `WorkspaceManager` owns `LoadedWorkspace` state
//! (§G admission accounting, §H rebuild plumbing, §F bijection check).
//! - [`rebuild`] *(Task 7)* — per-workspace rebuild lane + coalescing (§J).
//! - [`ipc`] *(Task 8)* — JSON-RPC over UDS with a standard response envelope.
//! - [`lifecycle`] *(Task 9)* — pidfile locking, signal handling, service
//! unit generators.
//! - [`client`] *(Task 10)* — client library used by `sqry-cli` /
//! `sqry-lsp --daemon` / `sqry-mcp --daemon` to connect to a running daemon
//! and auto-start one if necessary.
//!
//! Only [`config`] and the public error type [`DaemonError`] are in the surface
//! today; later tasks in this plan land the other modules in order.
/// Task 9 U10 — production sqryd binary entry point.
///
/// Owns the clap CLI (`SqrydCli`), the ordered startup / shutdown lifecycle
/// (`run()`), and every `run_start` / `run_stop` / `run_status` /
/// `run_install_*` / `run_print_config` dispatcher. `main.rs` calls
/// `sqry_daemon::entrypoint::main_impl()` which parses the CLI, builds the
/// tokio runtime, and maps every error to a POSIX `sysexits.h` exit code via
/// `DaemonError::exit_code()`.
/// Task 9 — daemon binary lifecycle: pidfile locking, signal handling, service
/// unit generators, log rotation, and auto-spawn primitives.
///
/// The module is built up incrementally across Task 9 units. Only the units
/// that have landed so far are present; later units (U3–U10) add submodules as
/// they are implemented.
/// Phase 8c U8 — in-daemon MCP host.
///
/// Hosts an rmcp `ServerHandler` in-process for each MCP shim
/// byte-pump connection (see [`mcp_host::host_mcp_on_streams`]),
/// routing every `tools/call` through Phase 8b's
/// `daemon_adapter::execute_*_for_daemon` path via the shared
/// [`ipc::tool_core::classify_and_execute`] pipeline. MCP tool
/// behaviour is bit-identical to direct sqryd JSON-RPC tool dispatch.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// JSON-RPC error code: per-tool invocation exceeded
/// `DaemonConfig::tool_timeout_secs`. Emitted by
/// `tool_core::classify_and_execute` (Task 8 Phase 8c U6) when the
/// `tokio::time::timeout(tool_timeout, spawn_blocking(run))` outer
/// timer fires. The detached `JoinHandle` is dropped — the OS thread
/// may continue executing the tool closure but its result is
/// discarded.
///
/// Source: Task 8 Phase 8c design §O (iter-2 Codex-approved wire contract).
pub const JSONRPC_TOOL_TIMEOUT: i32 = -32000;
/// JSON-RPC error code: workspace build failed and no prior good graph exists.
///
/// Source: Amendment 1 §C, Amendment 2 §G.7.
pub const JSONRPC_WORKSPACE_BUILD_FAILED: i32 = -32001;
/// JSON-RPC error code: the workspace is serving a Failed state, but the last
/// successful build is older than `stale_serve_max_age_hours`.
///
/// Source: Amendment 1 §C.
pub const JSONRPC_WORKSPACE_STALE_EXPIRED: i32 = -32002;
/// JSON-RPC error code: admission control could not satisfy a reservation
/// after evicting every non-pinned workspace.
///
/// Source: Amendment 2 §G.1, §G.7.
pub const JSONRPC_MEMORY_BUDGET_EXCEEDED: i32 = -32003;
/// JSON-RPC error code: the workspace was evicted or removed between a
/// rebuild dispatch and its admission / publish commit. Callers must treat
/// this as a terminal signal on the affected `WorkspaceKey` — subsequent
/// dispatches require a fresh `get_or_load` first.
///
/// Source: Amendment 2 §J (same-workspace rebuild serialization), Task 7
/// Phase 7b1 (runner-role gate + `reserve_rebuild` eviction check).
///
/// # Daemon public JSON-RPC error codes (authoritative table)
///
/// | Code | Variant | Semantics |
/// |---------|------------------------|----------------------------------------------------------------|
/// | -32000 | `ToolTimeout` | Per-tool `tool_timeout_secs` deadline elapsed (Phase 8c U6). |
/// | -32001 | `WorkspaceBuildFailed` | Build failed, no prior good graph. |
/// | -32002 | `WorkspaceStaleExpired`| Stale-serve window exceeded `stale_serve_max_age_hours`. |
/// | -32003 | `MemoryBudgetExceeded` | Admission cannot fit even after evicting all non-pinned. |
/// | -32004 | `WorkspaceEvicted` | Workspace gone mid-rebuild; caller must re-`get_or_load`. |
/// | -32602 | `InvalidArgument` | Tool-argument validation failure (JSON-RPC standard). |
/// | -32603 | `Internal` | Catch-all bubbled from `sqry_mcp::daemon_adapter` execution. |
/// | n/a | `AlreadyRunning` | Another sqryd holds the pidfile lock (Task 9 U1). Exit 75. |
/// | n/a | `AutoStartTimeout` | `start_detached` socket poll timed out (Task 9 U1). Exit 69. |
/// | n/a | `SignalSetup` | `tokio::signal` handler install failed (Task 9 U1). Exit 70. |
pub const JSONRPC_WORKSPACE_EVICTED: i32 = -32004;
/// JSON-RPC 2.0 standard "Invalid params" error code.
///
/// Surfaced by `tool_core` argument validation (Phase 8c U6) BEFORE
/// workspace classification runs — e.g. `resolve_index_root` failures
/// and missing `path` arguments in MCP tool args.
pub const JSONRPC_INVALID_PARAMS: i32 = -32602;
/// JSON-RPC 2.0 standard "Internal error" code. Catch-all for errors
/// bubbling from `sqry_mcp::daemon_adapter` tool execution that don't
/// map to a more specific `DaemonError` variant.
pub const JSONRPC_INTERNAL_ERROR: i32 = -32603;
/// Version of the daemon wire envelope (`DaemonHelloResponse.envelope_version`).
///
/// Re-exported from `sqry-daemon-protocol` so callers that only depend on
/// `sqry-daemon` (or on `sqry-daemon-client`) both see the same single source
/// of truth. See [`sqry_daemon_protocol::ENVELOPE_VERSION`] for the canonical
/// definition and bump policy.
pub use ENVELOPE_VERSION;
// ---------------------------------------------------------------------------
// Shared test-only ENV_LOCK
// ---------------------------------------------------------------------------
/// Single process-wide mutex for tests that manipulate `XDG_RUNTIME_DIR`.
///
/// Multiple test modules (`pidfile`, `detach`, `config`) run as threads in the
/// same binary. Each module previously had its own `ENV_LOCK`, which allowed
/// concurrent `XDG_RUNTIME_DIR` mutations and produced flaky pidfile-PID
/// mismatches. This shared lock serialises all env-var mutations across every
/// `#[cfg(test)]` module in the crate.
pub static TEST_ENV_LOCK: Mutex = new;