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
//! **What the seat last heard that was not content** — the sentence the shell
//! paints where an answer's content would have been.
//!
//! Split from [`super`] at the design-time budget on a seam of its own: the
//! model is what the window holds and how it changes, and this is one closed
//! vocabulary of what the seat heard that it cannot paint as content, with the
//! one line that says whose sentence it is. It changes when a new *kind* of
//! not-content appears, which is not when the model changes.
//!
//! **Five of the six are things that went wrong and the sixth is not**
//! (bl-bce2). A receipt that carries a FACT — which call was released, whether
//! a floor stands — is not content either: there is no row it belongs under
//! and no pane it fills, and the window has exactly one place for a one-line
//! statement about an act just performed. So [`Notice::Said`] is here, and
//! being here is what makes it dismissible: an act is an event and not a
//! state, so it does not re-post on a beat.
/// What the seat last heard that it could not turn into content.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Notice {
/// The engine refused, in its own words.
Refused(String),
/// This seat could not read what arrived — a malformed frame, or a kind
/// this build does not paint. A statement about **this seat**, which is why
/// it reads differently from a refusal.
Unreadable(String),
/// This seat could not **reach** the far end: a channel that will not open,
/// an engine that is not there, a preface that did not agree.
///
/// Three arms and not two, because the remedies are three different acts. A
/// refusal is answered by typing something else; an unreadable frame by
/// upgrading the seat; an unreachable channel by looking at this box's own
/// files or at whether the engine is up. A seat that collapsed them would
/// send an operator to check a certificate over a workspace they mistyped.
Unreachable(String),
/// **An act that crossed and was never answered** — yog's `docs/REMOTE.md`
/// §3's IN DOUBT. The engine had the gesture and this end cannot say what it
/// did with it, so the effect may have landed.
///
/// The fifth arm, and the first whose remedy is to do NOTHING. The four
/// above are answered by an act — type something else, upgrade the seat,
/// look at this box's files, do it again — and this one is answered by
/// looking, because *"an act is not idempotent"* and a resend of one that
/// already ran is a second effect nobody asked for. Which is why it must
/// not wear any of the other four sentences: every one of them invites the
/// act this one forbids.
InDoubt { op: String, why: String },
/// **An act that never left this box.** The counterpart, and it exists
/// because the honest answers are opposite: nothing happened, so doing it
/// again is safe and is the remedy.
///
/// It is in the bar rather than on the channel's section — where the same
/// transport failure on a READ goes — because an act is an exchange
/// (`super::absorb`). A channel's section is also the slot the roster read
/// owns and overwrites on every beat, so a click that went nowhere would
/// have left a red sentence for less than a second and then nothing at all.
Unsent { op: String, why: String },
/// **An act's receipt, in the engine's own terms** — the sixth arm, and
/// the first that is not a failure at all.
///
/// It exists because two acts answer with a fact rather than with content:
/// `answer` says which call it landed on and whether the conversation is
/// running again, and `revoke`/`restore` say whether a floor stands over
/// the conversation now — re-derived by the engine, so it is the one
/// statement about a floor this seat can make (§4.34).
Said(String),
}
impl Notice {
/// **What an act with no reply is**, off the transport's own reading of
/// whether the request crossed ([`crate::channel::Reach`]).
pub fn act(op: &str, reach: &crate::channel::Reach) -> Self {
let (op, why) = (op.to_owned(), reach.said());
if reach.crossed() {
return Self::InDoubt { op, why };
}
Self::Unsent { op, why }
}
/// **What an answer landed on, and what it did to the conversation.** The
/// verdict rides verbatim (`crate::reply`'s rung 3), and `advanced` is the
/// half worth saying: `pass` and `refuse` both drive the branch on, where
/// `hold` is the operator saying *stay parked* and launches nothing.
pub fn answered(tool: &str, tool_use: &str, verdict: &str, advanced: bool) -> Self {
let said = format!("answered {tool} ({tool_use}): {verdict}");
Self::Said(if advanced {
format!("{said} — the conversation is running again")
} else {
format!("{said} — it stays parked")
})
}
/// **Whether a floor stands over the conversation now**, which is the
/// engine's re-derivation and never an echo of the direction that was
/// asked: restoring one whose ancestor is still revoked leaves it floored,
/// and this is the sentence that says so instead of claiming a restore
/// that did not happen.
pub fn floored(standing: bool) -> Self {
Self::Said(
if standing {
"a floor stands over this conversation: every tool call but a read waits for you"
} else {
"the floor is lifted — its tool calls are adjudicated by the ordinary policy again"
}
.to_owned(),
)
}
/// The line the shell paints, with the half that says whose sentence it is.
///
/// **Fact first, remedy last**, which every refusal this seat paints keeps
/// and which the notice's own wrap (bl-3d0f) exists to protect: the half
/// that says what to do is the half a cut sentence loses.
pub fn line(&self) -> String {
match self {
Self::Refused(said) => format!("the engine refused: {said}"),
Self::Unreadable(why) => format!("this seat could not read the answer: {why}"),
Self::Unreachable(why) => format!("this seat could not reach it: {why}"),
Self::InDoubt { op, why } => format!(
"`{op}` is IN DOUBT: it reached the engine and no answer came back \
({why}), so it may have run. This seat never resends an act — the \
world is the record, and the reads on this window are already \
asking it again."
),
Self::Said(said) => said.clone(),
Self::Unsent { op, why } => format!(
"`{op}` was not sent: it never left this seat ({why}), so nothing \
happened — it is safe to do it again."
),
}
}
}