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
//! The **populating-read roster** (§8.5): every query both frontends ask, in
//! one enum. Its own file at §12's line budget (bl-765d), on the seam §8.5
//! already draws and the help table is already cut along — actions mutate,
//! queries populate. Nothing else moved with it: [`answer`](super::answer) is
//! still the one chokepoint, and [`Gesture`](super::Gesture) still names both
//! halves.
use super::config;
/// One populating read (§8.5): a §2 I1 derivation over the published snapshot,
/// answered by [`answer::answer`] — the same functions the frame's view-models
/// delegate to, so both frontends render one derivation.
///
/// **A read addresses by NAME, never by path** (REMOTE §8, bl-f5f6), exactly as
/// the mutating half does: a `workspace` is its §3.1 directory leaf, resolved
/// **once** at [`answer`](super::answer::answer) ahead of the table, over the
/// one table that says which reads name one ([`Query::workspace`],
/// `src/boundary/address.rs`).
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Query {
/// **The §9 config family** (bl-719a): the destination's bytes, the §9.3
/// lineage browse, the §9.4 model roster, the §16.3 marks read and the §8.3
/// provider table — one variant over [`config::Read`], the fold `Action`
/// has taken five times and on the seam every layer beneath already draws
/// (`boundary::config` answers all five, `codec::config` spells them,
/// `line::config` reads them). That type's own doc carries the five, and
/// each is still its own verb, `op` and help page.
Config(config::Read),
/// The enumerated workspaces (§3.1) with their §6 attention rollups.
Workspaces,
/// The §11 conversation list of one workspace: one row per root agent,
/// subtree-aggregated, attention > running > recency.
Conversations { workspace: String },
/// The §3.5 join rows — every ball⇄workspace binding fact.
Balls,
/// **What one workspace holds** (§3.2/§3.5, §11 balls section; REMOTE §9.7,
/// bl-b4b5): every ball bound to it, with its badge, the project its `bl`
/// verbs run in, the claimant they stamp `--as`, and its priced figure.
///
/// Distinct from [`Balls`](Query::Balls) by **address**, not by source, the
/// way [`Board`](Query::Board) is distinct by altitude: that answers the
/// world's whole binding table, this answers the one workspace a seat is
/// looking at — which is what every §11 balls surface actually paints, and
/// what a seat holding a §3.1 name could not select out of the table
/// without the engine-side join bl-7407 refused.
///
/// **The figure rides the row rather than earning a query.** A ball's spend
/// is a filter over the same `Snapshot::bills` walk the listing is made
/// from (§3.5, bl-9dd4), so asking for it separately would be a second read
/// of one derivation — the two-readings-of-one-tail defect bl-296f closed
/// at the activity chip.
WorkspaceBalls { workspace: String },
/// The V4 board (VISION §5 V4): the same balls, projected into the
/// operator's four columns with their gates, drones, spend and epic
/// rollups. Distinct from [`Balls`](Query::Balls) by *altitude*, not by
/// source — that answers the binding facts, this answers the board built on
/// them — and both are one derivation over the published snapshot.
Board,
/// **The decision queue** (VISION §5 V5.2): every conversation the §6
/// predicate says is waiting on the operator, in the roster order the ↓ key
/// walks, each carrying why it fires and what it last said. The attention
/// strip's own derivation — at the window a count and a jump control, here
/// a list an agent reads, answers ([`Action::MarkSeen`]) and hands on.
Attention,
/// The `ops.jsonl` tail (§4.2), newest last, at most `max` rows.
Ops { max: usize },
/// **What this workspace's agents actually changed** (§5.1 #32, VISION
/// §4.10): the pure git read `target..source` of every attempt the
/// workspace holds, and — when `file` names one — that file's bounded
/// patch. The second query whose subject is the world's bytes rather than
/// the snapshot's derivations: the snapshot says which balls this
/// workspace claims, and the project repos are read for the rest.
WorkDiff {
workspace: String,
file: Option<crate::workdiff::WorkFile>,
},
/// **Every delivery attempt this workspace holds, as science reads it**
/// (§3.9, VISION §4.10 item 7; bl-40ab): per attempt, the frozen inputs
/// (goal, pinned documents, governing config commit — model and skills ride
/// it), the base/source/target OIDs and the delivered commit when one
/// exists, the terminal response, usage and wall time, the project diff, the
/// verdicts, and the accepted/rejected/reworked outcome.
///
/// **It composes [`WorkDiff`](Query::WorkDiff), it does not replace it.**
/// The diff row is one derivation with one home, and a science row carries
/// that row rather than restating its fields — so the two answers agree by
/// construction and the §11 fan-group seat can read the churn from either.
/// What this adds is the agent side of the join: the conversation each
/// attempt was bound to, and everything only that conversation can be
/// asked. The third world-bytes read of the pair, and the reason it is a
/// query rather than a table is VISION §4.5's join discipline — nothing is
/// stored and nothing is cached, so a row is a statement about the world as
/// it is now.
Science { workspace: String },
/// One text across the whole world (§8.5, [`search`](crate::search)): live
/// and closed ball title+body, workspace and conversation identity+goal,
/// and transcript text. The **asynchronous** query — its subject is the
/// world's bytes rather than the snapshot's derivations, so a window asks
/// it off-frame and renders whatever answer has landed. It carries no
/// bound: how much of the world one answer hands back is yog's decision
/// ([`search::MAX`](crate::search::MAX)), not a knob two seats could spell
/// differently.
Search { text: String },
/// What a command does (§8.5): the whole roster, or one verb's page. The
/// **higher-order** query — its subject is the interface, not the world —
/// and therefore the one query with no snapshot to read, which is why every
/// seat may answer it in place instead of depositing it ([`help`]).
Help { verb: Option<String> },
/// **The conversation itself** (§11 Altitude-2 Transcript, bl-6233): every
/// committed `messages/` entry of one agent, with the live streaming tail
/// folded on when a call is in flight. The first of the §11 inspector
/// family — the five reads that were reachable from no seat but the window,
/// which is what made a chat unreadable headless (REMOTE §9 step 1).
///
/// **The in-flight tail is folded, not dropped.** The tail is the
/// snapshot's own [`Stream`](crate::git_tree::Stream), already carried by
/// the [`Deps`](super::dispatch::Deps) this query is answered from, so
/// folding it costs no read and keeps one derivation behind both seats: a
/// headless answer that stopped at the committed half would say something
/// different from the window about the same moment, which is the exact
/// parity §8.5 exists to hold.
Transcript { workspace: String, agent: String },
/// **The live tail, followed** (REMOTE §3, §10; DESIGN §7.2, bl-73e7) — the
/// second follow-class read, and the one the operator ruling of 2026-08-22
/// minted: one conversation's streaming answer, delivered as it is written
/// rather than as it is asked for.
///
/// Its subject is the same fold [`Transcript`](Query::Transcript) carries
/// on its tail — `inspector::live_tail` — so the two cannot describe one
/// moment differently (bl-6233). What differs is the **cadence**: an intake
/// that can hold a connection answers a frame per growth of the open
/// `response.json` and terminates the stream when the step commits, and an
/// intake that cannot answers the tail as of now, which is the general path
/// with one frame. The pull read stays the fallback, so a seat that loses
/// the lane keeps the tail at ask cadence rather than losing it.
Follow { workspace: String, agent: String },
/// **One sign-in's output, followed** (REMOTE §8.3, bl-c285) — the third
/// follow-class read: what `bz --login` has printed for this workspace's
/// `provider` row, buffered from the start and then live to the settled
/// exit. [`login`](super::login) carries the frame rule and the reason a
/// pair with no run answers emptiness rather than refusing.
LoginTail { workspace: String, provider: String },
/// **Every step one conversation has taken** (§11 Altitude-2 Steps): the
/// cheap per-step summary list — framing, attempts, tokens, timestamps, the
/// §8.3 login affordance and the §7.3 wound. The agent's liveness is read
/// off the snapshot rather than asked for, because it is a fact the world
/// already published and a parameter would let a seat contradict it.
Steps { workspace: String, agent: String },
/// **One step's records, drilled in** (§11 Altitude 2): `meta`, `request`,
/// `staging`, every `response.json` event and every tool call's
/// input/output, each as a jsonview doc — plus each **capture log** that has
/// bytes (bl-83d6): the step's own `stderr.log` and the agent's
/// `driver.log`, as bounded previews rather than docs, because nothing
/// parsed them. The second tier, asked by
/// sequence name exactly as the list answers it — a step the tree does not
/// hold answers absent records rather than refusing, the same forgiving
/// read the window makes (§10: never a false definite).
Step {
workspace: String,
agent: String,
seq: String,
},
/// **The agent worktree, read-only** (§11 Altitude-2 Files): the bounded
/// sorted listing, and — when `path` names one of its listed files — that
/// file's bounded preview. The [`WorkDiff`](Query::WorkDiff) shape, for the
/// same reason: a listing and one entry's bytes are one question asked at
/// two depths. `path` is **resolved against the listing yog just built**,
/// never joined blind, so this read can open nothing the same answer did
/// not already name.
///
/// **`at` names the tree, and a tree is a selection, not a fold** (REMOTE
/// §9.7, bl-44e9). VISION V1.2's pin folds four tabs to one commit, and
/// three of them read something the seat already holds — the transcript is a
/// prefix of the chat it was answered, the budget is a rollup on the notch,
/// the spine is the answer itself. This one is the tab whose *subject* is a
/// different tree, so it is the one the commit has to reach, and it reaches
/// it the way [`Step`](Query::Step)'s `seq` and
/// [`WorkDiff`](Query::WorkDiff)'s `file` do: as a parameter naming **which
/// thing you are asking about**. `None` is the live worktree. Nothing about
/// the operator's *selection* crosses — a seat that has pinned nothing asks
/// nothing different, which is what keeps DESIGN §8.5's "views gain no
/// boundary representation" true of this.
Files {
workspace: String,
agent: String,
path: Option<String>,
at: Option<String>,
},
/// **The config commit this conversation resolves its policy from** (§9.3,
/// §5.1 #17; VISION V1.2's *config-frozen-at*; REMOTE §9.7, bl-13f9): the
/// nearest `config/*` ancestor of a commit settles which lineage governs,
/// and the answer is that lineage's current head — with the lineage named,
/// and every path the head's tree holds. Where lineages have diverged over
/// the fork commit there is no head to follow, so the answer is that fork
/// commit and the count that held it (bl-e654, upstream bl-403b).
///
/// **`at` names the commit, and a commit is a selection** — the
/// [`Files`](Query::Files) shape, and for the same reason: this is the
/// *second* of VISION V1.2's four pinnable tabs whose subject is a tree the
/// pin names rather than something the seat already holds. `None` is the
/// agent's own branch tip, resolved off the published snapshot, so a seat
/// that has pinned nothing asks nothing different and no seat has to know a
/// tip before it may ask. Nothing about the operator's *selection* crosses.
/// Since follow-the-tip it selects a **rev, not a moment**: two commits of
/// one lineage resolve the same head, and policy as of an earlier step is
/// recorded by that step rather than derivable from ancestry.
///
/// It **refuses** rather than answering absent, unlike its siblings: the
/// derivation is a walk of the workspace's own git and it fails the way
/// [`Lineages`](Query::Lineages) fails — a defective or unfetched
/// workspace, or a commit that forks off no config lineage at all. Absence
/// would read as *this conversation has no policy*, which is never true.
Governing {
workspace: String,
agent: String,
at: Option<String>,
},
/// **The step spine** (VISION V1, §11): one notch per operable commit and
/// the child cards hanging off them. The notches are answered; the
/// operator's *pin* is not — a pin is a viewport fold, and §8.5 files folds
/// under views, exactly as [`Conversations`](Query::Conversations) answers
/// the all-collapsed list.
Rail { workspace: String, agent: String },
/// **The undelivered mail** (§11 Inbox, ARCH §2.11): one agent's deposit
/// files, each parsed beside its verbatim bytes.
Inbox { workspace: String, agent: String },
/// **One conversation as a seat sees it** (REMOTE §9.4, bl-1eb0): who is
/// selected, what the conversation is called, its own §3.5 liveness, the §6
/// marks it wears, what is in flight in it and the two §8.2 verb gates.
///
/// The seventh member of the conversation-addressed family, and the one
/// that made the other six paintable by a face holding no world: the §11
/// centre pane derived all of this on the frame thread out of the engine's
/// agent set, which is not a thing a wire can carry. Every field is a fold
/// the boundary already owned; only the spelling is new.
Agent { workspace: String, agent: String },
/// **This workspace's registered clients** (REMOTE §5, bl-4e08): who
/// participates in it, which of them holds a live connection right now, and
/// what each advertises. Three reads joined at the moment they are asked —
/// the §4.1 registration listing, the wire server's presence RAM, and each
/// client's own advertised set — so nothing is stored that could go stale
/// and a flap needs no invalidation.
///
/// **It is a point-in-time observation, deliberately** (REMOTE §5): the
/// seat sees the flap and the model's cached prefix never does, which is
/// why presence is answered here rather than declared anywhere durable.
Clients { workspace: String },
/// **Is this box wired up?** (bl-28f4) — every check a first conversation
/// depends on, asked at once, each row carrying the fact it read and, when
/// it fails, the act that fixes it ([`doctor`](crate::doctor)).
///
/// **The workspace is optional, and that is the point.** The box a doctor
/// is for is the box that cannot start a conversation yet, and it may hold
/// no workspace at all — so the engine's own checks answer with none named,
/// and naming one adds the two that are a workspace's (its wall, its
/// roster). Every other read that names a workspace requires it, because
/// every other read is *about* one.
Doctor { workspace: Option<String> },
/// **A tool host's next work** (REMOTE §3, §5; bl-024b) — *the*
/// follow-class read, and the first with a consumer. The answer stays
/// pending until this client has an invocation or the engine's hold
/// expires, which is why it is a read and not a poll: a machine waiting on
/// a machine is the ask rate REMOTE §10 set as the criterion for minting
/// one.
///
/// **The identity is the intake's**, exactly as an advertisement's is: a
/// connection drains its own queue, and a `client` field here would let one
/// connection take another's work. An intake carrying no client identity —
/// the deposit inbox, `yog gesture`, the window — refuses in band.
///
/// It names no workspace: a tool set is a fact about a machine (REMOTE
/// §5.1) and so is the queue of calls to it.
Invocations,
/// **What one routed invocation captured** (REMOTE §5): the asking side's
/// poll, answered `null` while the far machine still runs it. Bounded by
/// the *asker's* patience rather than the engine's — a vanished client is
/// this read answering nothing until its caller gives up and says so, which
/// is the visible in-band refusal §5 asks for and never a hang.
Capture { invocation: String },
/// **The price table, the ceiling and the world's ledger** (DESIGN §3.5,
/// §4.1; bl-53d1): every `(provider, model)` rate, the bound, and the
/// world's priced spend against it. World facts, so it addresses no
/// workspace and stands beside [`Workspaces`](Query::Workspaces) in the
/// window-level set. Slash form `/prices`.
Prices,
}