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
pub use ;
pub use Causal;
pub use Fifo;
pub use ;
/// The buffer's *stability rule*: the seam an [`Ideal`](crate::metis::Ideal) runs its machine over (PRD 0009).
///
/// [`Ideal`](crate::metis::Ideal) is a general machine. It holds an event until
/// stable, releases the stable frontier in stamp-minimal order, and forgets
/// released events. This trait names only the stability rule.
/// Causal happens-before is one rule ([`Causal`]), per-source FIFO another
/// ([`Fifo`]), [`And`] composes two, and a participation or quorum watermark
/// is a caller's.
///
/// The gate is the axis *below* the frontier: when to release. The resolver
/// above it. The caller decides what the concurrent frontier becomes
/// (PRD 0008).
///
/// # The invariant: `stale` is terminal
///
/// [`Progress`](Self::Progress) is ordered by information, starts at bottom,
/// and [`advance`](Self::advance) moves it only *up*. That monotone rise is
/// load-bearing: every law here is stated against it. The shipped gates go
/// further, their progress being a join-semilattice, but the machine never
/// joins two arbitrary progresses, so that lattice shape is those gates' and
/// not the trait's.
///
/// Fix a `(sender, dep)` pair. As progress rises, a gate MUST sort each
/// progress state into three regions, and MUST report at most one region at a
/// time: *waiting*, *deliverable*, and *dead*. [`stale`](Self::stale) reports
/// the *dead* region. Three independent laws over those regions make the
/// machine safe:
///
/// * *Terminal `stale`.* `{ progress : stale(p, _, dep) }` is an up-set: once
/// stale, stale for every greater progress. That finality is what lets
/// [`insert`](crate::metis::Ideal::insert) drop a stale event, and the
/// bounded [`try_insert`](crate::metis::Ideal::try_insert) reclaim a
/// pending one, on the strength of the current progress alone.
/// * *Disjoint from [`deliverable`](Self::deliverable).* No progress reports
/// an event both stale and deliverable. The release path consults only
/// `deliverable`, so this is what stops the stale-first drop discarding an
/// event a release would have delivered.
///
/// * *Stable up-closure.* Deliverable-or-stale is itself an up-set: once
/// stable, always stable. This does **not** follow from the other two ---
/// a gate with `deliverable(p) = (p == 0)` and `stale` always false
/// satisfies both and still returns the event to *waiting* once another
/// release advances progress, stranding it. `deliverable` alone need not
/// be monotone: causal contiguity is an equality, and it goes false on
/// overshoot. Terminal `stale` absorbs that overshoot for the shipped
/// gates. A gate whose `stale` does not fire there owes this law
/// separately.
///
/// These are laws an impl must satisfy, not properties the machine checks,
/// though [`check_gate_laws`] checks all three on a caller-supplied case.
///
/// A revisable gate, whose natural `stale` is not terminal, reports
/// `stale == false`. This works only where its `deliverable` is
/// independently up-closed, since stable up-closure then rests on
/// `deliverable` alone. A gate meeting neither needs its own machine rather
/// than a relaxed gate (`docs/metis-gate-stale-contract.adoc`).
///
/// The gate is handed the `sender` beside the dependency, because a bare
/// descriptor need not name which station authored the event. The machine
/// owns the stamp and the linearization and never asks the gate about
/// either.
/// A [`Gate`] whose progress changes only when [`Ideal`](crate::metis::Ideal)
/// releases an event.
///
/// This capability is required for product composition. [`And`] advances both
/// components after a product release, so neither component may require an
/// independent witness or another checked transition outside the delivery
/// machine. [`EpochGate`](crate::metis::EpochGate) deliberately does not
/// implement this trait: epoch adoption is separate authority exercised by
/// [`Ideal::adopt_epoch`](crate::metis::Ideal::adopt_epoch).
///
/// Implementors assert that every legal progress transition is induced by
/// [`Gate::advance`] for an event this gate admitted. The trait is an explicit
/// capability boundary; the machine cannot derive that property from the
/// three gate functions.