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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
//! The inbox substrate (ARCH §2.11 *Messages*).
//!
//! A **message** is content addressed to an existing agent, deposited
//! into the recipient's inbox and delivered at its next step boundary.
//! This module lands the deposit half of the channel: the executor lock
//! ([`lock`]), the create-only deposit ([`deposit`]), and the
//! deposit-starts-a-driver probe ([`probe_and_launch`]) behind the
//! `lernie message` verb ([`cli_message`]). The delivery drain that moves
//! these files into the transcript lives with the executor's step loop
//! (bl-1129, [`crate::prompt::dispatch`] — a driver, not a writer). The
//! workspace-wide sweep-and-flush behind the **operator verb**
//! `lernie scan` — crash-rate compensation, never wired into any driver
//! hot path (§2.11) — is [`scan`] (bl-d148, bl-5846); it, the
//! result-message return path (bl-4ce8), and the §2.11 exit protocol's
//! self-directed launch (bl-5846) ride this same substrate.
//!
//! **Writer/driver totality (§2.11).** `lernie message` is a *writer*:
//! it deposits and, if it observes the recipient quiescent (the lock
//! probe succeeds), *launches* a driver and exits — launching is not
//! driving, so the probe lease is released the instant it is taken and
//! never held to step. A driver that loses the acquire exits as a clean
//! no-op. Because no verb combines the two arms, the losing path is the
//! same code as the uncontended one.
pub use ;
pub use ;
pub use scan;
use crate;
use OsStr;
use io;
use ;
/// Workspace-root directory holding every agent's inbox, namespaced by
/// agent id exactly like `steps/` (§2.2, §2.11). Outside every worktree.
pub const INBOX_DIR: &str = "inbox";
/// The reserved sender token for a deposit made by the user rather than
/// by an agent (§2.11 — `<sender>` is an agent id or `user`).
pub const USER_SENDER: &str = "user";
/// The per-agent inbox directory `<workspace>/inbox/<agent-id>/` — the
/// deposit target and the executor lock's home (§2.11).
/// The parent agent's id — `agent_id` minus its last descent segment
/// (§2.11 "the parent's address is the agent's own id minus its last
/// descent segment") — or `None` when `agent_id` is a root (it has no
/// parent). An agent id is a hyphenated descent of `<ts>-<short>`
/// segments (§2.3), and both the compact timestamp and the short id are
/// hyphen-free (`clock.rs`), so each segment is exactly two
/// hyphen-delimited tokens: a root is two tokens, and stripping the last
/// segment removes the trailing two. This is the same token arithmetic
/// [`crate::prompt::budget::derive::depth`] already relies on.
/// Deposit a child's **result message** (§2.6) on its own behalf, into
/// its parent's inbox — the total return step (§2.3 step 5). A no-op
/// returning `Ok(None)` when `agent_id` is a root ([`parent_of`] is
/// `None`): a root has no parent inbox, its terminal response answers
/// the user instead (§2.4). Otherwise deposits and returns the created
/// path. The deposit is executor-side, never a model tool call ("Return
/// is not a verb", `docs/PRINCIPLES.md`).
/// Launches a driver for a quiescent agent — the one launch seam shared
/// by the writer's post-deposit probe, the `lernie scan` flush, and the
/// exit protocol's self-directed launch (§2.11). Kept as a trait so
/// every launch decision is testable with the spawn injected, and so the
/// production launch target can change without touching the callers. No
/// launcher ever decides whether launching is warranted; warrant is
/// decided by the launched driver under the lock (§2.11).
/// The production launcher: detach-spawns `lernie advance <workspace>
/// <agent>` (§6), the workflow-chain driver that takes the lease,
/// rematerializes the worktree, drains the inbox, and steps (its
/// own-branch entry is [`crate::prompt::dispatch::driver::drive`]).
///
/// The spawn is **detached per §2.11**: `setsid` in the child (its own
/// session and process group — a §2.9 stop cascade against the launching
/// process never reaches the driver, and the driver outlives a launcher
/// running inside another agent's tool subprocess or a user's script),
/// stdio bound to null (the driver's observable state is its on-disk
/// step records and commits, §3.1), and [`baton::LOCK_FD_ENV`] scrubbed
/// (a launched driver *acquires*; only an exec'd successor adopts, §6).
/// Fire-and-forget: the child is never waited on — a launcher is
/// short-lived by design, and the unreaped driver reparents to init when
/// the launcher exits.
/// The driver spawn's between-fork-and-exec hook: detach the child from
/// the launching agent's process group so a §2.9 cascade against the
/// parent never reaps the driver. `setsid` failure (caller already a
/// group leader) is ignored — the spawn proceeds grouped, which only
/// widens the cascade. Called in-process by its test: counters
/// incremented in the forked child die with the `exec`.
/// Outcome of the post-deposit probe (§2.11 *A deposit into a quiescent
/// agent starts a driver*).
/// Probe the executor lock for `agent_id` and, finding it quiescent,
/// release the probe and launch a driver (§2.11). A non-blocking
/// try-acquire whose *success* means nobody is driving: on success the
/// lease is dropped immediately — launching is not driving — before the
/// driver is launched, so the driver can win the acquire.
/// Every way [`cli_message`] can fail.
/// The `lernie message <workspace> <agent> <content>` verb (§2.11,
/// §3.4): deposit, then probe-and-launch. `sender` is resolved by the
/// caller — [`resolve_cli_sender`] for the bin, the calling agent's id
/// for the `message` tool — never from model input. Returns the probe
/// outcome so the caller can report whether a driver was launched.
/// CLI entry for `lernie message <workspace> <agent> <content>` (§3.4).
/// Guards the recipient first — the layout (§2.2) and then the agent's
/// existence ([`crate::workspace::agent_exists`]): §2.11 addresses a
/// message to an *existing* agent, so a deposit that no drain could ever
/// come for is declined loudly rather than written into a directory that
/// nothing will ever read. Returns the probe outcome so the verb layer
/// can advise on a branch whose latest model call failed (§2.10).
/// Kept in the lib so the bin stays under the 300-line cap and the wiring
/// is unit-testable — the same discipline as `stop::cli_run`. Resolves
/// the sender from the live `LERNIE_CONV_BRANCH` ([`resolve_cli_sender`])
/// and wires the production clock plus the real [`AdvanceLauncher`]
/// detached spawn (§2.11) at `driver_target` — the running-binary path
/// the exec binding injects (`cmd::Fx::driver_target`, §3.4), never
/// resolved in the library.
/// Resolve the deposit sender for a direct `lernie message` invocation
/// from the `LERNIE_CONV_BRANCH` value (§3.3): the calling agent's id
/// when the harness set it (an agent's `message` tool re-entering the
/// verb), else [`USER_SENDER`] for a bare user/frontend invocation. An
/// unset *or empty* value is `user`, mirroring the `LERNIE_HOME`
/// set-and-non-empty discipline (§2.2).