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
//! 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 the two events 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.
use is_transient_runtime_error;
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 two events 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.