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
//! The window-aggregation selector the embedding doors share: the serde-able
//! [`AggregatePolicyKind`] and the [`EmaRenormalizedOptions`] it carries.
//!
//! A door embeds a long input as several windows and combines them under one of
//! windit's `windit::aggregate::AggregatePolicy` strategies. This module is the
//! part of that surface a config file, CLI flag or environment variable
//! touches: a closed enum naming the built-in strategies, whose wire spellings
//! are owned and pinned here rather than by windit (windit's own `serde`
//! feature is deliberately not what produces them, so its differently-spelled
//! kind enum never defines the wire form). Each consuming door re-exports both
//! types at its own path.
use ;
/// The configuration [`AggregatePolicyKind::EmaRenormalized`] carries: the
/// smoothing factor a `windit::aggregate::EmaRenormalized` policy is built
/// with, once a value has been read off a config surface.
///
/// Construction is infallible and the range is checked where the value is used,
/// the same contract [`EmaRenormalized::new`] itself keeps — see [`Self::new`].
///
/// # Why it is not named `EmaRenormalized`
///
/// A variant and its payload struct may otherwise share a name, living in
/// different namespaces; here they cannot, because `EmaRenormalized` is
/// already bound in this module as windit's policy type. A bare `EmaOptions`
/// would clear that collision and still be wrong: a door's flat namespace may
/// hold a SECOND ema whose parameter is also an `alpha` — a streaming vector
/// smoother — so the name has to say which ema it configures. `…Options` is
/// this crate's suffix for a configuration carrier, and is what windit calls
/// the same infallible-construction, validated-where-used shape
/// ([`WindowOptions`]).
///
/// [`WindowOptions`]: windit::plan::WindowOptions
/// A serde-able closed enum over the built-in policies, for config surfaces
/// (a file, CLI flag, or env var that names the aggregation strategy).
///
/// Custom policies use `windit::aggregate::AggregatePolicy` directly — this
/// wrapper exists only so the *built-ins* survive a round trip through text.
/// [`Self::into_policy`] converts a deserialized value into the trait object the
/// pipeline runs. The wire spellings are owned here and pinned (windit's own
/// kind enum never defines them); the mapping to windit policies happens in
/// [`Self::into_policy`].
///
/// Every variant is unit or newtype — the EMA parameter lives in
/// [`EmaRenormalizedOptions`] rather than loose in the variant — and no
/// `is_`/`unwrap_`/`try_unwrap_` face is generated over them: every consumer
/// here matches exhaustively on purpose, which is what the two no-`_` matches
/// below buy, so a helper triple would be unspent public surface.
///
/// # Golden-enum contract (what the tests actually force)
///
/// A wildcard-free golden test (`serde` feature) serializes each representative
/// in the test-only `REPRESENTATIVES` roster to a pinned JSON literal, round-trips
/// it, and rejects a non-`snake_case` spelling. Two exhaustive, no-`_` matches
/// stop a new variant being added half-way in the ways that matter at runtime:
///
/// - [`Self::into_policy`] has no `_` arm, so a new variant fails to compile until
/// it is dispatched to a policy.
/// - The golden test's `match kind` has no `_` arm, so a new variant fails to
/// compile until its expected JSON literal is written.
///
/// What is **not** compiler-enforced is roster completeness: the round-trip
/// iterates the hand-maintained test-only `REPRESENTATIVES` slice, so *executing* a
/// new variant's round-trip still requires adding it there (keep it complete).
/// This is weaker than alignkit's `define_alignment_fallback!`, which
/// co-generates the enum and its roster in one macro; the payload-carrying
/// [`Self::EmaRenormalized`] is why the roster is hand-written here, so its
/// completeness is a maintained invariant rather than a compile-time guarantee.
/// **This spelling is persisted by downstream derivation fingerprints — change
/// it only with a major bump.**
///
/// The kind's snake_case name, and for an EMA its factor through `f64`'s own
/// `Display`, the shortest representation that round-trips:
/// `coverage_weighted_mean`, `mean_renormalized`, `ema_renormalized(alpha=0.5)`.