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
//! The fire (DESIGN §3.3, §8.1 step 2): mint the conversation's name and spawn
//! `litany prompt` **detached** — the goal exactly as the operator edited it.
//!
//! Split from [`exec`](super::exec) at §12's 300-line budget, along the seam the
//! design already draws: everything else in the start flow is a piped, gated
//! substrate step, while this is the one irreversible launch — and the one place
//! the §3.3 conversation mint runs for real. The mint is re-derived *here*, not
//! carried from the composer's preview: another instance may have taken the
//! predicted name between preview and Enter, so the preview is a prediction and
//! this mint is the truth.
use mint_conversation;
use ;
use ;
use crateCli;
use crate;
use Rng;
use io;
use Path;
// The verb and the name flag are `opslog::launch`'s (bl-b95e): the launch
// writes them into `ops.jsonl` and the §8.1 verdict reads them back out, so
// the two sides of that join have one home — `detached::sink`'s own argument
// about the file name, one field over.
use ;
/// litany's creation-time working-directory parameter (upstream bl-d0b4,
/// released 0.0.8): the §3.3 typed work-target binding's one channel.
const CWD_FLAG: &str = "--cwd";
/// litany's caller-supplied pinned document (upstream bl-fb5c, released 0.0.4):
/// the §3.7 project-instruction freeze's one channel.
const PIN_FLAG: &str = "--pin";
/// litany's config-lineage selector (upstream bl-a693, released 0.0.6): fork
/// off `config/<name>`'s head instead of `config/default`. The §8.7 birth
/// policy's one channel — the whole of how a ball's tags reach the model and
/// the skill set the drone is born with.
const CONFIG_FLAG: &str = "--config";
const YOG_NAME: &str = "YOG_NAME";
/// One fire, whole (§8.1): the `Prepared` a `/prompt` carries, the edited
/// `goal`, and `prepared.workspace` **located** (REMOTE §8, bl-f5f6) — the name
/// is the identity, the path is where the driver stands and what `litany
/// prompt` is aimed at.
///
/// One value rather than three parameters, for
/// [`fork::Fire`](crate::fork::Fire)'s reason exactly: a fire is all three or
/// none, so the argv below is a pure function of one value and no caller can
/// pass a goal for one workspace beside a `Prepared` from another.
/// `litany prompt --name <minted> [--cwd <target>] <workspace> <goal>` fired
/// **detached** (§8.1): own process
/// group, stdin/stdout→null, stderr→the per-spawn sink ([`opslog::detached::sink`]),
/// `YOG_NAME=<workspace name>` layered (§8, §3.2 — the harness channel the goal
/// text no longer duplicates), the driver standing in the workspace it drives.
/// `prepared` carries all of it,
/// composed once by [`goal::compose_prepared`](super::goal).
///
/// **`--cwd` is the work target's one channel** (§3.3, bl-6654 consuming
/// bl-2b8c's ruling / VISION §4.10 item 2): the rung's typed binding — the ball
/// rung's claim-derived `work/<id>` worktree, the path rung's directory — seeds
/// the agent's working-directory mark at creation, so every tool step of every
/// later turn runs there. It rides only when the rung binds something
/// ([`Prepared::binding`](super::Prepared::binding)); an absent flag is litany's
/// own default, the agent's worktree, which is exactly what the bare rung
/// means. It replaced a paragraph of goal prose naming the path, which reached
/// the model as content it had to notice and obey, and the initial process's
/// `current_dir`, which reached no tool step at all.
///
/// The conversation name mints first ([`mint_conversation`] over `occupied` + the
/// injected `rng`); an exhausted pool leaves a `["yog-step","mint"]` row and
/// aborts before anything spawns (§4.2). The minted name rides `--name` (§3.3 as
/// ruled by bl-50f3): litany commits it beside `goal.md`, the one durable home
/// the display ladder reads back — and on a lost-race re-mint the re-derived
/// name is what passes, since the mint here *is* the truth. What is sent is
/// `goal` **verbatim** — the operator's edited payload, unmutated (operator
/// ruling bl-6920): identity is `--name`'s alone, and litany states the stored
/// name fact in its assembled context (litany bl-d55f, released 0.0.4 —
/// `compose_system`'s `Your name is <name>.` in the system slot); yog prepends
/// nothing. The *logged* argv rides
/// the full goal through [`opslog::clip_goal`], which trims it so the serialized
/// line stays ≤ CAP/PIPE_BUF (§4.2 atomicity) — the *spawned* one is full. Only
/// the spawn is logged, and which line it writes is the outcome (bl-afa9): a
/// handoff logs [`DETACHED_EXIT`] and nothing else, a fork that never landed logs
/// the §4.2 synthetic-failure line with the error in `stderr`. A child that dies
/// *after* launching speaks through the sink, folded into the `-2` row at read
/// time (§13.3 amended).
///
/// Returns the **minted conversation name** — the one thing the fire learns that
/// no caller could have known beforehand (the preview only predicted it). It is
/// the handle the §3.4 focus claim is held by: the started root has no agent id
/// until the detached driver writes its branch, so the name is what identifies
/// the conversation until then ([`AppModel::await_conversation`](crate::AppModel::await_conversation)).