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
//! The **orphaned tail** (bl-ace6, widened by bl-abba): the transcript ends
//! on something that is owed a driver, and no driver is there — plus, when
//! the last one left words behind, why.
//!
//! The §7.3 wound beside this covers a driver that died *inside a step*.
//! The gap it left is the driver that died **before creating one**, or
//! **between two of them**: the ordinary 2nd..Nth message of a conversation
//! is driven by a child *litany* launched (ARCH §2.11 — never a yog spawn,
//! so no §8.1 sink), and when that driver errors out — an unpaired-tail
//! decline, a lease fault, a crashed launch, an executor killed mid-tool-
//! window — the steps tree is unchanged, `ops.jsonl` says `exit 0`, and the
//! transcript simply stops. STORIES INV-2 (no swallowed errors) is the
//! invariant that state violates.
//!
//! The **state** is two observations, both already derived, nothing
//! stored (§5.1 #13):
//!
//! - **The newest transcript entry is owed an answer** — one of the two
//! [`Tail`] shapes below. Which one it is is read through the transcript
//! module's own classifier (`transcript::classify`), never a second
//! reading of a filename here, and only the tail file is opened: the
//! predicate must not cost a resting conversation the whole record.
//! - **Nobody is driving** — the agent's lock is free (§3.5). Both shapes
//! are laid down *under* a driver's lock and the driver holds that lock
//! across them, so on a healthy branch this pair exists only for the
//! relaunch gap — which is why the banner rides the same grace window the
//! wound does (bl-90bf), and a send whose driver has not been seen yet
//! never alarms.
//!
//! **Two shapes, one state, and deliberately not two of everything**
//! (bl-abba). A crashed tool window is the same fact about the same agent,
//! read off the same disk, said in the same seat, through the same grace
//! gate — so it is a second [`Tail`] on this state rather than a third
//! banner beside it. The wire pays for that the way the wound already did
//! (bl-fb87): a `(bool, Option<reason>)` pair stops being a bijection at
//! the third arm, so the class is a token and the reason resolves the rest.
//!
//! The **reason** is the tail of `steps/<agent>/driver.log` — where
//! litany binds every launched driver's stderr (lernie 0.0.9, its
//! bl-55f9; the file yog pinned that release for and then never read).
//! It is append-only across launches, so its content is never the
//! trigger — a stale line from a healed crash must not alarm — only the
//! diagnosis, read exactly when the state holds (a healthy conversation
//! pays no syscall for it).
//!
//! Like the wound, this is not a new stored fact and not a new agent
//! state: the badge vocabulary is untouched (the ■ stopped ruling and
//! attention's rest-not-wound rule both stand — bl-d816 tracks whether
//! they ever should not), and everything here is re-derived per reading.
use Path;
use driven;
use crateAgentState;
use crate;
/// What the transcript's tail is owed. Both shapes are "a driver was going
/// to answer this and is not there"; they differ only in what the last
/// entry is, which is the whole of what the operator needs told apart.
/// The sentence yog renders for the mail shape — the §7.3 rendered fact.
pub const ORPHANED_MAIL: &str = "a delivered message has no driver";
/// The same for the tool-window shape. It carries the remedy because the
/// remedy is one gesture and the operator's whole problem is that the
/// conversation reads as an idle one nobody needs to touch: an executor
/// that died mid-window leaves an agent that looks finished, and on an
/// unattended box that window has no upper bound. A deposit settles it —
/// the next drive boundary writes an in-band `is_error` `tool_result` per
/// unanswered id before delivery (litany ARCH §6, its bl-4187, consumed in
/// bl-4c1f) and the branch carries on.
pub const ORPHANED_WINDOW: &str =
"a tool call has no driver — the turn died mid-tool-window; a message revives it";
/// What the banner adds when `driver.log` has nothing to quote — the
/// honest end of the trail, said outright (the wound's own discipline).
const MUTE: &str = "and driver.log has no words — nothing on disk says why";
/// How the banner introduces the captured bytes. It names the **file**:
/// an operator who wants more than the tail must be told where the
/// whole of it lives.
const SPOKE: &str = "the last driver's words (driver.log):";
/// The §11 banner's leading mark — never the only carrier (§11 glyph
/// doctrine); the sentence beside it states the fact in words.
const ALARM: &str = "⚠";
/// The orphaned-tail state **and its reason** — the [`super::Wound`]
/// shape, for the wound's own reason: an orphan with nothing to say is
/// a real, distinct answer, and `Some("")` would be one fact with two
/// encodings.
/// Derive the state for one agent. The `driver.log` read is gated on
/// the predicate, and both bounds on how much of it is read are the
/// wound's own borrows: [`crate::opslog::detached::captured`] for how
/// much of a capture file yog ever reads,
/// [`crate::opslog::rows::stderr_tail`] for how much a surface says.
pub
/// Which [`Tail`] the newest `messages/` entry is, if either. Filename order
/// is entry order (ARCH §2.3: the zero-padded counter), so the newest name is
/// a `max` over the listing; only that one file is opened, and the transcript
/// module's own classifier says what it is. An absent or empty directory has
/// no tail and is never an orphan.
/// Does this entry call a tool at all? A model turn that ended on text is
/// a conversation resting, which is the ordinary shape and no orphan.