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
//! The model call: exec `bz` once per attempt and own the retry loop
//! (ARCH §4.4, §2.10, §3.5). The typed request every attempt sends is
//! composed apart, in [`super::canonical`].
//!
//! brazen never retries — each `bz` process performs exactly one HTTP
//! round-trip (§4.4). The harness owns the retry loop: on an in-band
//! `Error` event whose kind is retryable ([`CanonicalError::retryable`],
//! the linked crate's single home for the fact — never re-derived), it
//! re-invokes `bz` with the *identical* request (context assembly is a
//! pure function of the step's recorded commit tree, §2.3, so no drift)
//! up to the `workflow.yaml` attempt cap, sleeping the backoff between
//! attempts.
//!
//! **Fd held open for the whole model call (§3.5).** The `response.json`
//! fd is opened once at the first attempt and held across *every*
//! attempt and *every* backoff sleep — closed only at step resolution.
//! fd-open is the single `in_flight` signal, so a mid-retry `Error`
//! segment never reads as `failed` while the loop is still pending.
//! Each attempt's stdout is appended verbatim as one segment; the last
//! segment is authoritative (§4.4).
//!
//! **The stop flag bounds the loop, and classifies its outcome (§2.9).**
//! A pending stop ends the loop instead of launching another `bz`: a
//! process spawned after the group SIGTERM is outside the cascade's
//! reach, so retrying through a stop would spend a whole further model
//! call — the window that dominates a stop's observed latency. And the
//! error this module hands back under a pending stop means nothing on
//! its own: a kill lands wherever the adapter was, so the stop leaves
//! [`Error::AdapterHalfStream`] on a clean line boundary,
//! [`Error::AdapterJson`] on a torn one, or an `AdapterError` from an
//! attempt that had already failed — indistinguishable from the genuine
//! article by shape. The flag is the only reliable witness, so the
//! callers' §2.9 step-3 check points discard *whatever* came back when
//! it is set, and propagate it as a fault when it is not.
//!
//! **A response cut at the output cap is a truncation, not an answer**
//! (bl-ecf9, bl-155f, bl-a928). When the terminal `Finish` reason is
//! `Length` the provider stopped because the request's own `max_tokens`
//! ran out, so the last block is cut wherever the counter reached — a
//! `tool_use` whose `input` never finished arrives as `{}` and, before
//! this, was committed and executed. Measured: every one of nine
//! reviewer `apply_patch` calls in a learning-loop run arrived as
//! `input: {}` at exactly 4096 output tokens, each answered with
//! *"invalid input JSON: missing field `input`"*, and the loop staged
//! nothing; from the seat the conversation read "came to rest — your
//! turn". So the segment is its own outcome and the call fails with
//! [`Error::OutputTruncated`]: the staging sink is never sealed, so no
//! entry is committed and no tool runs, and the branch settles as
//! *failed* rather than as a conversation that finished.
//!
//! **It is not retried**, unlike a retryable in-band `Error`. The
//! request is a pure function of the branch's tree (§2.3), so a second
//! attempt re-issues the identical prompt against the identical ceiling
//! and is cut at the same byte — the retry loop would pay a whole
//! further model call to reach the same place. That was measured too:
//! three consecutive steps re-emitting the same oversized `apply_patch`,
//! each paying a ~100k-token context, leaving a 0-byte file. The remedy
//! is config (`max_output_tokens:`, §4.3) or a smaller ask, and the
//! error names both.
//!
//! The adapter's stderr rides beside the call — see [`stderr`].
use ;
use stop_signal;
use crateRetryConfig;
use crateError;
use crateAdapterRunner;
use run_attempt;
use ;
use OsString;
use File;
use Path;
use AtomicBool;
use Duration;
/// How one attempt's segment settled — the framing the retry loop acts
/// on (§4.4, §2.10). Content lives only in the staging sink (§2.3), so
/// no assembled blocks ride here.
/// Injected sleep so the retry backoff is real in production and a
/// no-op in tests (the retry *logic* does not depend on wall time).
/// Production [`Sleeper`] — blocks the calling thread.
;
/// Everything the retry loop needs beyond the request itself.
pub
/// Drive one model call to resolution: `bz --json --provider <row>` per
/// attempt, request on stdin, each attempt's stdout appended verbatim to
/// `response_path` as one segment. On success the staging sink is sealed
/// (the model-output transcript entry, §2.3) and `Ok(())` returns — the
/// call's *content and usage* have their one home in that entry, never a
/// return value. A non-retryable / budget-exhausted `Error`, a half-stream
/// kill, or a malformed event surfaces as a harness [`Error`] — which,
/// with a stop pending, the caller reads as the stop (§2.9 step 3).
pub
/// Under an `adapter:` override the completed segment must carry a
/// `MessageStart.v` equal to `brazen::EVENT_SCHEMA_VERSION` (§4.4).