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
//! **Holding the line on one conversation** — the seat's own word for
//! watching work happen, which is more than one gesture.
//!
//! # What was wrong, and both halves were the same mistake
//!
//! `follow` was one `ask`: one held connection, its frames collected, the
//! stream printed at the end, and the exit code read off the last frame. That
//! gave two defects with one cause.
//!
//! - **On a quiescent conversation it blocked 31 seconds, printed one newline
//! and exited 1** (bl-3dca). Nothing is wrong with a conversation at rest —
//! it is the ordinary state of one an operator has just looked at — but exit
//! 1 with no output is byte for byte what a failed dial, a refused
//! certificate and a dead engine look like, and those are what a first-time
//! user suspects.
//! - **On a live one it returned mid-turn, every time** (bl-f076). The engine
//! ends the stream at the STEP boundary (yog's REMOTE §5.1), not at the
//! turn's, so three consecutive reads of one conversation ended after 3, 8
//! and 6 seconds while it worked on. Watching an agent was
//! `while true; do lernie follow …; done`, which the operator had to invent
//! and which loses whatever landed between two reads.
//!
//! # The rule this file implements
//!
//! **Hold the line until the conversation rests, or until the user quits.**
//! The engine's own step boundary is not the end of anything an operator
//! cares about, so a read that ends there is re-asked; what ends the WORD is
//! the conversation coming to rest, and that is a fact the engine already
//! answers — `agent`'s `state`. So the loop is: ask what it is doing, and if
//! it is not working, say so and exit 0; otherwise hold a read and print what
//! lands, then ask again.
//!
//! **The state read comes first, which is what fixes the quiescent case at no
//! cost.** A conversation already at rest never opens a held connection at
//! all, so the half-minute of silence is not shortened — it never happens.
//!
//! **An unknown state ends the follow rather than looping on it.** The reply
//! vocabulary paints an unrecognised token as itself (DESIGN §4.9 rung 3), and
//! the safe reading here is *this seat does not know that this is working* —
//! ending, and printing the word, beats holding a connection open forever on a
//! state nobody here understands.
//!
//! # `--json` narrates nothing (bl-87ab)
//!
//! `--help` promises *"the frames exactly as they crossed, one envelope per
//! line, which is what a script wants"*, and this word broke it on the one
//! line that mattered: every frame of a watch was an envelope and the line
//! saying the watch was OVER was prose, so a reader calling `json.loads` on
//! each line died on the terminator. The rule is now one rule for both
//! sentences this file writes — under `--json` this seat says nothing of its
//! own, and what ends the watch is the `agent` frame that ENDED it, printed as
//! it crossed. It carries the state in a field, which is what a script wanted
//! from the sentence. The elapsed is this end's own fact and a script has its
//! own clock; the rendered form keeps it.
//!
//! # Why the frames are handed to a sink
//!
//! A held read that printed only at the end would not be a follow. So this is
//! the one place in the crate where the product is written as it arrives, and
//! the writing stays the entry point's: [`follow`] takes a sink, `src/main.rs`
//! hands it a printer, and the suite hands it a `Vec`. The decision is still
//! entirely in the library, where a test reads it back.
use Path;
use ;
use Value;
use crateReach;
use crateVerdict;
use crate;
use crateStream;
/// **When the watch stops, and what it says then** — the three readings of the
/// standing row, and the two sentences an ending can be. Split from this file
/// at the 300-line cap on the seam the word already has (bl-3a1f): above is
/// the LOOP — ask, hold, print, ask again — and there is the ENDING, which is
/// a different question and the one that keeps growing.
use ;
/// **How long a read that brought nothing waits before asking again.**
///
/// The engine paces this loop on its own — a held read stays open while the
/// tail is quiet — so this is insurance against an engine that closes an empty
/// read at once, where the alternative is a busy loop on somebody else's
/// socket. It is not a poll interval: a read that brought a frame asks again
/// immediately.
const SETTLE: Duration = from_millis;
/// **Watch one conversation until it rests.** `say` takes each frame's
/// rendering as it lands; the verdict is the sentence that ends the watch.
/// One held read, printed as it arrives. Answers how many frames landed, which
/// is the one fact the loop above needs from it.
///
/// **The fold's whole lifetime is this call**, which is the whole of how REMOTE
/// §5.5's *"onto an empty fold"* is implemented here: one read is one `held`,
/// so a read boundary needs no flag and no field — it is a local's scope. What
/// is printed is still the frame's own append, because a terminal is already a
/// fold and re-printing the accumulation would be the same answer at quadratic
/// cost; the fold exists for the half that CANNOT be printed twice, which is
/// the tool window's closing entry ([`crate::render::tail`]).