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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//! Daemon mode — keeps Store open to eliminate CLI startup overhead (M-17-A).
//!
//! The daemon listens on a Unix socket (`~/.mati/<slug>/mati.sock`) and handles
//! newline-delimited JSON requests. Hook commands and CLI commands (via
//! `StoreProxy`) route through the socket to skip the ~150ms SurrealKV init
//! cost and avoid lock contention against the daemon's exclusive flock.
//!
//! ## Protocol — v2 only on the public wire
//!
//! One v2 `protocol::Request` per connection, one v2 `protocol::Response`,
//! then close. There is no v1 fallback path on the public socket; the
//! legacy `(cmd_str, args)` form is mapped to v2 internally by
//! `daemon_result` / `protocol::v1_to_v2_command` for callers that have
//! not yet migrated to typed `daemon_v2`.
//!
//! ```json
//! // Request — v2
//! {"v":2,"id":"<uuid>","session":"<uuid>","cmd":{"type":"Ping"}}
//! {"v":2,"id":"<uuid>","session":"<uuid>","cmd":{"type":"Get","key":"file:src/main.rs"}}
//!
//! // Response — v2
//! {"v":2,"id":"<uuid>","status":"ok","data":<value>}
//! {"v":2,"id":"<uuid>","status":"err","code":"<error_code>","message":"description"}
//! ```
//!
//! ## Lifecycle
//!
//! Self-managing — no agent-specific session hooks required:
//! - Start: `mati daemon start` (or any agent's session-start script)
//! - Auto-shutdown: after [`IDLE_SHUTDOWN_SECS`] of wall-clock inactivity
//! AND zero active UDS connections. Wall-clock (vs tokio monotonic) so
//! sleep/wake cycles count toward idle time. The active-connection
//! gate (γ-C5) prevents the daemon from exiting while an `mati serve`
//! MCP proxy is holding a long-lived UDS connection — without the
//! gate, a long Claude/Codex session that paused between tool calls
//! would silently lose its daemon.
//! - Signal shutdown: SIGINT / SIGTERM → flush store, remove socket + PID file.
//! - Stop: `mati daemon stop` is **synchronous and authoritative**: when the
//! command returns Ok, the daemon process is gone, the SurrealKV flock is
//! released, and `mati.sock` / `mati.pid` are unlinked. Refuses (exit 1)
//! when the socket is owned by an active `mati serve` (MCP) unless the
//! caller passes `--force`.
//! - `mati init` bypasses `StoreProxy` and opens the store directly, so it
//! requires the daemon to be stopped first. Most other CLI commands
//! route through the socket and run while the daemon is up.
//!
//! ## Connection model
//!
//! Bounded-concurrent: handlers are spawned into a `JoinSet` capped by a
//! `Semaphore(MAX_DAEMON_CONNECTIONS)`. Reads on the underlying
//! `RwLock<Graph>` parallelize; writes serialize at the lock layer. Beyond
//! the limit, the accept loop pauses (the OS socket backlog absorbs the
//! surplus) — bounded memory under flood. Mirrors the embedded
//! `serve_daemon_socket` loop in `mcp/server.rs` so both daemon paths share
//! identical concurrency + drain semantics.
use ;
use ;
use Arc;
use ;
use ;
use ;
use ;
use ;
use Graph;
use PolicyMatcherSet;
use ;
// ── CLI subcommand types ──────────────────────────────────────────────────────
/// `mati daemon <start|stop|status>` — manage the background daemon process.
/// Arguments for `mati daemon stop`.
///
/// Default behavior: SIGTERM the daemon, wait up to `--timeout` for exit,
/// escalate to SIGKILL on timeout. After γ, `mati serve` proxies survive
/// daemon restarts transparently via `ensure_daemon` auto-respawn, so the
/// default flow is non-destructive to active MCP sessions.
///
/// Flag semantics (γ-C6):
///
/// - `--force`: send SIGKILL directly, no SIGTERM grace period. Useful
/// when a daemon is wedged or you need an immediate kill. Also retains
/// its historical meaning of overriding the safety refusal on
/// MCP-owned / unknown-owned sockets (pre-γ daemons or out-of-band
/// processes). Active `mati serve` proxies still auto-respawn the
/// daemon — they remain reachable to their MCP clients.
/// - `--include-mcp`: additionally kill any running `mati serve` proxy
/// processes. This is the "I really want to end the MCP session"
/// destructive option. Without it, killing the daemon leaves serve
/// proxies running; with it, serve processes also die and Codex /
/// Claude's MCP transport closes.
/// - `--no-wait`: SIGTERM (or SIGKILL with `--force`) and return without
/// waiting. Escape hatch for supervisor scripts.
// ── Protocol constants ───────────────────────────────────────────────────────
//
// These previously had local definitions duplicating values in
// `mcp::server`. Both daemon paths share the same operational policy
// (same idle thresholds, same socket-path limit, same concurrency cap),
// and drift between them was a real risk: pass-11 found `auto_drain`
// missing from one path while present in the other for exactly this
// reason. All now resolve to a single canonical definition.
use ;
/// Outcome of a [`daemon_result`] call. Each variant carries the information
/// the caller needs to decide whether to fall back to `Store::open`.
// ── Connection timeout ───────────────────────────────────────────────────────
// ── Server ───────────────────────────────────────────────────────────────────
/// Start the daemon: open the Store, bind the Unix socket, and serve forever.
///
/// Exits cleanly on SIGINT, SIGTERM, or after [`IDLE_SHUTDOWN_SECS`] of wall-clock
/// inactivity with no active UDS connections (γ-C5 gate). For the historic wall-clock
/// idle time. Removes the socket and PID file on any exit path.
use kill_and_wait;
use ;
pub use ;
use ;
use daemon_get;
use serve_loop_graceful;
pub use ;
pub use run_daemon_start;
pub use ;