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
301
302
303
304
305
306
307
//! Compacting a conversation because someone asked.
//!
//! mentra already compacts on a threshold, and the model can already ask for
//! it through the `compact` intrinsic. The person whose conversation it is
//! could not — which is the one case where the *instruction* matters, because
//! only they know that the migration plan is worth keeping and the log
//! spelunking is not.
//!
//! # Why the sink is drained rather than written to
//!
//! [`PreparedRun::compact`] answers twice: the return value goes to the
//! caller, and the events go to whoever is reading the stream. Both matter —
//! a sink that watched the history shrink with nothing to explain it would be
//! describing a conversation nobody could account for.
//!
//! The events are mentra's own, not basis's re-derivation of them.
//! `Session::compact` installs the same agent-event tap a turn installs, for
//! the duration of the pass, so `CompactionStarted` and `CompactionCompleted`
//! reach the session's stream exactly as they do when a threshold fires. What
//! is missing outside a turn is only the *other* half: the forwarder that
//! carries that stream into a run's sink runs per turn, and this is not a
//! turn. So this subscribes first and drains after, which is what makes an
//! on-demand pass indistinguishable from an automatic one on the wire.
//!
//! Draining after rather than forwarding concurrently is enough because the
//! pass emits at its end — mentra applies the compaction and *then* announces
//! it — and because its handful of events (the announcement pair, then one
//! usage report per provider sample) cannot outrun a broadcast channel that
//! holds 512. A turn needs the concurrent forwarder for a different reason:
//! it has to answer permission requests while the turn is blocked on them,
//! and a summarizing pass asks for nothing.
//!
//! # Why a failed pass is announced too
//!
//! The same argument, read the other way. A pass that fails is a model call
//! that happened and cost something, and the conversation a client is
//! watching does not shrink — so a stream that says nothing leaves that
//! client with a `/compact` that produced no observable effect and no reason.
//! mentra does not fill that in: `Session::compact` hands the error back and,
//! unlike `finish_turn`, puts no `SessionEvent::Error` on the stream for it.
//!
//! So basis emits one [`Event::Error`], from the error it is already holding,
//! and only when the drain forwarded none. This is not a workaround for a
//! runtime hole (ADR-0005) — there is nothing hidden upstream to recover here.
//! It is basis's own verb accounting for its own outcome, exactly as the
//! success path does, and the guard means an upstream event would take
//! precedence rather than double up.
//!
//! # And why a bounded pass is announced the same way
//!
//! [`PreparedRun::compact_with_options`] can end a pass on a cancellation
//! token or a deadline, and mentra reports both as what they are —
//! `RuntimeError::Cancelled`, `RuntimeError::DeadlineExceeded` — rather than
//! as a summarizer that refused. The caller therefore has the bound in the
//! type it matches on, which is the half that matters for control flow.
//!
//! The stream gets the same single [`Event::Error`] a failure gets, and that
//! is deliberate rather than an omission. The alternative is silence, and
//! silence is what the failure path already rejected: a client that asked for
//! a conversation to shrink and watched nothing happen is owed a line either
//! way. What a client needs is to tell the two apart, and it can — the
//! message is mentra's own (`operation cancelled`, `deadline exceeded`, and
//! not the summarizer's complaint), and `recoverable` is false for both
//! because mentra classifies a bound as terminal, so nothing here invites a
//! retry into a stop somebody asked for. basis has no `Bound` to report on
//! this verb the way [`RunReport`](crate::RunReport) does for a turn, because
//! there is no report: a pass returns a value, not a run.
use ;
use TryRecvError;
use ;
/// What a summarizing pass did.
///
/// basis's own shape rather than mentra's `CompactionDetails`, for the same
/// reason [`Event`] is: what basis publishes should not move because a runtime
/// internal did. The field names are [`Event::CompactionCompleted`]'s, because
/// a caller reading the return value and a client reading the stream are
/// looking at one pass and should not have to learn two vocabularies for it.
/// Empties whatever the pass put on the session's stream into the sink, and
/// reports whether any of it already announced a failure.
///
/// The answer is what keeps [`PreparedRun::compact`]'s own error event from
/// becoming a duplicate. mentra says nothing on the stream when a summarizing
/// pass fails — `Session::compact` returns the error and, unlike
/// `finish_turn`, emits no `SessionEvent::Error` for it — so today this is
/// always `false` on the failing path and basis speaks. If mentra grows that
/// event, its line is the one the client gets and basis stays quiet, which is
/// the right precedence: the runtime's own account of its own failure.
///
/// A lag is impossible in practice — a compaction emits its announcement pair
/// plus one usage report per provider sample into a channel that holds 512 —
/// so a receiver that reports one has been overtaken by something this
/// function cannot see, and stopping is the honest response: the alternative
/// is a stream that quietly disagrees with what happened.