caixa_core/supervisor.rs
1//! OTP-shaped supervisor trees, encoded as a typed `:kind Supervisor`
2//! caixa with a strategy + restart-policy children list.
3//!
4//! See `theory/INSPIRATIONS.md` §II.2 + §III.2 for the prior-art frame
5//! (Erlang OTP supervisor + Lunatic supervisor strategies as Rust types).
6//!
7//! ```lisp
8//! (defcaixa
9//! :nome "my-app-root"
10//! :versao "0.1.0"
11//! :kind Supervisor
12//! :estrategia OneForOne
13//! :max-restarts 5
14//! :restart-window "60s"
15//! :children ((:caixa "worker" :versao "^0.1" :restart Permanent)
16//! (:caixa "cache-server" :versao "^0.1" :restart Transient)
17//! (:caixa "scratch-job" :versao "^0.1" :restart Temporary)))
18//! ```
19//!
20//! wasm-operator (M3) walks the tree, materializes one ComputeUnit per
21//! child, and applies the strategy on child failure. The Rust types
22//! here are the typed contract; the runtime owns lifecycle.
23
24use std::time::Duration;
25
26use serde::{Deserialize, Serialize};
27use thiserror::Error;
28
29/// One of the four canonical Erlang/OTP restart strategies.
30///
31/// The strategy decides what happens to *sibling* children when one
32/// child dies. Per-child behaviour is governed by [`RestartPolicy`].
33#[derive(
34 Serialize,
35 Deserialize,
36 Debug,
37 Clone,
38 Copy,
39 PartialEq,
40 Eq,
41 Hash,
42 gen_platform::TypedDispatcher,
43 gen_platform::Discriminant,
44 gen_platform::IsVariant,
45 gen_platform::FromStrKind,
46)]
47pub enum RestartStrategy {
48 /// On child failure, restart only that child. Default; matches
49 /// most "tree of independent workers" use cases.
50 OneForOne,
51 /// On child failure, restart every child. Used when children
52 /// share state and must be in sync.
53 OneForAll,
54 /// On child failure, restart the failed child and every child
55 /// started *after* it (preserving startup order). Used when later
56 /// children depend on earlier ones.
57 RestForOne,
58 /// Dynamic children of the same shape, started on demand. The
59 /// supervisor doesn't know its children at boot; they're added as
60 /// they're needed (e.g. one child per session).
61 SimpleOneForOne,
62}
63
64impl Default for RestartStrategy {
65 fn default() -> Self {
66 // Route the [`Default for RestartStrategy`] impl through the
67 // substrate-canonical [`SUPERVISOR_ESTRATEGIA_DEFAULT`] typed
68 // `pub const` rather than a raw `Self::OneForOne` arm — one
69 // source of truth for the Erlang/OTP `one_for_one` half of Learn
70 // You Some Erlang's `{one_for_one, intensity, 5, 60}` worker-
71 // supervisor canonical default, paired with the sibling
72 // `SUPERVISOR_MAX_RESTARTS_DEFAULT` `MaxIntensity` half (b698ec0)
73 // and `SUPERVISOR_RESTART_WINDOW_DEFAULT` `Period` half (f7dcd0e).
74 // Pinned by `restart_strategy_default_routes_through_lifted_default`.
75 SUPERVISOR_ESTRATEGIA_DEFAULT
76 }
77}
78
79impl RestartStrategy {
80 /// Exhaustive iteration surface for every consumer that walks the
81 /// closed four-arm [`RestartStrategy`] discriminator set (the future
82 /// M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
83 /// admission-webhook rejection body naming the accepted-`:estrategia`
84 /// list, a future `feira supervisor --estrategia …` CLI arg-parse's
85 /// "did you mean" hint via a [`Self::from_wire`]-scan over the slice,
86 /// the future `feira app graph` per-supervisor `:estrategia` column,
87 /// any future round-trip fuzz harness that sweeps every arm). A
88 /// future arm addition (an OTP-`rest_for_all` arm the theory
89 /// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
90 /// might reach for once the four canonical OTP strategies stop
91 /// covering the substrate's discovered load-shape) extends this
92 /// slice as one edit and every consumer picks up the new entry by
93 /// construction; the compiler-checked exhaustiveness on the sibling
94 /// method `match` arms ([`Self::as_str`] / [`Self::from_wire`]) is
95 /// the build-time guarantee that no arm forgets to grow.
96 ///
97 /// Peer of the sibling closed-set typed enums'
98 /// [`crate::CaixaKind::ALL`] (6b1f4fb) /
99 /// [`crate::aplicacao::PlacementStrategy::ALL`] (18c7342) /
100 /// [`crate::aplicacao::RateLimitUnit::ALL`] (6bce03d) /
101 /// [`crate::dep::DepList::ALL`] (45ee563) exhaustive-iteration
102 /// surfaces — the fifth (and the first M2 OTP-shape) closed-set
103 /// typed enum on the caixa surface to converge onto the same
104 /// one-canonical-arm-list-per-enum discipline.
105 pub const ALL: &'static [Self] = &[
106 Self::OneForOne,
107 Self::OneForAll,
108 Self::RestForOne,
109 Self::SimpleOneForOne,
110 ];
111
112 /// Substrate-canonical exhaustive accept-set on the
113 /// [`RestartStrategy`] `PascalCase` wire byte-string axis — the
114 /// closed four-arm roster of every byte-string [`Self::as_str`]
115 /// returns, routed byte-for-byte through the paired
116 /// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
117 /// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
118 /// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
119 /// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`]
120 /// lifted `pub const` roster the [`Self::as_str`] emitter (and the
121 /// [`std::fmt::Display`] / [`AsRef<str>`] /
122 /// `From<{Self,&Self}> for {&'static str, String, Cow<'static, str>,
123 /// Box<str>, Arc<str>}` trait triple + quintuple routed through it)
124 /// walks — and byte-for-byte the same four strings the un-`rename`d
125 /// `Serialize` derive emits under the paired
126 /// [`crate::render::SUPERVISOR_KEY_ESTRATEGIA`] tag key on every
127 /// JSON / YAML CR round-trip.
128 ///
129 /// Peer of the sibling [`crate::CaixaKind::WIRE_NAMES`] (bd708bd)
130 /// roster on the top-level typed-kind discriminator's `PascalCase`
131 /// wire byte-string axis, and of the sibling
132 /// [`crate::upgrade::UpgradeInstruction::WIRE_FORMS`] (cc42c0e) /
133 /// [`crate::upgrade::UpgradeInstruction::LISP_FORMS`] (1898d77)
134 /// rosters on the OTP-appup discriminator's two-axis roster split —
135 /// the same closed-set exhaustive-accept-set roster discipline
136 /// extended here onto the first M2 OTP-shape sibling-restart
137 /// closed-set typed enum. The sibling
138 /// [`crate::aplicacao::PlacementStrategy`] M3 mesh-shape distribution
139 /// strategy enum is the next natural peer on the same axis, still
140 /// carrying only [`crate::aplicacao::PlacementStrategy::ALL`].
141 ///
142 /// Downstream consumers of the closed accepted-wire-form set — a
143 /// future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook
144 /// rejection body enumerating the accepted JSON `:estrategia` values
145 /// verbatim (as distinct from the kebab-case dispatcher-catalog
146 /// enumeration [`Self::discriminant`] serves, whose per-arm form
147 /// `"one-for-one"` / `"one-for-all"` / `"rest-for-one"` /
148 /// `"simple-one-for-one"` structurally disagrees with the wire byte-
149 /// string these `PascalCase` entries carry), a future `feira
150 /// supervisor --estrategia …` CLI-side "did you mean" hint whose
151 /// candidate-list must byte-match the wire form the operator's
152 /// per-strategy dispatch keys off (rather than the kebab
153 /// dispatcher-catalog identity), a future `feira app graph`
154 /// per-supervisor `:estrategia`-histogram column that renders
155 /// zero-count arms, a future wasm-operator per-reconcile-step
156 /// diagnostic log line enumerating accepted wire forms on an
157 /// unknown-strategy rejection, a future
158 /// `tracing::field::valuable::Value::List` structured-log accepted-
159 /// wire-form emit — now reach for one lifted substrate-primitive
160 /// roster rather than open-coding a four-string array-literal
161 /// (`["OneForOne", "OneForAll", "RestForOne", "SimpleOneForOne"]`)
162 /// whose arm-set has no compile-time link back to the typed
163 /// [`RestartStrategy`] enum. A future arm addition (an OTP-`rest_for_all`
164 /// arm the theory
165 /// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
166 /// might reach for once the four canonical OTP strategies stop
167 /// covering the substrate's discovered load-shape) extends this
168 /// roster as a single edit — paired with the [`Self::as_str`]
169 /// match's compiler-checked exhaustiveness on the new arm — and
170 /// every consumer picks up the new wire form by construction rather
171 /// than a coordinated array-literal rewrite across every downstream
172 /// site.
173 ///
174 /// Length is pinned load-bearing at `RestartStrategy::ALL.len()`
175 /// (four) by
176 /// [`tests::restart_strategy_wire_names_covers_every_arm`], every
177 /// variant's [`Self::as_str`] projection is pinned to a member of
178 /// the roster so a silent skew between the emitter's arm-set and
179 /// this const's arm-set trips at caixa-core test time rather than
180 /// at a downstream consumer's accepted-set enumeration miss, and
181 /// every entry is further pinned to open with an ASCII uppercase
182 /// byte so a silent collapse of the wire-form axis with the peer
183 /// kebab-case dispatcher-catalog axis (an entry byte-identical to a
184 /// sibling [`Self::discriminant`] kebab byte-string that would let
185 /// a wire-axis consumer accept the dispatcher-catalog vocabulary)
186 /// trips here rather than at a downstream K8s-CR round-trip miss.
187 pub const WIRE_NAMES: &'static [&'static str] = &[
188 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
189 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
190 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
191 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
192 ];
193
194 /// Canonical PascalCase discriminator scalar this variant serializes
195 /// as under [`crate::render::SUPERVISOR_KEY_ESTRATEGIA`]. The four arms
196 /// return the paired [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`]
197 /// / [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
198 /// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
199 /// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] lifted
200 /// constants so every substrate consumer that dispatches on the
201 /// per-supervisor sibling-restart strategy (the future
202 /// wasm-operator's per-supervisor sibling-restart branch, the future
203 /// M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
204 /// admission-time enum-arm bind, the `caixa-operator`'s hierarchical
205 /// reconciliation scheduler's per-strategy fan-out) reads the same
206 /// byte-string the `Serialize` derive emits — the pin test in
207 /// [`tests::restart_strategy_variants_serialize_to_lifted_scalar_values`]
208 /// asserts the two paths agree, peer of the M3
209 /// `PlacementStrategy::as_str` (cc8f749) on the sibling per-Aplicacao
210 /// distribution-strategy axis.
211 #[must_use]
212 pub const fn as_str(self) -> &'static str {
213 match self {
214 Self::OneForOne => crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
215 Self::OneForAll => crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
216 Self::RestForOne => crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
217 Self::SimpleOneForOne => crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
218 }
219 }
220
221 /// Substrate-canonical reverse projection on the `:supervisor
222 /// :estrategia` closed-set axis — parses the `PascalCase`
223 /// discriminator scalar back to the typed variant, or `None` when
224 /// `s` is outside
225 /// the closed-set arm-string set [`Self::as_str`] emits. Dispatches
226 /// on the same lifted
227 /// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
228 /// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
229 /// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
230 /// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`]
231 /// constants the [`Self::as_str`] emitter walks, so the parse and
232 /// emit halves of the round-trip migrate through one caixa-core
233 /// edit on any future arm addition.
234 ///
235 /// Prior to this lift the substrate carried only the forward
236 /// `Self → &str` projection on the OTP sibling-restart axis (the
237 /// [`Self::as_str`] emitter, the [`std::fmt::Display`] impl routed
238 /// through it, the `Serialize` derive that emits the same
239 /// byte-string under [`crate::render::SUPERVISOR_KEY_ESTRATEGIA`])
240 /// plus the kebab-case dispatcher-catalog identity via
241 /// [`Self::discriminant`] — every non-serde consumer that wanted to
242 /// parse a wire-form `PascalCase` strategy scalar had to re-inline
243 /// a four-arm `match s { "OneForOne" => …, "OneForAll" => …,
244 /// "RestForOne" => …, "SimpleOneForOne" => …, _ => … }` cascade
245 /// that expressed no compile-time link back to the typed variant's
246 /// canonical lifted constant. A future variant rename or per-arm
247 /// serde-attribute drift would silently split the wire byte-string
248 /// one non-serde consumer parsed from the one the emitter wrote,
249 /// with the failure surfacing at parse time far from the rebrand
250 /// commit.
251 ///
252 /// Distinct axis from the [`std::str::FromStr`] impl the
253 /// [`gen_platform::FromStrKind`] derive already installs on this
254 /// enum by design, not by drift: `FromStr` parses the *kebab-case*
255 /// dispatcher-catalog identity (`"one-for-one"` / `"one-for-all"` /
256 /// `"rest-for-one"` / `"simple-one-for-one"` — the inverse of
257 /// [`Self::discriminant`]), while this method inverts the
258 /// `PascalCase` wire byte-string [`Self::as_str`] emits. The
259 /// two-axis split lets the dispatcher-catalog identity live in
260 /// kebab-case
261 /// (where every peer catalog identifier already lives) without
262 /// forcing a wire-format rename on the tatara-lisp author surface
263 /// (`:estrategia OneForOne`, `PascalCase`) — the same two-axis
264 /// distinction the sibling [`crate::CaixaKind::from_wire`] (2aa6d23)
265 /// / [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342)
266 /// carry on their peer closed-set typed-enum wire round-trips.
267 ///
268 /// Same closed-set-reverse-projection discipline the sibling
269 /// [`crate::CaixaKind::from_wire`] (2aa6d23) /
270 /// [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342) /
271 /// [`crate::aplicacao::RateLimitUnit::from_suffix`] typed enums
272 /// carry on the peer wire-side `str → Self` axes — extended onto
273 /// the M2 OTP-shape sibling-restart-strategy closed-set axis, the
274 /// fifth substrate-side closed-set typed enum to converge on the
275 /// two-way `str ↔ Self` round-trip. Method-named `from_wire` (not
276 /// `from_str`) to match the peer [`crate::CaixaKind::from_wire`]
277 /// shape verbatim and side-step the [`std::str::FromStr`] impl the
278 /// derive already installs on the sibling kebab-case axis. Returns
279 /// `Option<Self>` (rather than `Result<Self, _>`) to match the peer
280 /// shapes: the caller picks the diagnostic form appropriate for
281 /// its use site.
282 #[must_use]
283 pub fn from_wire(s: &str) -> Option<Self> {
284 match s {
285 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE => Some(Self::OneForOne),
286 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL => Some(Self::OneForAll),
287 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE => Some(Self::RestForOne),
288 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE => Some(Self::SimpleOneForOne),
289 _ => None,
290 }
291 }
292}
293
294/// [`std::fmt::Display`] routed through [`RestartStrategy::as_str`], so the
295/// pretty-printed byte-string every consumer that formats the strategy as
296/// user-facing text lands on (the future wasm-operator's per-supervisor
297/// sibling-restart-strategy diagnostic line, the future `feira app graph`
298/// per-supervisor strategy line, the future M4
299/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission-webhook
300/// rejection body) reaches for the same lifted
301/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
302/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
303/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
304/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const the
305/// wire-format `Serialize` derive already emits under
306/// [`crate::render::SUPERVISOR_KEY_ESTRATEGIA`] and the
307/// [`RestartStrategy::as_str`] helper already returns.
308///
309/// Pre-convergence the two paths structurally disagreed — the
310/// `#[derive(gen_platform::Discriminant)]` + `#[discriminant(also_display)]`
311/// route (now retired here) sent [`std::fmt::Display`] through the
312/// gen-platform discriminant catalog string, which arrives kebab-case as
313/// `"one-for-one"` / `"one-for-all"` / `"rest-for-one"` /
314/// `"simple-one-for-one"`, while the wire format ran as `PascalCase`
315/// `"OneForOne"` / `"OneForAll"` / `"RestForOne"` / `"SimpleOneForOne"`
316/// through the un-`rename`d serde derive. Every consumer that formatted
317/// the strategy for a diagnostic line, a graph, or a rejection body under
318/// `format!("{v}")` therefore landed under a different byte-string than
319/// the wire format the operator's per-strategy dispatch keyed off — a
320/// silent split whose apply-time symptom (a `format!("{v}")`-carrying
321/// diagnostic quoting `"one-for-one"` while the wire scalar the operator
322/// probed was `"OneForOne"`) surfaced as a confused correlate at
323/// operator-log time far from the two-declaration site.
324///
325/// Routing `Display` through [`RestartStrategy::as_str`] closes the third
326/// path: every `format!("{v}")` call reaches the same lifted
327/// [`crate::render::SUPERVISOR_ESTRATEGIA_*`] const the wire format and
328/// the [`RestartStrategy::as_str`] helper route through — `Debug` (the
329/// compiler-derived variant name), `Display` (via `as_str`), and `Serialize`
330/// (via the un-`rename`d derive) all resolve to the same `PascalCase`
331/// byte-string per variant. A future variant rename or
332/// `#[serde(rename_all = "kebab-case")]` attribute reaches every path at
333/// exactly one place, structurally.
334///
335/// The dispatcher-catalog identity remains kebab-case — [`Self::discriminant`]
336/// (from `#[derive(gen_platform::Discriminant)]`) still returns
337/// `"one-for-one"` / etc., and the fleet-wide
338/// [`gen_platform::register_dispatcher!("caixa.restart-strategy", …)`]
339/// registration keys the catalog off the same kebab identity. The two
340/// naming worlds now live on separate typed methods (`Display` /
341/// `as_str` for the wire byte-string, `discriminant` for the catalog
342/// identity) rather than sharing one `Display` route that structurally
343/// disagrees with the wire format.
344///
345/// Pin tests
346/// [`tests::restart_strategy_display_routes_through_as_str_helper`]
347/// and
348/// [`tests::restart_strategy_display_matches_serialized_wire_byte_string`]
349/// assert the three paths agree byte-for-byte on every variant, so a
350/// future variant rename or per-arm serde attribute drift is a build
351/// error visible at caixa-core test time, not a silent per-consumer
352/// dispatch miss at apply / reconcile time.
353///
354/// Mirrors the M3 [`crate::aplicacao::PlacementStrategy`] `Display` impl
355/// (aplicacao.rs:2306) on the sibling per-Aplicacao distribution-strategy
356/// axis — same three-path-convergence discipline, extended to close the
357/// second of three OTP-shaped closed-enum discriminator axes on the
358/// caixa typed surface.
359impl std::fmt::Display for RestartStrategy {
360 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
361 f.write_str(self.as_str())
362 }
363}
364
365/// Substrate-canonical [`AsRef<str>`] projection on the M2
366/// per-supervisor sibling-restart [`RestartStrategy`] closed-set typed
367/// enum — routes through the same [`RestartStrategy::as_str`]
368/// `pub const fn` scalar accessor the paired [`std::fmt::Display`]
369/// impl and the un-`rename`d [`serde::Serialize`] derive already key
370/// off, so any future consumer that binds a [`RestartStrategy`]
371/// through the standard-library `impl AsRef<str>` bound (a future
372/// [`caixa-feira`] `feira supervisor --estrategia <arm>` verb that
373/// composes the emitted `PascalCase` wire scalar into a
374/// [`std::process::Command::arg`] shell-out of the future
375/// wasm-operator's admission gate, a per-supervisor structured-log
376/// recorder on the future `caixa-operator`'s hierarchical
377/// reconciliation surface that accepts `impl AsRef<str>` at the
378/// `tracing::field::Value` `Str`-arm, a [`std::collections::HashMap`]
379/// lookup keyed on the estrategia wire byte through
380/// `map.get::<str>(strategy.as_ref())` on a future per-strategy
381/// dispatch table) reaches the paired [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`]
382/// / [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
383/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
384/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`]
385/// lifted-const through one substrate-primitive dispatch rather
386/// than an open-coded `.as_str()` projection at every wire-up.
387///
388/// Peer of the sibling [`std::fmt::Display`] impl on the same
389/// primitive — both delegate to the shared
390/// [`RestartStrategy::as_str`] `pub const fn` accessor, so
391/// [`format!("{s}")`], `s.as_str()`, and
392/// `<RestartStrategy as AsRef<str>>::as_ref(&s)` resolve to the same
393/// byte-string per instance by construction. A future variant rename
394/// or `#[serde(rename_all = "kebab-case")]` attribute-drift on the
395/// enum reaches every one of the three paths (plus the wire-format
396/// `Serialize` derive that already routes through the same lifted
397/// const) through exactly one caixa-core edit.
398///
399/// Same "route the trait impl through the substrate-primitive
400/// accessor" discipline the sibling [`crate::CaixaVersion`]
401/// [`AsRef<str>`] impl (16d5c7e) carries on the paired top-level
402/// `:versao` typed newtype — extends it onto the second `AsRef<str>`
403/// axis on the caixa typed surface (the first M2 OTP-shape
404/// closed-set typed enum to converge onto the standard-library
405/// [`AsRef<str>`] projection). Rust-side newtype/typed-enum
406/// convention pairs [`AsRef<str>`] and [`fmt::Display`] on the same
407/// primitive so a caller who has one has both; before this lift,
408/// [`RestartStrategy`] carried [`fmt::Display`] but not the paired
409/// [`AsRef<str>`] impl the convention names.
410///
411/// Pinned load-bearing by
412/// [`tests::restart_strategy_as_ref_str_routes_through_as_str_accessor`]
413/// (byte-parity pin against [`RestartStrategy::as_str`] across the
414/// four-arm closed set) — any future silent detour that routes the
415/// impl through a divergent projection (a per-arm inline
416/// `match self { … }` re-inlining that opens a compile-time link to
417/// the un-lifted arm-literal, a swap onto the kebab-case
418/// [`gen_platform::Discriminant`] catalog identity that would collide
419/// the wire axis with the dispatcher-catalog axis) trips at
420/// caixa-core test time under `assert_eq!` rather than at a
421/// downstream `impl AsRef<str>`-bound consumer's silent split.
422impl AsRef<str> for RestartStrategy {
423 fn as_ref(&self) -> &str {
424 self.as_str()
425 }
426}
427
428/// Trait-idiomatic reverse projection on the M2-OTP-shape sibling-restart
429/// [`RestartStrategy`] closed-set typed enum — routes byte-for-byte through
430/// the paired substrate-primitive [`RestartStrategy::from_wire`]
431/// `Option<Self>` accessor so every future consumer that binds a
432/// `PascalCase` `:supervisor :estrategia` wire byte-string through the
433/// standard-library `.try_into()` / [`TryFrom`] axis (a future
434/// [`caixa-feira`] `feira supervisor --estrategia <OneForOne|OneForAll|
435/// RestForOne|SimpleOneForOne>` CLI arg-parse that composes into
436/// `let estrategia: RestartStrategy = s.try_into()?`, a future
437/// `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook that folds a
438/// `spec.estrategia: String` field through
439/// `RestartStrategy::try_from(&s)?`, a generic
440/// `<T: TryFrom<&str>>`-bound loader over any of the substrate's closed-
441/// set typed enums) reaches the same four-arm accept-set the sibling
442/// [`RestartStrategy::from_wire`] resolver parses through and the sibling
443/// [`RestartStrategy::as_str`] emits, rather than an open-coded per-arm
444/// `match s { "OneForOne" => …, "OneForAll" => …, "RestForOne" => …,
445/// "SimpleOneForOne" => …, _ => … }` cascade whose arm-set has no
446/// compile-time link back to the substrate primitive.
447///
448/// Complements the pre-existing forward-projection triple
449/// ([`std::fmt::Display`], [`AsRef<str>`], [`RestartStrategy::as_str`])
450/// with the paired trait-idiomatic reverse-projection axis: Rust-side
451/// newtype/typed-enum convention pairs [`AsRef<str>`] with either
452/// [`std::str::FromStr`] or [`TryFrom<&str>`] on the same primitive so a
453/// caller who can project *out to* a `&str` can also project *in from*
454/// one. The [`TryFrom<&str>`] axis is deliberately chosen over
455/// [`std::str::FromStr`] to sidestep the `clippy::should_implement_trait`
456/// lint the sibling method-named [`RestartStrategy::from_wire`] would
457/// trigger under a `FromStr` impl and to avoid colliding with the
458/// [`std::str::FromStr`] impl the [`gen_platform::FromStrKind`] derive
459/// already installs on the paired *kebab-case dispatcher-catalog* axis
460/// (which parses `"one-for-one"` / `"one-for-all"` / `"rest-for-one"` /
461/// `"simple-one-for-one"`, the inverse of [`Self::discriminant`]) — this
462/// impl closes the trait-idiomatic reverse axis on the *`PascalCase` wire*
463/// half without disturbing either the method-named `from_wire` shape every
464/// sibling closed-set typed enum on the substrate already carries or the
465/// pre-existing `FromStr` on the dispatcher-catalog half, keeping the
466/// two-axis split the sibling [`Self::from_wire`] doc block motivates.
467///
468/// `type Error = ()` matches the sibling [`RestartStrategy::from_wire`]'s
469/// `Option<Self>` return-shape's deliberate deferral of error typing: the
470/// caller picks the diagnostic form appropriate for its use site (a future
471/// `feira supervisor --estrategia` arg-parse composes its own per-verb
472/// "unknown strategy: <arg> — accepted: {…}" message enumerating
473/// [`RestartStrategy::ALL`], a future M4 admission-webhook rejection body
474/// wraps the `Err(())` outcome with the accepted-set enumeration for
475/// operator diagnostics, a `Result::map_err` at the call site lifts the
476/// unit-error to a per-verb error type). Same shape the peer
477/// [`crate::CaixaKind`] (3c83606), [`crate::CaixaDialeto`] (bf33136),
478/// [`crate::aplicacao::PlacementStrategy`] (6fd00cd), and
479/// [`crate::provedor::ferrite::FerriteRuntime::from_wire`] blocks motivate
480/// on their peer closed-set typed enums' reverse projections.
481///
482/// The paired [`TryFrom<&str>`] impl reaches the same four-arm accept-set
483/// the [`RestartStrategy::from_wire`] resolver dispatches through, so any
484/// future arm addition (an OTP-`rest_for_all` fifth arm the theory
485/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
486/// might reach for once the four canonical OTP strategies stop covering
487/// the substrate's discovered load-shape) grows the trait-idiomatic axis
488/// by construction — one caixa-core edit on
489/// [`RestartStrategy::from_wire`] extends both the method-named reverse
490/// projection every existing consumer keys off and the trait-idiomatic
491/// reverse projection this impl exposes, without a coordinated rewrite
492/// across every future `TryFrom<&str>`-bound consumer's arm-set.
493///
494/// Extends the substrate-wide closed-set-enum reverse-projection family
495/// ([`crate::CaixaKind`] via 3c83606, [`crate::CaixaDialeto`] via bf33136,
496/// [`crate::aplicacao::PlacementStrategy`] via 6fd00cd) onto the first
497/// M2-OTP-shape closed-set typed enum on the caixa surface — the
498/// `:supervisor :estrategia` closed set the future wasm-operator's
499/// hierarchical reconciliation scheduler keys off end-to-end.
500///
501/// Pinned load-bearing by
502/// [`tests::restart_strategy_try_from_str_routes_through_from_wire_accessor`]
503/// (byte-parity pin against [`RestartStrategy::from_wire`] across the
504/// four-arm accept-set) and
505/// [`tests::restart_strategy_try_from_str_rejects_unknown_byte_strings`]
506/// (rejection witness against silent accept-set widening).
507impl TryFrom<&str> for RestartStrategy {
508 type Error = ();
509
510 fn try_from(s: &str) -> Result<Self, Self::Error> {
511 Self::from_wire(s).ok_or(())
512 }
513}
514
515/// Trait-idiomatic *forward* projection on the M2-OTP-shape sibling-restart
516/// [`RestartStrategy`] closed-set typed enum onto the `&'static str` axis —
517/// routes byte-for-byte through the paired substrate-primitive
518/// [`RestartStrategy::as_str`] `pub const fn` accessor so every future
519/// consumer that binds a [`RestartStrategy`] through the standard-library
520/// `.into()` / [`From<Self> for &'static str`] (equivalently
521/// [`Into<&'static str>`]) axis (a future
522/// `tracing::field::valuable::Value::Str(strategy.into())` structured-log
523/// recorder where the `Str` arm typing demands `&'static str` and the
524/// sibling [`AsRef<str>`] impl's borrowed `&str` return-type does not
525/// satisfy the bound, a future `Cow::Borrowed::<'static, str>(strategy.into())`
526/// composer on the future M4 admission-webhook rejection body where the
527/// `Cow<'static, str>` typing rules out the sibling [`AsRef<str>`] borrowed
528/// return, a generic `<T: Into<&'static str>>`-bound serializer on a
529/// per-strategy diagnostic column) reaches the same lifted
530/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
531/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
532/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
533/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const the
534/// paired [`std::fmt::Display`], [`AsRef<str>`], and
535/// [`RestartStrategy::as_str`] surfaces already return, rather than an
536/// open-coded per-arm `match s { OneForOne => "OneForOne", … }` cascade
537/// whose arm-set has no compile-time link back to the substrate primitive.
538///
539/// Complements the pre-existing quadruple
540/// ([`std::fmt::Display`], [`AsRef<str>`], [`RestartStrategy::as_str`],
541/// [`TryFrom<&str>`] via 5b828ed) with the paired trait-idiomatic
542/// forward-projection axis: Rust-side newtype/typed-enum convention pairs
543/// [`TryFrom<&str>`] (trait-idiomatic reverse) with [`From<Self> for
544/// &'static str`] (trait-idiomatic forward) on the same primitive so a
545/// caller who can project *in from* a `&str` via the trait axis can also
546/// project *out to* one — mirroring the `strum::IntoStaticStr` /
547/// `serde::Serialize`-shape idiom where both projection halves share one
548/// trait-driven vocabulary. Before this lift the substrate carried a
549/// `&str`-returning [`AsRef<str>`] but not the paired `&'static str`-
550/// returning [`From<Self> for &'static str`] axis every downstream
551/// generic that specifically needs `'static` byte-string bytes reaches for.
552///
553/// The paired [`RestartStrategy::as_str`] returns `&'static str` by
554/// construction (each `match` arm resolves to a
555/// [`crate::render::SUPERVISOR_ESTRATEGIA_*`] `pub const &str` with static
556/// lifetime), so the trait's return-type promise is upheld structurally.
557/// Any future silent detour that routes the impl through a non-static
558/// projection (a per-arm inline `String::from("OneForOne")`-shaped
559/// re-inlining that would `.leak()`-cast for the `'static` bound, a
560/// hypothetical rebrand of one arm's [`crate::render::SUPERVISOR_ESTRATEGIA_*`]
561/// const to a non-`const &str`) is a caixa-core-build-time failure through
562/// the `pub const fn as_str` signature the trait routes through.
563///
564/// The paired impl reaches the same four-arm emit-set the
565/// [`RestartStrategy::as_str`] accessor dispatches through, so any future
566/// arm addition (an OTP-`rest_for_all` fifth arm the theory
567/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
568/// might reach for once the four canonical OTP strategies stop covering
569/// the substrate's discovered load-shape) grows the trait-idiomatic
570/// forward axis by construction — one caixa-core edit on
571/// [`RestartStrategy::as_str`] extends every one of the five sibling
572/// forward-projection paths ([`std::fmt::Display`], [`AsRef<str>`],
573/// [`RestartStrategy::as_str`] itself, this [`From<Self> for &'static str`],
574/// and the un-`rename`d [`serde::Serialize`] derive that also emits
575/// [`Self::as_str`]'s bytes) without a coordinated rewrite across every
576/// future `Into<&'static str>`-bound consumer's arm-set.
577///
578/// Opens the substrate-wide trait-idiomatic *forward*-projection family on
579/// closed-set fieldless typed enums — the mirror of the recently-closed
580/// trait-idiomatic *reverse*-projection family ([`crate::CaixaKind`] via
581/// 3c83606, [`crate::CaixaDialeto`] via bf33136,
582/// [`crate::aplicacao::PlacementStrategy`] via 6fd00cd, this enum via
583/// 5b828ed, [`crate::supervisor::RestartPolicy`] via 6fdd0d9,
584/// [`crate::aplicacao::WitShape`] via 5472902,
585/// [`crate::aplicacao::RateLimitUnit`] via bf78400,
586/// [`crate::render::PathShapeViolation`] via e67e48a, and the four
587/// downstream-crate peers — [`caixa_arch::InvariantKind`] via e21a857,
588/// [`caixa_arch::ArchVerdict`] via 0a4cc45, [`caixa_lint::Severity`] via
589/// a7bf74c, [`caixa_lint::FixSafety`] via df86c94,
590/// [`caixa_theme::Semantic`] via bd7da69, and
591/// [`caixa_provedor::ferrite::FerriteRuntime`] via 42ab951). This lift
592/// picks [`RestartStrategy`] as the first-mover on the forward-projection
593/// family because its wire byte-string (`PascalCase`) and diagnostic
594/// byte-string ([`as_str`] return) coincide by construction — the sibling
595/// [`crate::CaixaKind`] two-axis split (lowercase Portuguese diagnostic
596/// vs `PascalCase` wire) would leave a first-mover peer arbitrarily
597/// picking one axis; on [`RestartStrategy`] the choice is unambiguous.
598///
599/// Pinned load-bearing by
600/// [`tests::restart_strategy_from_into_static_str_routes_through_as_str_accessor`]
601/// (byte-parity pin against [`RestartStrategy::as_str`] across the
602/// four-arm emit-set, plus a `const`-context materialization witness for
603/// the `&'static str` lifetime promise) and
604/// [`tests::restart_strategy_from_into_static_str_and_as_str_partition_the_emit_set`]
605/// (partition pin asserting `<&'static str as From<RestartStrategy>>::from`
606/// and [`RestartStrategy::as_str`] agree on every arm, so no future
607/// silent bifurcation of the two forward-projection paths can land
608/// silently).
609impl From<RestartStrategy> for &'static str {
610 fn from(strategy: RestartStrategy) -> &'static str {
611 strategy.as_str()
612 }
613}
614
615/// Trait-idiomatic *forward* projection on [`RestartStrategy`] from a
616/// *borrowed* input onto the `&'static str` axis — the borrowed-input
617/// companion to the paired owned-input [`From<RestartStrategy> for
618/// &'static str`] impl immediately above. Routes byte-for-byte through
619/// the same substrate-primitive [`RestartStrategy::as_str`] `pub const
620/// fn` accessor so every consumer that binds a `&RestartStrategy`
621/// through the standard-library `.into()` / [`From<&Self> for &'static
622/// str`] axis (a `RestartStrategy::ALL.iter().map(<&'static
623/// str>::from).collect::<Vec<_>>()` per-arm accept-set materializer —
624/// whose iterator over `&'static [RestartStrategy]` yields
625/// `&RestartStrategy`, not `RestartStrategy`, so the owned-input
626/// [`From<RestartStrategy>`] axis alone forces every call site through
627/// an explicit `.copied()` / dereference / [`Copy`]-bound restatement
628/// rather than the direct trait-idiomatic projection; a future generic
629/// `<T: Copy + for<'a> Into<&'static str>>`-bound diagnostic column
630/// that walks the `iter().map(Into::into)` shape verbatim across every
631/// substrate-wide closed-set typed enum; the future wasm-operator's
632/// per-supervisor sibling-restart-strategy diagnostic line that
633/// composes the accepted-set enumeration from an iterated
634/// `RestartStrategy::ALL.iter().map(|s| s.into())` pipe rather than a
635/// per-arm `match s { … }` cascade; a future
636/// `HashMap::<&'static str, RestartStrategy>::from_iter(
637/// RestartStrategy::ALL.iter().map(|s| (s.into(), *s)))`-style
638/// per-strategy reverse-lookup table the sibling [`TryFrom<&str>`]
639/// impl cannot compose without this borrowed-input axis in place)
640/// reaches the same four-arm lifted
641/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
642/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
643/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
644/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
645/// the paired owned-input [`From<RestartStrategy> for &'static str`],
646/// the sibling [`std::fmt::Display`], [`AsRef<str>`], and
647/// [`RestartStrategy::as_str`] surfaces already return.
648///
649/// Fourth peer on the substrate-wide trait-idiomatic *borrowed-input*
650/// forward-projection family opened on [`crate::dep::DepList`]
651/// (64aa742) and extended onto [`crate::CaixaKind`] (5ab993a) and
652/// [`crate::CaixaDialeto`] (807b0b5). Rust's `From` trait does not
653/// auto-derive the `From<&Self>` sibling from a `From<Self>` impl (the
654/// blanket `impl<T, U> From<&T> for U where T: Copy, U: From<T>` does
655/// not exist in `core`), so every closed-set typed enum that carries
656/// the owned-input axis but not the borrowed-input axis forces every
657/// borrowed-input call site through a `.copied()` /
658/// `<&'static str>::from(*strategy)` / `strategy.as_str()` detour whose
659/// type bounds have no compile-time link to the substrate primitive.
660/// [`RestartStrategy`] is the first M2 OTP-shape peer to converge onto
661/// this campaign (mirroring the first-mover role it played on the
662/// owned-input axis in 523157d); the remaining eleven substrate-wide
663/// closed-set fieldless typed enum peers (`RestartPolicy`, `WitShape`,
664/// `RateLimitUnit`, `PlacementStrategy`, `PathShapeViolation`,
665/// `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`, `Semantic`,
666/// `FerriteRuntime`) are the future targets of this campaign.
667///
668/// Unlike the peer [`crate::CaixaKind`] axis pair (whose forward
669/// [`From<Self> for &'static str`] emits the lowercase Portuguese
670/// [`Self::as_str`] diagnostic vocabulary while the reverse
671/// [`TryFrom<&str>`] parses the `PascalCase` [`Self::wire_name`]
672/// author-surface vocabulary, forcing the round-trip through an
673/// intermediate wire-vocab hop), [`RestartStrategy`]'s
674/// [`Self::as_str`] emit and [`Self::from_wire`] parse share the same
675/// `PascalCase` vocabulary by construction, so the borrowed-input
676/// forward axis and the reverse axis compose directly — the round-trip
677/// witness pin below locks this direct composition without the
678/// intermediate hop the peer axis requires.
679///
680/// Pinned load-bearing by
681/// [`tests::restart_strategy_from_borrowed_into_static_str_routes_through_as_str_accessor`]
682/// (byte-parity pin against [`RestartStrategy::as_str`] across the
683/// four-arm emit-set via a borrowed input, plus a `const`-context
684/// materialization witness for the `&'static str` lifetime promise,
685/// plus a blanket `.into()` shape) and
686/// [`tests::restart_strategy_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
687/// (cross-axis partition pin against the paired owned-input
688/// [`From<RestartStrategy> for &'static str`] impl, plus a
689/// `.iter().map(Into::into)` pipe witness over
690/// [`RestartStrategy::ALL`], plus a direct round-trip witness through
691/// [`TryFrom<&str>`] that closes the two-way `&Self → &'static str →
692/// Self` round-trip without the wire-vocab intermediate the peer
693/// [`crate::CaixaKind`] axis pair requires).
694impl From<&RestartStrategy> for &'static str {
695 fn from(strategy: &RestartStrategy) -> &'static str {
696 strategy.as_str()
697 }
698}
699
700/// Trait-idiomatic *owned-`String`* forward projection on the M2
701/// OTP-shape sibling-restart-strategy closed-set typed enum — the
702/// owned-heap-string companion to the paired `&'static str`-returning
703/// [`From<RestartStrategy> for &'static str`] / [`From<&RestartStrategy>
704/// for &'static str`] impls immediately above. Routes byte-for-byte
705/// through the substrate-primitive [`RestartStrategy::as_str`]
706/// `pub const fn` accessor (via [`str::to_owned`]) so every consumer
707/// that binds a [`RestartStrategy`] through the standard-library
708/// `.into()` / [`From<Self> for String`] (equivalently
709/// [`Into<String>`]) axis — a future
710/// `serde_json::Value::String(strategy.into())` structured-payload
711/// composer where the `Value::String` arm typing demands an owned
712/// [`String`] and the sibling [`&'static str`]-returning axis forces an
713/// explicit `.to_owned()` / `String::from` restatement at every call
714/// site, a future
715/// `HashMap::<String, RestartStrategy>::from_iter(RestartStrategy::ALL
716/// .iter().map(|s| (s.into(), *s)))` per-strategy lookup where the
717/// map's key type is owned [`String`] rather than [`&'static str`], a
718/// future `Cow::<'static, str>::Owned(strategy.into())` composer on
719/// the future M4 admission-webhook rejection body's owned-arm, the
720/// future wasm-operator's per-supervisor `serde_json::json!({
721/// "estrategia": strategy })` diagnostic emit where the JSON
722/// serializer's `Serialize` impl on [`String`] owns the emit-path — reaches
723/// the same four-arm lifted
724/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
725/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
726/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
727/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const the
728/// paired [`std::fmt::Display`], [`AsRef<str>`],
729/// [`RestartStrategy::as_str`], and the two `&'static str`-returning
730/// forward-projection impls already return.
731///
732/// Opens the trait-idiomatic *owned-`String`* forward-projection axis
733/// on the closed-set fieldless typed enum surface — first-mover on the
734/// M2 OTP-shape sibling-restart-strategy axis, mirror of the
735/// [`crate::supervisor::RestartStrategy`] first-mover position that
736/// opened the paired owned-`&'static str` axis (523157d) and the
737/// borrowed-input `&'static str` axis on
738/// [`crate::dep::DepList`] (64aa742). Rust's standard library does not
739/// carry a blanket `impl<T: AsRef<str>> From<T> for String` (nor an
740/// `impl<T: fmt::Display> From<T> for String`), so every closed-set
741/// typed enum that carries the paired `AsRef<str>` / `Display` /
742/// `From<Self> for &'static str` triple but not the owned-[`String`]
743/// axis forces every owned-string call site through a `.to_string()` /
744/// `.as_str().to_owned()` / `String::from(strategy.as_str())` detour
745/// whose type bounds have no compile-time link to the substrate
746/// primitive.
747///
748/// Deliberately routes through the human-readable
749/// [`RestartStrategy::as_str`] axis — for this enum the wire format
750/// (`PascalCase`, tatara-lisp author surface `:estrategia OneForOne`)
751/// and the diagnostic byte-string share the same vocabulary by
752/// construction (unlike the sibling [`crate::CaixaKind`] enum whose two
753/// axes diverge), so the owned-[`String`] projection lands
754/// byte-identically on both the wire vocabulary the paired
755/// [`serde::Serialize`] derive emits and the diagnostic vocabulary the
756/// [`RestartStrategy::as_str`] helper returns.
757///
758/// The remaining fourteen closed-set typed enums on the caixa
759/// substrate surface (`RestartPolicy`, `CaixaKind`, `CaixaDialeto`,
760/// `DepList`, `PlacementStrategy`, `WitShape`, `RateLimitUnit`,
761/// `PathShapeViolation`, `InvariantKind`, `ArchVerdict`, `Severity`,
762/// `FixSafety`, `Semantic`, `FerriteRuntime`) are the future targets of
763/// this campaign — each carries the same paired `AsRef<str>` /
764/// `Display` / `From<Self> for &'static str` / `From<&Self> for
765/// &'static str` quadruple that this owned-[`String`] axis extends onto.
766///
767/// Pinned load-bearing by
768/// [`tests::restart_strategy_from_into_owned_string_routes_through_as_str_accessor`]
769/// (byte-parity pin against [`RestartStrategy::as_str`] across the
770/// four-arm emit-set, plus a blanket `.into::<String>()` shape witness)
771/// and
772/// [`tests::restart_strategy_from_into_owned_string_and_static_str_agree_on_every_arm`]
773/// (cross-axis partition pin against the paired owned-input
774/// [`From<RestartStrategy> for &'static str`] impl and the sibling
775/// [`ToString::to_string`] surface routed through [`std::fmt::Display`],
776/// plus a direct round-trip witness through [`TryFrom<&str>`] on the
777/// owned-[`String`]'s [`String::as_str`] borrow that closes the two-way
778/// `Self → String → Self` round-trip on the trait-idiomatic
779/// owned-[`String`] forward + reverse axis pair).
780impl From<RestartStrategy> for String {
781 fn from(strategy: RestartStrategy) -> String {
782 strategy.as_str().to_owned()
783 }
784}
785
786/// Trait-idiomatic *borrowed-input, owned-`String` output* forward
787/// projection on the M2 OTP-shape sibling-restart-strategy closed-set
788/// typed enum — the fourth (and closing) corner of the
789/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
790/// projection family. Routes byte-for-byte through the
791/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
792/// accessor (via [`str::to_owned`]) so every consumer that holds a
793/// borrowed [`&RestartStrategy`] and needs an owned [`String`] — a
794/// future `serde_json::Value::String(String::from(&strategy))`
795/// structured-payload composer over a borrowed field, a future
796/// `Iterator::map` over `&[RestartStrategy]` that projects to owned
797/// keys through `.iter().map(String::from)`, a future
798/// `HashMap::<String, RestartStrategy>::from_iter` that keys off a
799/// borrowed-iteration axis where dereferencing the strategy would force
800/// an unnecessary `Copy` at every step, the future wasm-operator's
801/// per-supervisor `strategies.iter().map(String::from).collect()`
802/// diagnostic emit whose iteration axis is borrowed by construction —
803/// reaches the same four-arm lifted
804/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
805/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
806/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
807/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const the
808/// paired [`std::fmt::Display`], [`AsRef<str>`],
809/// [`RestartStrategy::as_str`], and the three other trait-idiomatic
810/// forward-projection impls
811/// ([`From<RestartStrategy> for &'static str`],
812/// [`From<&RestartStrategy> for &'static str`],
813/// [`From<RestartStrategy> for String`]) already return.
814///
815/// Opens the trait-idiomatic *borrowed-input, owned-`String` output*
816/// forward-projection axis on closed-set fieldless typed enums —
817/// first-mover on the 2×2 completion corner, mirror of the
818/// [`crate::supervisor::RestartStrategy`] first-mover position that
819/// opened the paired owned-input owned-`String` axis (7baa18a), the
820/// owned-input owned-`&'static str` axis (523157d), and the paired
821/// [`crate::dep::DepList`] first-mover position that opened the
822/// borrowed-input `&'static str` axis (64aa742). Rust's standard
823/// library does not carry a blanket `impl<T: AsRef<str>> From<&T> for
824/// String` (nor an `impl<T: fmt::Display> From<&T> for String`), so
825/// every closed-set typed enum that carries the paired `AsRef<str>` /
826/// `Display` / `From<Self> for &'static str` / `From<&Self> for
827/// &'static str` / `From<Self> for String` quintuple but not the
828/// borrowed-input owned-[`String`] axis forces every borrowed-input
829/// owned-string call site through a `strategy.as_str().to_owned()` /
830/// `String::from(*strategy)` (with a spurious `Copy`) /
831/// `strategy.to_string()` (through `Display`) detour whose type bounds
832/// have no compile-time link to the substrate primitive.
833///
834/// Deliberately routes through the human-readable
835/// [`RestartStrategy::as_str`] axis — for this enum the wire format
836/// (`PascalCase`, tatara-lisp author surface `:estrategia OneForOne`)
837/// and the diagnostic byte-string share the same vocabulary by
838/// construction (unlike the sibling [`crate::CaixaKind`] enum whose two
839/// axes diverge), so the borrowed-input owned-[`String`] projection
840/// lands byte-identically on both the wire vocabulary the paired
841/// [`serde::Serialize`] derive emits and the diagnostic vocabulary the
842/// [`RestartStrategy::as_str`] helper returns.
843///
844/// The remaining fourteen closed-set typed enums on the caixa
845/// substrate surface (`RestartPolicy`, `CaixaKind`, `CaixaDialeto`,
846/// `DepList`, `PlacementStrategy`, `WitShape`, `RateLimitUnit`,
847/// `PathShapeViolation`, `InvariantKind`, `ArchVerdict`, `Severity`,
848/// `FixSafety`, `Semantic`, `FerriteRuntime`) are the future targets of
849/// this 2×2-completion campaign — each carries the same paired
850/// quintuple that this borrowed-input owned-[`String`] axis extends onto.
851///
852/// Pinned load-bearing by
853/// [`tests::restart_strategy_from_into_borrowed_owned_string_routes_through_as_str_accessor`]
854/// (byte-parity pin against [`RestartStrategy::as_str`] across the
855/// four-arm emit-set through the borrowed-input surface) and
856/// [`tests::restart_strategy_from_into_borrowed_owned_string_agrees_with_paired_axes_on_every_arm`]
857/// (cross-axis partition pin against the paired owned-input owned-
858/// [`String`] [`From<RestartStrategy> for String`] impl, the paired
859/// borrowed-input owned-[`&'static str`] [`From<&RestartStrategy> for
860/// &'static str`] impl, and the sibling [`ToString::to_string`] surface
861/// routed through [`std::fmt::Display`], plus a direct round-trip
862/// witness through [`TryFrom<&str>`] on the owned-[`String`]'s
863/// [`String::as_str`] borrow that closes the two-way
864/// `&Self → String → Self` round-trip on the trait-idiomatic
865/// borrowed-input owned-[`String`] forward + reverse axis pair).
866impl From<&RestartStrategy> for String {
867 fn from(strategy: &RestartStrategy) -> String {
868 strategy.as_str().to_owned()
869 }
870}
871
872/// Trait-idiomatic *owned-input, [`std::borrow::Cow<'static, str>`]
873/// output* forward projection on the M2 OTP-shape sibling-restart
874/// [`RestartStrategy`] closed-set typed enum — extends the substrate-
875/// wide [`std::borrow::Cow<'static, str>`] forward-projection family
876/// opened on [`crate::CaixaKind`] (99c1735) onto the first M2 OTP-
877/// shape closed-set fieldless typed enum peer on the caixa surface
878/// (`:supervisor :estrategia`). Routes byte-for-byte through the
879/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
880/// accessor (via [`std::borrow::Cow::Borrowed`]) so every consumer
881/// that binds a [`RestartStrategy`] through the trait-idiomatic
882/// [`std::borrow::Cow<'static, str>`] axis — a future
883/// `axum::response::IntoResponse` composer whose per-strategy
884/// diagnostic-body typing rules out the sibling [`AsRef<str>`]
885/// borrowed return, a future M4 admission-webhook rejection body
886/// that composes the accepted-strategy enumeration through the same
887/// `RestartStrategy::ALL.iter().map(Cow::from)` shape [`CaixaKind`]
888/// already routes through, a generic `<T: for<'a>
889/// Into<std::borrow::Cow<'static, str>>>`-bound structured-log
890/// emitter on a per-supervisor diagnostic column — reaches the same
891/// four-arm lifted [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`]
892/// / [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
893/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
894/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
895/// the paired [`std::fmt::Display`], [`AsRef<str>`],
896/// [`RestartStrategy::as_str`], and the four
897/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
898/// forward-projection corners already return.
899///
900/// Deliberately returns [`std::borrow::Cow::Borrowed`] rather than
901/// [`std::borrow::Cow::Owned`] — the substrate-primitive
902/// [`RestartStrategy::as_str`] accessor's return carries the
903/// `&'static str` lifetime by construction (each `match` arm resolves
904/// to a [`crate::render::SUPERVISOR_ESTRATEGIA_*`] `pub const &str`
905/// with static lifetime), so the zero-alloc borrowed arm is the
906/// type-correct projection with no runtime allocation.
907///
908/// Rust's standard library carries no blanket `impl<T: AsRef<str>>
909/// From<T> for Cow<'static, str>` (nor an `impl<T: fmt::Display>
910/// From<T> for Cow<'static, str>`), so the paired sibling
911/// [`From<RestartStrategy> for &'static str`],
912/// [`From<RestartStrategy> for String`], [`AsRef<str>`], and
913/// [`std::fmt::Display`] surfaces do not implicitly extend to a
914/// [`Cow<'static, str>`]-bound call site — every such site is forced
915/// through a `Cow::Borrowed(strategy.as_str())` /
916/// `Cow::Owned(strategy.to_string())` open-code whose type bounds
917/// have no compile-time link back to the substrate primitive until
918/// this lift.
919///
920/// First peer to extend the substrate-wide trait-idiomatic
921/// [`std::borrow::Cow<'static, str>`] forward-projection axis off the
922/// top-level [`crate::CaixaKind`] enum (99c1735 owned-input,
923/// d45c409 borrowed-input) onto the wider substrate — the remaining
924/// twelve peers (`RestartPolicy`, `PlacementStrategy`, `RateLimitUnit`,
925/// `DepList`, `CaixaDialeto`, and the outside-`caixa-core` peers
926/// `WitShape`, `PathShapeViolation`, `InvariantKind`, `ArchVerdict`,
927/// `Severity`, `FixSafety`, `Semantic`, `FerriteRuntime`) are the
928/// future targets of this campaign.
929///
930/// Pinned load-bearing by
931/// [`tests::restart_strategy_from_into_static_cow_str_routes_through_as_str_accessor`]
932/// (byte-parity + zero-alloc [`std::borrow::Cow::Borrowed`]-arm pin
933/// against [`RestartStrategy::as_str`] across the four-arm
934/// [`RestartStrategy::ALL`]) and
935/// [`tests::restart_strategy_from_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
936/// (cross-axis partition pin against the paired [`From<RestartStrategy>
937/// for &'static str`], [`From<RestartStrategy> for String`], and
938/// [`ToString`]-through-[`std::fmt::Display`] axes, plus a
939/// `.iter().copied().map(Cow::from)` pipe witness over
940/// [`RestartStrategy::ALL`] that materializes the four-arm accept-set
941/// through the [`Cow<'static, str>`] axis alone and pins the
942/// zero-alloc discipline on every element).
943impl From<RestartStrategy> for std::borrow::Cow<'static, str> {
944 fn from(strategy: RestartStrategy) -> std::borrow::Cow<'static, str> {
945 std::borrow::Cow::Borrowed(strategy.as_str())
946 }
947}
948
949/// Trait-idiomatic *borrowed-input, [`std::borrow::Cow<'static, str>`]
950/// output* forward projection on the M2 OTP-shape sibling-restart
951/// [`RestartStrategy`] closed-set typed enum — the borrowed-input
952/// companion to the paired owned-input
953/// [`From<RestartStrategy> for std::borrow::Cow<'static, str>`] impl
954/// immediately above (7dd28b3). Routes byte-for-byte through the same
955/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
956/// accessor (via [`std::borrow::Cow::Borrowed`]) so every consumer
957/// that holds a `&RestartStrategy` and needs a
958/// [`std::borrow::Cow<'static, str>`] — a
959/// `RestartStrategy::ALL.iter().map(std::borrow::Cow::from).collect::<Vec<_>>()`
960/// per-arm accept-set materializer (whose iterator over
961/// `&'static [RestartStrategy]` yields `&RestartStrategy`, not
962/// `RestartStrategy`, so the paired owned-input
963/// [`From<RestartStrategy> for std::borrow::Cow<'static, str>`] axis
964/// alone forces every call site through an explicit `.copied()` /
965/// dereference / [`Copy`]-bound restatement rather than the direct
966/// trait-idiomatic projection), a future generic
967/// `<T: for<'a> Into<std::borrow::Cow<'static, str>>>`-bound emitter
968/// on a per-strategy diagnostic column that walks the
969/// `iter().map(Into::into)` shape verbatim, the future M4 admission-
970/// webhook rejection body that composes the accepted-strategy
971/// enumeration from an iterated
972/// `RestartStrategy::ALL.iter().map(|s| s.into())` pipe rather than a
973/// per-arm `match s { … }` cascade — reaches the same four-arm lifted
974/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
975/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
976/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
977/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
978/// the paired [`std::fmt::Display`], [`AsRef<str>`],
979/// [`RestartStrategy::as_str`], the four
980/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
981/// forward-projection corners, and the paired owned-input
982/// [`From<RestartStrategy> for std::borrow::Cow<'static, str>`] impl
983/// already return.
984///
985/// Deliberately returns [`std::borrow::Cow::Borrowed`] rather than
986/// [`std::borrow::Cow::Owned`] — the substrate-primitive
987/// [`RestartStrategy::as_str`] accessor's return carries the
988/// `&'static str` lifetime by construction (each `match` arm resolves
989/// to a [`crate::render::SUPERVISOR_ESTRATEGIA_*`] `pub const &str`
990/// with static lifetime), so the zero-alloc borrowed arm is the
991/// type-correct projection with no runtime allocation.
992///
993/// Second peer on the substrate-wide trait-idiomatic
994/// [`std::borrow::Cow<'static, str>`] forward-projection family
995/// opened one commit prior (7dd28b3) on the paired owned-input
996/// [`From<RestartStrategy> for std::borrow::Cow<'static, str>`] impl
997/// — closes the `{Self, &Self}` input-shape corner of the
998/// [`Cow<'static, str>`] axis on the first M2 OTP-shape closed-set
999/// fieldless typed enum peer on the caixa surface, exactly as
1000/// d45c409 closed it on the top-level [`crate::CaixaKind`] one commit
1001/// after the owning half (99c1735) landed. Rust's standard library
1002/// does not carry a blanket `impl<T: AsRef<str>> From<&T> for
1003/// Cow<'static, str>` (nor an `impl<T: fmt::Display> From<&T> for
1004/// Cow<'static, str>`), so every closed-set fieldless typed enum peer
1005/// on the substrate that carries the paired owned-input
1006/// [`Cow<'static, str>`] axis but not the borrowed-input axis forces
1007/// every borrowed-input [`Cow<'static, str>`]-parameterized call site
1008/// through a spurious [`Copy`] deref
1009/// (`std::borrow::Cow::from(*strategy)`) or a
1010/// `std::borrow::Cow::Borrowed(strategy.as_str())` open-code whose
1011/// type bounds have no compile-time link to the substrate primitive.
1012///
1013/// Pinned load-bearing by
1014/// [`tests::restart_strategy_from_borrowed_into_static_cow_str_routes_through_as_str_accessor`]
1015/// (byte-parity + zero-alloc [`std::borrow::Cow::Borrowed`]-arm pin
1016/// against [`RestartStrategy::as_str`] across the four-arm
1017/// [`RestartStrategy::ALL`] through the borrowed-input surface) and
1018/// [`tests::restart_strategy_from_borrowed_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
1019/// (cross-axis partition pin against the paired owned-input
1020/// [`From<RestartStrategy> for std::borrow::Cow<'static, str>`], the
1021/// paired borrowed-input owned-`&'static str`
1022/// [`From<&RestartStrategy> for &'static str`], and the paired
1023/// borrowed-input owned-`String` [`From<&RestartStrategy> for String`]
1024/// impls, plus a `.iter().map(std::borrow::Cow::from)` pipe witness
1025/// over [`RestartStrategy::ALL`] — whose iterator yields
1026/// `&RestartStrategy` by construction, so the borrowed-input
1027/// [`Cow<'static, str>`] axis is what routes the pipe through the
1028/// substrate-primitive [`RestartStrategy::as_str`] accessor with the
1029/// zero-alloc [`Cow::Borrowed`] arm by construction and without a
1030/// spurious [`Copy`] deref).
1031impl From<&RestartStrategy> for std::borrow::Cow<'static, str> {
1032 fn from(strategy: &RestartStrategy) -> std::borrow::Cow<'static, str> {
1033 std::borrow::Cow::Borrowed(strategy.as_str())
1034 }
1035}
1036
1037/// Trait-idiomatic *owned-input, [`Box<str>`] output* forward
1038/// projection on the M2 OTP-shape sibling-restart [`RestartStrategy`]
1039/// closed-set fieldless typed enum — opens a fresh
1040/// substrate-wide `Box<str>` forward-projection campaign tier on the
1041/// first M2 OTP-shape closed-set fieldless typed enum peer on the
1042/// caixa surface, immediately after the paired `Cow<'static, str>`
1043/// axis (7dd28b3 / ee577fd) closed the
1044/// `{Self, &Self} × {&'static str, String, Cow<'static, str>}` 2×3
1045/// corner on this enum. Routes byte-for-byte through the
1046/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
1047/// accessor via [`Box::<str>::from`] on the returned `&'static str`,
1048/// so every consumer that binds a
1049/// `let key: Box<str> = strategy.into();`-shaped call site — a
1050/// per-supervisor metric-key materializer that stashes the strategy
1051/// discriminator in a `Box<str>`-typed heap-owned scalar for cheap
1052/// clone (a shared-nothing per-strategy accept-set the
1053/// `caixa-operator` reconciliation scheduler carries), a future
1054/// admission-webhook rejection body whose per-arm `Box<str>` field
1055/// composes from an owned `RestartStrategy` handle — reaches the
1056/// same four-arm lifted
1057/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
1058/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
1059/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
1060/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
1061/// the sibling
1062/// `{Self, &Self} × {&'static str, String, Cow<'static, str>}`
1063/// forward-projection corner already returns. Rust's standard
1064/// library carries `impl From<&str> for Box<str>` and
1065/// `impl From<String> for Box<str>` but no blanket
1066/// `impl<T: AsRef<str>> From<T> for Box<str>`, so this axis is a
1067/// distinct trait-idiomatic surface that a downstream
1068/// `RestartStrategy → Box<str>` `.into()` reaches through this impl
1069/// and no other — without a
1070/// `Box::from(strategy.as_str())` open-code whose type bounds have
1071/// no compile-time link back to the substrate primitive.
1072///
1073/// Pinned load-bearing by
1074/// [`tests::restart_strategy_from_into_box_str_routes_through_as_str_accessor`]
1075/// (byte-parity pin against [`RestartStrategy::as_str`] across the
1076/// four-arm [`RestartStrategy::ALL`] emit-set on the owned-input
1077/// surface, plus a blanket-derived [`Into`] shape witness).
1078impl From<RestartStrategy> for Box<str> {
1079 fn from(strategy: RestartStrategy) -> Box<str> {
1080 Box::<str>::from(strategy.as_str())
1081 }
1082}
1083
1084/// Trait-idiomatic *borrowed-input, [`Box<str>`] output* forward
1085/// projection on the M2 OTP-shape sibling-restart [`RestartStrategy`]
1086/// closed-set fieldless typed enum — closes the `{Self, &Self}`
1087/// input-shape corner of the substrate-wide `Box<str>`
1088/// forward-projection axis opened one commit prior (69ef45c) on the
1089/// paired owned-input [`From<RestartStrategy> for Box<str>`] impl.
1090/// Routes byte-for-byte through the same substrate-primitive
1091/// [`RestartStrategy::as_str`] `pub const fn` accessor via
1092/// [`Box::<str>::from`] on the returned `&'static str`, so every
1093/// consumer that holds a `&RestartStrategy` and needs a
1094/// [`Box<str>`] — a
1095/// `RestartStrategy::ALL.iter().map(Box::<str>::from).collect::<Vec<_>>()`
1096/// per-arm accept-set materializer (whose iterator over
1097/// `&'static [RestartStrategy]` yields `&RestartStrategy`, not
1098/// `RestartStrategy`, so the paired owned-input
1099/// [`From<RestartStrategy> for Box<str>`] axis alone forces every
1100/// call site through an explicit `.copied()` / dereference /
1101/// [`Copy`]-bound restatement rather than the direct trait-idiomatic
1102/// projection), a per-supervisor metric-key materializer holding
1103/// `&RestartStrategy` through a `caixa-operator` reconciliation
1104/// scheduler's borrow lifetime, a future admission-webhook rejection
1105/// body whose per-arm `Box<str>` field composes from a borrowed
1106/// `&RestartStrategy` handle without a spurious [`Copy`] deref —
1107/// reaches the same four-arm lifted
1108/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
1109/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
1110/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
1111/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
1112/// the paired owned-input [`From<RestartStrategy> for Box<str>`] and
1113/// the sibling
1114/// `{Self, &Self} × {&'static str, String, Cow<'static, str>}`
1115/// forward-projection corner already return.
1116///
1117/// Second peer on the substrate-wide trait-idiomatic
1118/// [`Box<str>`] forward-projection family opened one commit prior
1119/// (69ef45c) on the paired owned-input
1120/// [`From<RestartStrategy> for Box<str>`] impl — closes the
1121/// `{Self, &Self}` input-shape corner of the [`Box<str>`] axis on
1122/// the first M2 OTP-shape closed-set fieldless typed enum peer on
1123/// the caixa surface (`:supervisor :estrategia`), exactly as
1124/// ee577fd closed the paired [`Cow<'static, str>`] axis one commit
1125/// after its owning half (7dd28b3) landed. Rust's standard library
1126/// carries `impl From<&str> for Box<str>` and
1127/// `impl From<String> for Box<str>` but no blanket
1128/// `impl<T: AsRef<str>> From<&T> for Box<str>` (nor a
1129/// `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`), so
1130/// every closed-set fieldless typed enum peer on the substrate that
1131/// carries the paired owned-input `Box<str>` axis but not the
1132/// borrowed-input axis forces every borrowed-input
1133/// `Box<str>`-parameterized call site through a spurious [`Copy`]
1134/// deref (`Box::<str>::from((*strategy).as_str())`) or a
1135/// `Box::<str>::from(strategy.as_str())` open-code whose type bounds
1136/// have no compile-time link back to the substrate primitive.
1137///
1138/// Pinned load-bearing by
1139/// [`tests::restart_strategy_from_borrowed_into_box_str_routes_through_as_str_accessor`]
1140/// (byte-parity pin against [`RestartStrategy::as_str`] across the
1141/// four-arm [`RestartStrategy::ALL`] emit-set on the borrowed-input
1142/// surface, plus a blanket-derived [`Into`] shape witness and a
1143/// cross-axis pin against the paired owned-input
1144/// [`From<RestartStrategy> for Box<str>`] and the sibling
1145/// borrowed-input `{&'static str, String, Cow<'static, str>}`
1146/// return-shape axes).
1147impl From<&RestartStrategy> for Box<str> {
1148 fn from(strategy: &RestartStrategy) -> Box<str> {
1149 Box::<str>::from(strategy.as_str())
1150 }
1151}
1152
1153/// Trait-idiomatic *owned-input, [`std::sync::Arc<str>`] output*
1154/// forward projection on the M2 OTP-shape sibling-restart
1155/// [`RestartStrategy`] closed-set fieldless typed enum — opens the
1156/// substrate-wide [`std::sync::Arc<str>`] forward-projection campaign
1157/// tier on the first M2 OTP-shape closed-set fieldless typed enum peer
1158/// on the caixa surface (`:supervisor :estrategia`), immediately after
1159/// the paired [`Box<str>`] axis (69ef45c / 59ae5dc) closed the
1160/// `{Self, &Self} × {&'static str, String, Cow<'static, str>, Box<str>}`
1161/// 2×4 corner on this enum. Routes byte-for-byte through the
1162/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
1163/// accessor (via [`std::sync::Arc::<str>::from`] on the returned
1164/// `&'static str`), so every consumer that binds a
1165/// [`RestartStrategy`] through the standard-library `.into()` /
1166/// [`From<Self> for std::sync::Arc<str>`] (equivalently
1167/// [`Into<std::sync::Arc<str>>`]) axis — a future admission-webhook
1168/// running under `axum` + `tokio` whose per-arm structured-log field
1169/// crosses an `.await` boundary and demands the [`Sync`] +
1170/// [`Send`]-safe shared-ownership envelope [`std::sync::Arc<str>`]
1171/// provides (the sibling [`Box<str>`] axis's owned-move return-shape
1172/// forces every downstream `.clone()` through a heap allocation, while
1173/// [`std::sync::Arc<str>`]'s reference-counted shared-ownership
1174/// resolves the same `.clone()` through a refcount bump), a future
1175/// wasm-operator's per-supervisor reconciliation scheduler that
1176/// dispatches the same per-strategy diagnostic key onto multiple
1177/// concurrent reconcile-loop tasks holding shared-ownership through
1178/// [`std::sync::Arc<str>`], a future
1179/// `tracing::field::valuable::Value::Str(strategy.into())` structured-
1180/// log recorder whose typing folds a shared-ownership envelope onto
1181/// the span-context axis, a generic
1182/// `<T: Into<std::sync::Arc<str>>>`-bound diagnostic column on a
1183/// shared-ownership per-strategy cache — reaches the same four-arm
1184/// lifted [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
1185/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
1186/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
1187/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
1188/// the sibling
1189/// `{Self, &Self} × {&'static str, String, Cow<'static, str>, Box<str>}`
1190/// forward-projection corner already returns.
1191///
1192/// First-mover on the substrate-wide trait-idiomatic
1193/// [`std::sync::Arc<str>`] forward-projection family — Rust's
1194/// standard library carries `impl From<&str> for std::sync::Arc<str>`
1195/// and `impl From<String> for std::sync::Arc<str>` but no blanket
1196/// `impl<T: AsRef<str>> From<T> for std::sync::Arc<str>` (nor an
1197/// `impl<T: fmt::Display> From<T> for std::sync::Arc<str>`), so every
1198/// closed-set fieldless typed enum on the substrate that carries the
1199/// paired [`AsRef<str>`] / [`std::fmt::Display`] /
1200/// [`From<Self> for &'static str`] / [`From<&Self> for &'static str`] /
1201/// [`From<Self> for String`] / [`From<&Self> for String`] /
1202/// [`From<Self> for Cow<'static, str>`] /
1203/// [`From<&Self> for Cow<'static, str>`] /
1204/// [`From<Self> for Box<str>`] / [`From<&Self> for Box<str>`] decet
1205/// but not the [`std::sync::Arc<str>`] axis forces every
1206/// `std::sync::Arc<str>`-parameterized call site through a
1207/// `std::sync::Arc::<str>::from(strategy.as_str())` open-code (or a
1208/// `std::sync::Arc::<str>::from(String::from(strategy))` two-step
1209/// composition through the owned-`String` axis that allocates
1210/// twice — once into the intermediate `String`, once into the
1211/// [`Arc<str>`] on the `From<String>` conversion) whose type bounds
1212/// have no compile-time link back to the substrate primitive. Opening
1213/// the axis on the first M2 OTP-shape closed-set fieldless typed enum
1214/// peer on the caixa substrate surface establishes the "route through
1215/// `as_str` via [`std::sync::Arc::<str>::from`] on the returned
1216/// `&'static str`" discipline; every future closed-set fieldless
1217/// typed enum peer on the substrate ([`RestartPolicy`],
1218/// [`crate::aplicacao::PlacementStrategy`],
1219/// [`crate::aplicacao::RateLimitUnit`], [`crate::aplicacao::WitShape`],
1220/// [`crate::dep::DepList`], [`crate::dialeto::CaixaDialeto`],
1221/// [`crate::kind::CaixaKind`],
1222/// [`crate::render::PathShapeViolation`], and the outside-`caixa-core`
1223/// peers `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`,
1224/// `Semantic`, `FerriteRuntime`) is a future target of the campaign,
1225/// tracking the same 14-peer emit-set every prior projection tier
1226/// ([`&'static str`], [`String`], [`Cow<'static, str>`], [`Box<str>`])
1227/// converged onto.
1228///
1229/// Peer of the sibling [`Box<str>`] forward-projection first-mover
1230/// (69ef45c) — same "opens a new substrate-wide projection tier"
1231/// discipline, extended onto the [`std::sync::Arc<str>`] axis whose
1232/// shared-ownership + [`Sync`] + [`Send`] contract is the distinct
1233/// value the [`Box<str>`] axis's owned-move return-shape cannot
1234/// provide.
1235///
1236/// Pinned load-bearing by
1237/// [`tests::restart_strategy_from_into_arc_str_routes_through_as_str_accessor`]
1238/// (byte-parity pin against [`RestartStrategy::as_str`] across the
1239/// four-arm [`RestartStrategy::ALL`] emit-set on the owned-input
1240/// surface, plus a blanket-derived [`Into`] shape witness and cross-
1241/// axis byte-parity pins against the sibling owned-input
1242/// `{&'static str, String, Cow<'static, str>, Box<str>}` return-shape
1243/// axes).
1244impl From<RestartStrategy> for std::sync::Arc<str> {
1245 fn from(strategy: RestartStrategy) -> std::sync::Arc<str> {
1246 std::sync::Arc::<str>::from(strategy.as_str())
1247 }
1248}
1249
1250/// Trait-idiomatic *borrowed-input, [`std::sync::Arc<str>`] output*
1251/// forward projection on the M2 OTP-shape sibling-restart
1252/// [`RestartStrategy`] closed-set fieldless typed enum — closes the
1253/// `{Self, &Self}` input-shape corner of the [`std::sync::Arc<str>`]
1254/// forward-projection axis on the first M2 OTP-shape closed-set
1255/// fieldless typed enum peer on the caixa surface
1256/// (`:supervisor :estrategia`), companion to the paired owned-input
1257/// [`From<RestartStrategy> for std::sync::Arc<str>`] impl one commit
1258/// prior (bca2ec8). Routes byte-for-byte through the
1259/// substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
1260/// accessor (via [`std::sync::Arc::<str>::from`] on the returned
1261/// `&'static str`), so every consumer that binds a
1262/// [`&RestartStrategy`] through the standard-library `.into()` /
1263/// [`From<&Self> for std::sync::Arc<str>`] (equivalently
1264/// [`Into<std::sync::Arc<str>>`]) axis — a future admission-webhook's
1265/// per-request borrowed-`&RestartStrategy` handle rendering a per-arm
1266/// `Sync` + `Send`-safe structured-log field across an `.await`
1267/// boundary through a `<T: Into<std::sync::Arc<str>>>`-bound
1268/// diagnostic-column dispatch, a future wasm-operator's per-
1269/// supervisor reconciliation pipeline whose
1270/// `.iter().map(std::sync::Arc::<str>::from)` collector reaches into
1271/// the shared-ownership per-strategy key without a spurious [`Copy`]
1272/// deref (which would only be reachable through the owned-input
1273/// [`From<RestartStrategy> for std::sync::Arc<str>`] axis by first
1274/// calling `.copied()` on the iterator), a future
1275/// `<T: Into<std::sync::Arc<str>>>`-bound `tracing`-span attributes
1276/// collector recording a borrowed-`&RestartStrategy` per-arm field
1277/// onto the parent span's shared-ownership context — reaches the
1278/// same four-arm lifted
1279/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
1280/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
1281/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
1282/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`] const
1283/// the paired owned-input
1284/// [`From<RestartStrategy> for std::sync::Arc<str>`] impl and the
1285/// sibling `{&'static str, String, Cow<'static, str>, Box<str>}`
1286/// forward-projection corner already return.
1287///
1288/// Second peer on the substrate-wide trait-idiomatic
1289/// [`std::sync::Arc<str>`] forward-projection family opened one
1290/// commit prior (bca2ec8) on the paired owned-input
1291/// [`From<RestartStrategy> for std::sync::Arc<str>`] impl — closes
1292/// the `{Self, &Self}` input-shape corner of the
1293/// [`std::sync::Arc<str>`] axis on the first M2 OTP-shape closed-set
1294/// fieldless typed enum peer on the caixa surface, exactly as
1295/// 59ae5dc closed the paired [`Box<str>`] axis one commit after its
1296/// owning half (69ef45c) landed. Rust's standard library carries
1297/// `impl From<&str> for std::sync::Arc<str>` and
1298/// `impl From<String> for std::sync::Arc<str>` but no blanket
1299/// `impl<T: AsRef<str>> From<&T> for std::sync::Arc<str>` (nor a
1300/// `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`), so
1301/// every closed-set fieldless typed enum peer on the substrate that
1302/// carries the paired owned-input [`std::sync::Arc<str>`] axis but
1303/// not the borrowed-input axis forces every borrowed-input
1304/// [`std::sync::Arc<str>`]-parameterized call site through a
1305/// spurious [`Copy`] deref
1306/// (`std::sync::Arc::<str>::from((*strategy).as_str())`) or a
1307/// `std::sync::Arc::<str>::from(strategy.as_str())` open-code whose
1308/// type bounds have no compile-time link back to the substrate
1309/// primitive.
1310///
1311/// Pinned load-bearing by
1312/// [`tests::restart_strategy_from_borrowed_into_arc_str_routes_through_as_str_accessor`]
1313/// (byte-parity pin against [`RestartStrategy::as_str`] across the
1314/// four-arm [`RestartStrategy::ALL`] emit-set on the borrowed-input
1315/// surface, plus a blanket-derived [`Into`] shape witness and a
1316/// cross-axis pin against the paired owned-input
1317/// [`From<RestartStrategy> for std::sync::Arc<str>`] and the sibling
1318/// borrowed-input `{&'static str, String, Cow<'static, str>,
1319/// Box<str>}` return-shape axes).
1320impl From<&RestartStrategy> for std::sync::Arc<str> {
1321 fn from(strategy: &RestartStrategy) -> std::sync::Arc<str> {
1322 std::sync::Arc::<str>::from(strategy.as_str())
1323 }
1324}
1325
1326/// Substrate-canonical [`AsRef<[u8]>`] byte-view projection on the M2
1327/// OTP-shape sibling-restart [`RestartStrategy`] closed-set fieldless
1328/// typed enum — routes byte-for-byte through the substrate-primitive
1329/// [`RestartStrategy::as_str`] `pub const fn` accessor via
1330/// [`str::as_bytes`] on the returned `&'static str`, so any future
1331/// consumer that binds a [`RestartStrategy`] through a standard-library
1332/// `<T: AsRef<[u8]>>` trait bound reaches the same four-arm lifted
1333/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
1334/// [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
1335/// [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
1336/// [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`]
1337/// `PascalCase` wire byte-string emit-set the paired sibling
1338/// [`AsRef<str>`] (5b828ed) / [`std::fmt::Display`] /
1339/// [`RestartStrategy::as_str`] str-view surfaces and every
1340/// `{Self, &Self} × {&'static str, String, Cow<'static, str>, Box<str>,
1341/// std::sync::Arc<str>}` reverse-projection corner already return —
1342/// through the byte-view axis, which the str-view axes cannot express.
1343///
1344/// Rust's standard library carries `impl AsRef<[u8]> for str` and
1345/// `impl AsRef<[u8]> for String`, so the two-hop composition
1346/// `strategy.as_str().as_bytes()` (or, equivalently,
1347/// `AsRef::<str>::as_ref(&strategy).as_bytes()`) is reachable through
1348/// the pre-existing str-view axis alone. But that two-hop shape has no
1349/// compile-time link back to the byte-projection axis, forces every
1350/// downstream `<T: AsRef<[u8]>>`-bound consumer to open-code the
1351/// two-hop composition at every call site, and admits a silent split
1352/// whenever a future call site takes a sibling reverse-projection axis
1353/// whose `.as_bytes()` byte-tail carries no compile-time byte-view
1354/// surface (`Display` returns a formatter, `String` / `Box<str>` /
1355/// `Arc<str>` allocate). The lifted single-hop impl closes the
1356/// byte-view axis so every future `<T: AsRef<[u8]>>`-bound consumer
1357/// reaches the substrate primitive through one trait dispatch, and
1358/// every future arm addition (an OTP-`rest_for_all` fifth arm the
1359/// theory
1360/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
1361/// might reach for once the four canonical OTP strategies stop covering
1362/// the substrate's discovered load-shape) grows the byte-view axis
1363/// through one edit on the substrate-primitive `as_str` accessor, not a
1364/// coordinated rewrite across every future `<T: AsRef<[u8]>>`-bound
1365/// consumer's arm-set.
1366///
1367/// The primary compounding target is the same `caixa-lacre` BLAKE3
1368/// content-address closure the peer [`crate::CaixaKind`] (69d8d86),
1369/// [`crate::dialeto::CaixaDialeto`] (8151347),
1370/// [`crate::dep::DepList`] (05ffaca),
1371/// [`crate::aplicacao::PlacementStrategy`] (daa8705), and
1372/// [`crate::aplicacao::RateLimitUnit`] (4867e0f) `AsRef<[u8]>` impls
1373/// open onto: [`blake3::hash`] and [`blake3::Hasher::update`] both bind
1374/// their input through `impl AsRef<[u8]>`, so any future per-supervisor
1375/// content-address tag that folds an `:estrategia` discriminator
1376/// byte-tag into the [`crate::Lacre`] closure (a hypothetical
1377/// `hasher.update(estrategia);`-shape composition partitioning the
1378/// four OTP restart-topology closures at content-address time so
1379/// downstream `Lacre` consumers key per-strategy reconciliation caches
1380/// off the typed discriminator rather than the sibling `&'static str`
1381/// wire scalar) reaches the substrate-primitive `as_str` accessor
1382/// through this impl and no other.
1383///
1384/// Opens the trait-idiomatic byte-view axis on the first M2 OTP-shape
1385/// closed-set fieldless typed enum peer on the caixa surface
1386/// (`:supervisor :estrategia`), extending the substrate-wide byte-view
1387/// campaign the sibling [`crate::CaixaKind`] first-mover (69d8d86)
1388/// opened onto the fifth in-caixa-core enum peer. The remaining
1389/// in-caixa-core closed-set fieldless typed-enum peers
1390/// ([`RestartPolicy`], [`crate::aplicacao::WitShape`],
1391/// [`crate::upgrade::UpgradeInstruction`],
1392/// [`crate::render::PathShapeViolation`]) each carry the same
1393/// [`AsRef<str>`] + `pub const fn as_str` substrate-primitive accessor
1394/// discipline, so a future extension of the byte-view axis onto each
1395/// peer reaches through one impl per enum keyed to that peer's
1396/// substrate-primitive accessor.
1397///
1398/// Pinned load-bearing by
1399/// [`tests::restart_strategy_as_ref_bytes_routes_through_as_str_accessor`]
1400/// (fail-before-pass-after byte-parity pin against
1401/// [`RestartStrategy::as_str`] `.as_bytes()` across the four-arm
1402/// [`RestartStrategy::ALL`] emit-set, cross-axis witness against the
1403/// paired str-view [`AsRef<str>`] / [`std::fmt::Display`] /
1404/// [`RestartStrategy::as_str`] axes' `.as_bytes()` byte-tails,
1405/// cross-axis witness against the paired reverse-projection
1406/// `{&'static str, String, Cow<'static, str>, Box<str>,
1407/// std::sync::Arc<str>}` return-shape axes' `.as_bytes()` byte-tails,
1408/// a `<T: AsRef<[u8]>>`-bound-consumer witness that a generic
1409/// byte-input function accepts a [`RestartStrategy`] directly through
1410/// the trait bound, and a `blake3::Hasher::update`-shape byte-input
1411/// surface witness routed through the `<T: AsRef<[u8]>>`-bound
1412/// consumer axis to reach the caixa-lacre compounding target). Any
1413/// future silent detour that routes the byte-view impl off the
1414/// substrate-primitive [`RestartStrategy::as_str`] accessor (a per-arm
1415/// inline `b"OneForOne".as_slice()`-shaped re-inlining that opens a
1416/// compile-time link to the un-lifted arm-literal, a swap onto the
1417/// kebab-case [`gen_platform::Discriminant`] catalog identity that
1418/// would collide the wire axis with the dispatcher-catalog axis) trips
1419/// at caixa-core test time rather than at a downstream byte-consumer's
1420/// silent split.
1421impl AsRef<[u8]> for RestartStrategy {
1422 fn as_ref(&self) -> &[u8] {
1423 self.as_str().as_bytes()
1424 }
1425}
1426
1427/// Trait-idiomatic *owned-input, owned-`Vec<u8>` output* byte-owned
1428/// reverse projection on the first M2 OTP-shape closed-set fieldless
1429/// typed enum peer on the caixa surface ([`RestartStrategy`]) — the
1430/// byte-mirror of the [`From<RestartStrategy> for String`] str-owned
1431/// reverse-projection axis and the owned-`Vec<u8>` reverse-projection
1432/// sibling of the paired [`AsRef<[u8]>`] borrowed byte-view axis
1433/// (cd4c4e0) lifted on this same enum. Routes byte-for-byte through
1434/// the substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
1435/// accessor via [`str::as_bytes`] + [`slice::to_vec`] so every
1436/// consumer that binds a [`RestartStrategy`] through the standard-
1437/// library `impl From<RestartStrategy> for Vec<u8>` axis
1438/// (equivalently `<T: Into<Vec<u8>>>`) — a future
1439/// [`std::io::Write::write_all`]-shape per-supervisor audit-log byte-
1440/// sink whose input parameter is an owned [`Vec<u8>`] payload, a
1441/// future `bytes::Bytes::from(Vec::<u8>::from(strategy))` composer
1442/// folding the per-arm sibling-restart-topology byte-tag into the
1443/// [`bytes::Bytes`] framing surface, a future
1444/// `hasher.update(&Vec::<u8>::from(strategy))`-shape BLAKE3 content-
1445/// address closure that needs the owned byte-tail buffered before
1446/// folding into the [`crate::Lacre`] closure body, a future per-
1447/// strategy protobuf/CBOR/msgpack payload composer whose framer takes
1448/// an owned [`Vec<u8>`] rather than a borrowed byte-slice — reaches
1449/// the substrate primitive through one trait dispatch rather than an
1450/// open-coded per-call-site `strategy.as_str().as_bytes().to_vec()`
1451/// composition whose type bounds have no compile-time link back to
1452/// the substrate primitive.
1453///
1454/// Extends the substrate-wide trait-idiomatic byte-owned reverse-
1455/// projection axis onto the first M2-OTP-shape closed-set fieldless
1456/// typed-enum peer, matching the trajectory the first-mover
1457/// [`crate::CaixaKind`] `From<{Self, &Self}> for Vec<u8>` lift
1458/// (b245fd6), the second-mover [`crate::dialeto::CaixaDialeto`] lift
1459/// (4cceaf5), and the third-mover [`crate::dep::DepList`] lift
1460/// (e974ca2) established across the caixa-core-internal tier. Every
1461/// future arm addition (an OTP-`rest_for_all` fifth arm the theory
1462/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
1463/// might reach for once the four canonical OTP strategies stop
1464/// covering the substrate's discovered load-shape) grows the byte-
1465/// owned axis through one edit on the substrate-primitive
1466/// [`RestartStrategy::as_str`] accessor, mirroring the discipline the
1467/// paired [`AsRef<[u8]>`] borrowed byte-view axis campaign already
1468/// tracked across every closed-set fieldless typed enum peer on the
1469/// substrate.
1470///
1471/// Pinned load-bearing by
1472/// [`tests::restart_strategy_from_into_owned_vec_bytes_routes_through_as_str_accessor`]
1473/// (byte-parity pin against [`RestartStrategy::as_str`] across the
1474/// four-arm [`RestartStrategy::ALL`] emit-set binding the byte-owned
1475/// reverse-projection axis against the paired [`AsRef<[u8]>`]
1476/// borrowed byte-view axis and the str-owned reverse-projection
1477/// family (`String`, `Cow<'static, str>`, `Box<str>`,
1478/// `std::sync::Arc<str>`) `.into_bytes()` / `.as_bytes().to_vec()`
1479/// byte-tails, a `<T: Into<Vec<u8>>>`-bound generic-consumer witness,
1480/// and a `std::io::Write::write_all`-shape owned-byte-sink surface
1481/// witness on both owned and borrowed input shapes).
1482impl From<RestartStrategy> for Vec<u8> {
1483 fn from(strategy: RestartStrategy) -> Vec<u8> {
1484 strategy.as_str().as_bytes().to_vec()
1485 }
1486}
1487
1488/// Trait-idiomatic *borrowed-input, owned-`Vec<u8>` output* byte-
1489/// owned reverse projection on the first M2 OTP-shape closed-set
1490/// fieldless typed enum peer on the caixa surface
1491/// ([`RestartStrategy`]) — the borrowed-input peer of
1492/// [`From<RestartStrategy> for Vec<u8>`], closing the
1493/// `{Self, &Self} → Vec<u8>` pair on the byte-owned reverse-projection
1494/// axis in one lift. Routes byte-for-byte through the substrate-
1495/// primitive [`RestartStrategy::as_str`] `pub const fn` accessor so
1496/// every consumer that holds a borrowed [`&RestartStrategy`] and
1497/// needs an owned [`Vec<u8>`] — a future
1498/// `.iter().map(Vec::<u8>::from).collect()` pipe over
1499/// `&[RestartStrategy]` (whose iterator yields `&RestartStrategy`,
1500/// not `RestartStrategy`, so the owned-input axis alone forces every
1501/// call site through an explicit `.copied()` / spurious [`Copy`]
1502/// deref restatement rather than the direct trait-idiomatic
1503/// projection), a future admission-webhook rejection body composer
1504/// that walks [`RestartStrategy::ALL`] through an `Into<Vec<u8>>`-
1505/// bound per-arm byte-writer to surface the accepted `:estrategia`
1506/// set — reaches the substrate primitive through one trait dispatch
1507/// rather than a `Vec::<u8>::from(*strategy)` spurious-`Copy`-deref
1508/// restatement.
1509impl From<&RestartStrategy> for Vec<u8> {
1510 fn from(strategy: &RestartStrategy) -> Vec<u8> {
1511 strategy.as_str().as_bytes().to_vec()
1512 }
1513}
1514
1515/// Trait-idiomatic *borrowed byte-slice input* reverse projection on the
1516/// first M2-OTP-shape closed-set fieldless typed enum peer on the caixa
1517/// surface ([`RestartStrategy`]) — the byte-view mirror of the str-view
1518/// reverse-projection axis carried by the paired
1519/// [`TryFrom<&str> for RestartStrategy`] impl (which routes through the
1520/// substrate-primitive [`RestartStrategy::from_wire`] `Option<Self>`
1521/// accessor on the four-arm `PascalCase` accept-set the sibling
1522/// [`RestartStrategy::as_str`] emitter returns). Routes byte-for-byte
1523/// through the standard-library [`std::str::from_utf8`] UTF-8 validator
1524/// and then through [`RestartStrategy::from_wire`] so every consumer that
1525/// holds a borrowed [`&[u8]`] and needs to project it back into a typed
1526/// [`RestartStrategy`] — a future `bytes::Bytes::as_ref()`-fed reader
1527/// that parses a per-supervisor `:estrategia` `PascalCase` wire scalar
1528/// from an already-borrowed framing byte-tail (a
1529/// `tracing::field::valuable::Value::Bytes` recorder on the future
1530/// wasm-operator's per-supervisor sibling-restart-strategy diagnostic
1531/// emission path, a future audit-report re-loader binding a prior
1532/// [`RestartStrategy::as_str`] output from a mmap'd byte-slice back
1533/// through the typed enum for cross-run comparison), a future M4
1534/// `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook rejection
1535/// body that reads a `spec.estrategia` field off a raw HTTP body byte-
1536/// slice before UTF-8 validation commits allocation, a future generic
1537/// `<T: for<'a> TryFrom<&'a [u8]>>`-bound loader over any of the
1538/// substrate's closed-set typed enums — reaches the same four-arm
1539/// `PascalCase` wire accept-set the sibling method-named
1540/// [`RestartStrategy::from_wire`] resolver and the paired trait-idiomatic
1541/// [`TryFrom<&str>`] axis already resolve against, rather than an open-
1542/// coded per-call-site
1543/// `std::str::from_utf8(bytes).ok().and_then(RestartStrategy::from_wire)`
1544/// composition or a
1545/// `<RestartStrategy as TryFrom<&str>>::try_from(std::str::from_utf8(bytes)?)`
1546/// two-hop shape whose type bounds have no compile-time link to the
1547/// substrate primitive.
1548///
1549/// Extends the substrate-wide trait-idiomatic *byte-view reverse-
1550/// projection* family — opened on the structurally most fundamental
1551/// closed-set fieldless typed enum peer ([`crate::CaixaKind`], commit
1552/// 18d1940), extended onto the second caixa-core-internal peer
1553/// ([`crate::CaixaDialeto`], commit d102cb8) and the third
1554/// ([`crate::dep::DepList`], commit b8f25d5) — onto the first
1555/// M2-OTP-shape supervisor-slot closed-set fieldless typed enum peer,
1556/// tracking the "route through `from_wire` via `std::str::from_utf8`"
1557/// discipline the first-mover established. Rust's standard library
1558/// carries no blanket
1559/// `impl<T: for<'a> TryFrom<&'a str>> TryFrom<&[u8]> for T`, so a two-
1560/// hop composition through [`std::str::from_utf8`] + the paired
1561/// [`TryFrom<&str>`] axis is reachable at every call site but has no
1562/// compile-time link back to the byte-view reverse-projection axis.
1563/// Every remaining closed-set fieldless typed enum peer on the substrate
1564/// ([`RestartPolicy`], [`crate::aplicacao::PlacementStrategy`],
1565/// [`crate::aplicacao::RateLimitUnit`], [`crate::aplicacao::WitShape`],
1566/// and the outside-`caixa-core` peers `PathShapeViolation`,
1567/// `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`, `Semantic`,
1568/// `FerriteRuntime`) is a future target of the campaign, mirroring the
1569/// trajectory the closed byte-owned reverse-projection family walked
1570/// arm-by-arm onto each peer.
1571///
1572/// `type Error = ()` matches the sibling [`RestartStrategy::from_wire`]'s
1573/// `Option<Self>` return-shape's deliberate deferral of error typing and
1574/// the paired trait-idiomatic [`TryFrom<&str>`] axis's unit-error shape —
1575/// the caller picks the diagnostic form appropriate for its use site (a
1576/// future `feira supervisor --estrategia …` arg-parse composes its own
1577/// per-verb "unknown strategy: <arg> — accepted: {…}" message enumerating
1578/// [`RestartStrategy::WIRE_NAMES`]; a future admission-webhook rejection
1579/// body wraps the `Err(())` outcome with the accepted-set enumeration for
1580/// operator diagnostics; a `Result::map_err` at the call site lifts the
1581/// unit-error to a per-verb error type). Two rejection paths route
1582/// through the single unit-error: an invalid UTF-8 byte-sequence
1583/// ([`std::str::from_utf8`] returns `Err`) and a valid UTF-8 byte-string
1584/// that falls outside the four-arm `PascalCase` accept-set
1585/// ([`RestartStrategy::from_wire`] returns `None`) — both collapse onto
1586/// `Err(())` so the trait signature stays consistent with the sibling
1587/// str-view reverse axis, and a caller that needs to distinguish the two
1588/// failure modes composes [`std::str::from_utf8`] +
1589/// [`RestartStrategy::from_wire`] explicitly.
1590///
1591/// Pinned load-bearing by
1592/// [`tests::restart_strategy_try_from_bytes_routes_through_from_wire_accessor`]
1593/// (byte-parity pin against [`RestartStrategy::from_wire`] across the
1594/// four-arm [`RestartStrategy::ALL`] accept-set on the borrowed byte-
1595/// slice surface, plus a cross-axis witness that the byte-view reverse
1596/// projection agrees with the paired [`TryFrom<&str>`] str-view reverse
1597/// axis on every accepted arm) and
1598/// [`tests::restart_strategy_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
1599/// (rejection witness against silent accept-set widening on both the
1600/// non-UTF-8 byte-sequence rejection path and the unknown-wire-vocabulary
1601/// rejection path — the latter includes the sibling kebab-case
1602/// dispatcher-catalog byte-strings on the two-axis wire/catalog split so
1603/// a caller that confuses the two axes trips here rather than at a
1604/// downstream K8s-CR round-trip miss).
1605impl TryFrom<&[u8]> for RestartStrategy {
1606 type Error = ();
1607
1608 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
1609 std::str::from_utf8(bytes)
1610 .ok()
1611 .and_then(Self::from_wire)
1612 .ok_or(())
1613 }
1614}
1615
1616/// Per-child restart policy.
1617///
1618/// Permanent / Temporary / Transient match Erlang/OTP semantics 1:1.
1619#[derive(
1620 Serialize,
1621 Deserialize,
1622 Debug,
1623 Clone,
1624 Copy,
1625 PartialEq,
1626 Eq,
1627 Hash,
1628 gen_platform::TypedDispatcher,
1629 gen_platform::Discriminant,
1630 gen_platform::IsVariant,
1631 gen_platform::FromStrKind,
1632)]
1633pub enum RestartPolicy {
1634 /// Always restart the child, regardless of how it died. Used for
1635 /// long-running services that must always be up.
1636 Permanent,
1637 /// Never restart. Used for one-shot work whose completion is
1638 /// itself the success signal (`oneShot` triggers map here).
1639 Temporary,
1640 /// Restart only when the child died *abnormally* (non-zero exit
1641 /// or unhandled exception). A clean exit completes the child.
1642 Transient,
1643}
1644
1645impl Default for RestartPolicy {
1646 fn default() -> Self {
1647 // Route the [`Default for RestartPolicy`] impl's return arm through
1648 // the substrate-canonical [`SUPERVISOR_CHILD_RESTART_DEFAULT`] typed
1649 // `pub const` rather than a raw `Self::Permanent` arm — one source
1650 // of truth for the Erlang/OTP-canonical `permanent` worker-child
1651 // default across the two production consumers that currently
1652 // dispatch on it (this impl at the [`RestartPolicy::default`] call
1653 // and the serde-side `#[serde(default)]` on
1654 // [`ChildSpec::restart`] that resolves an author-omitted
1655 // `:children :restart` slot through `RestartPolicy::default()`).
1656 // Peer of the sibling per-`:supervisor` axis
1657 // [`Default for RestartStrategy`] → [`SUPERVISOR_ESTRATEGIA_DEFAULT`]
1658 // route (95ffacc) — the two impls now share one substrate-primitive
1659 // lift discipline, so any future coherent rebrand of the OTP-shape
1660 // supervisor+child default set migrates through typed constants in
1661 // lockstep instead of splitting a lifted supervisor half against
1662 // an open-coded child half. Pinned by
1663 // `restart_policy_default_routes_through_lifted_default` +
1664 // `child_spec_serde_default_restart_routes_through_lifted_default`
1665 // in the tests module.
1666 SUPERVISOR_CHILD_RESTART_DEFAULT
1667 }
1668}
1669
1670impl RestartPolicy {
1671 /// Exhaustive iteration surface for every consumer that walks the
1672 /// closed three-arm [`RestartPolicy`] discriminator set (the future
1673 /// M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
1674 /// per-child admission-webhook rejection body naming the accepted-
1675 /// `:restart` list, a future `feira supervisor --restart …` CLI
1676 /// arg-parse's "did you mean" hint via a [`Self::from_wire`]-scan
1677 /// over the slice, the future `feira app graph` per-child restart
1678 /// column, any future round-trip fuzz harness that sweeps every
1679 /// arm). A future arm addition (an OTP-`intrinsic` fourth arm the
1680 /// theory
1681 /// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
1682 /// might reach for once the three canonical OTP restart policies
1683 /// stop covering the substrate's discovered load-shape) extends
1684 /// this slice as one edit and every consumer picks up the new entry
1685 /// by construction; the compiler-checked exhaustiveness on the
1686 /// sibling method `match` arms ([`Self::as_str`] / [`Self::from_wire`])
1687 /// is the build-time guarantee that no arm forgets to grow.
1688 ///
1689 /// Peer of the sibling closed-set typed enums'
1690 /// [`RestartStrategy::ALL`] (4eec29c) /
1691 /// [`crate::CaixaKind::ALL`] (6b1f4fb) /
1692 /// [`crate::aplicacao::PlacementStrategy::ALL`] (18c7342) /
1693 /// [`crate::aplicacao::RateLimitUnit::ALL`] (6bce03d) /
1694 /// [`crate::dep::DepList::ALL`] (45ee563) exhaustive-iteration
1695 /// surfaces — the sixth (and the third and final M2 OTP-shape)
1696 /// closed-set typed enum on the caixa surface to converge onto the
1697 /// same one-canonical-arm-list-per-enum discipline. Sibling axis to
1698 /// the peer [`RestartStrategy::ALL`] on the per-supervisor
1699 /// sibling-restart-strategy axis; this closes the per-child
1700 /// restart-decision-policy axis on the same M2 `:supervisor` slot.
1701 pub const ALL: &'static [Self] = &[Self::Permanent, Self::Temporary, Self::Transient];
1702
1703 /// Substrate-canonical exhaustive accept-set on the [`RestartPolicy`]
1704 /// `PascalCase` wire byte-string axis — the closed three-arm roster
1705 /// of every byte-string [`Self::as_str`] returns, routed byte-for-byte
1706 /// through the paired
1707 /// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
1708 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
1709 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] lifted
1710 /// `pub const` roster the [`Self::as_str`] emitter (and the
1711 /// [`std::fmt::Display`] impl / `Serialize` derive routed through it)
1712 /// walks — and byte-for-byte the same three strings the un-`rename`d
1713 /// `Serialize` derive emits under the paired
1714 /// [`crate::render::SUPERVISOR_CHILD_KEY_RESTART`] tag key on every
1715 /// JSON / YAML CR round-trip.
1716 ///
1717 /// Peer of the sibling [`crate::CaixaKind::WIRE_NAMES`] (bd708bd)
1718 /// roster on the top-level typed-kind discriminator's `PascalCase`
1719 /// wire byte-string axis, the sibling
1720 /// [`RestartStrategy::WIRE_NAMES`] (3033f45) roster on the per-
1721 /// supervisor sibling-restart-strategy axis (the first M2 OTP-shape
1722 /// closed-set typed enum to converge onto the paired-roster
1723 /// discipline), the sibling
1724 /// [`crate::aplicacao::PlacementStrategy::WIRE_NAMES`] (3e5b194)
1725 /// roster on the first M3 mesh-shape distribution-strategy closed-
1726 /// set typed enum, and the sibling
1727 /// [`crate::upgrade::UpgradeInstruction::WIRE_FORMS`] (cc42c0e) /
1728 /// [`crate::upgrade::UpgradeInstruction::LISP_FORMS`] (1898d77)
1729 /// rosters on the OTP-appup discriminator's two-axis roster split —
1730 /// the same closed-set exhaustive-accept-set roster discipline
1731 /// extended here onto the second and final M2 OTP-shape sibling-
1732 /// enum on the caixa surface, closing the per-child restart-decision-
1733 /// policy axis paired with the peer [`RestartStrategy::WIRE_NAMES`]
1734 /// per-supervisor sibling-restart-strategy axis on the same M2
1735 /// `:supervisor` slot.
1736 ///
1737 /// Downstream consumers of the closed accepted-wire-form set — a
1738 /// future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR admission-
1739 /// webhook rejection body enumerating the accepted JSON `:restart`
1740 /// values verbatim (as distinct from the kebab-case dispatcher-
1741 /// catalog enumeration [`Self::discriminant`] serves, whose per-arm
1742 /// form `"permanent"` / `"temporary"` / `"transient"` structurally
1743 /// disagrees with the wire byte-string these `PascalCase` entries
1744 /// carry — the split the sibling
1745 /// [`tests::restart_policy_display_matches_serialized_wire_byte_string`]
1746 /// pin already makes load-bearing), a future `feira supervisor
1747 /// --restart …` CLI-side "did you mean" hint whose candidate-list
1748 /// must byte-match the wire form the operator's per-child dispatch
1749 /// keys off, a future `feira app graph` per-child `:restart`-
1750 /// histogram column that renders zero-count arms, a future
1751 /// `caixa-operator` per-reconcile-step diagnostic log line
1752 /// enumerating accepted wire forms on an unknown-policy rejection,
1753 /// a future
1754 /// `tracing::field::valuable::Value::List` structured-log accepted-
1755 /// wire-form emit — now reach for one lifted substrate-primitive
1756 /// roster rather than open-coding a three-string array-literal
1757 /// (`["Permanent", "Temporary", "Transient"]`) whose arm-set has no
1758 /// compile-time link back to the typed [`RestartPolicy`] enum. A
1759 /// future arm addition (an OTP-`intrinsic` fourth arm the theory
1760 /// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
1761 /// might reach for once the three canonical OTP restart policies
1762 /// stop covering the substrate's discovered load-shape) extends
1763 /// this roster as a single edit — paired with the [`Self::as_str`]
1764 /// match's compiler-checked exhaustiveness on the new arm — and
1765 /// every consumer picks up the new wire form by construction rather
1766 /// than a coordinated array-literal rewrite across every downstream
1767 /// site.
1768 ///
1769 /// Length is pinned load-bearing at `RestartPolicy::ALL.len()`
1770 /// (three) by
1771 /// [`tests::restart_policy_wire_names_covers_every_arm`], every
1772 /// variant's [`Self::as_str`] projection is pinned to a member of
1773 /// the roster so a silent skew between the emitter's arm-set and
1774 /// this const's arm-set trips at caixa-core test time rather than at
1775 /// a downstream consumer's accepted-set enumeration miss, and every
1776 /// entry is further pinned to open with an ASCII uppercase byte so
1777 /// a silent collapse of the `PascalCase` wire-form axis with the
1778 /// peer kebab-case dispatcher-catalog axis (an entry byte-identical
1779 /// to a sibling [`Self::discriminant`] kebab byte-string that would
1780 /// let a wire-axis consumer accept the dispatcher-catalog
1781 /// vocabulary) trips here rather than at a downstream K8s-CR round-
1782 /// trip miss.
1783 pub const WIRE_NAMES: &'static [&'static str] = &[
1784 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
1785 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
1786 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
1787 ];
1788
1789 /// Canonical PascalCase discriminator scalar this variant serializes
1790 /// as under [`crate::render::SUPERVISOR_CHILD_KEY_RESTART`]. The three
1791 /// arms return the paired
1792 /// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
1793 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
1794 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] lifted
1795 /// constants so every substrate consumer that dispatches on the
1796 /// per-child restart-decision policy (the future wasm-operator's
1797 /// per-child post-exit restart-decision branch, the future M4
1798 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
1799 /// admission-time enum-arm bind, the `caixa-operator`'s hierarchical
1800 /// reconciliation scheduler's per-child-policy fan-out) reads the
1801 /// same byte-string the `Serialize` derive emits — the pin test in
1802 /// [`tests::restart_policy_variants_serialize_to_lifted_scalar_values`]
1803 /// asserts the two paths agree, peer of the M2
1804 /// [`RestartStrategy::as_str`] (09ffb2d) on the sibling per-supervisor
1805 /// sibling-restart-strategy axis and the M3
1806 /// [`crate::aplicacao::PlacementStrategy::as_str`] (cc8f749) on the
1807 /// per-Aplicacao distribution-strategy axis — the third of three
1808 /// OTP-shaped closed-enum discriminator axes on the caixa typed
1809 /// surface to converge onto the same three-path-convergence
1810 /// (`Serialize` derive → `as_str` helper → lifted constant)
1811 /// drift-detection posture.
1812 #[must_use]
1813 pub const fn as_str(self) -> &'static str {
1814 match self {
1815 Self::Permanent => crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
1816 Self::Temporary => crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
1817 Self::Transient => crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
1818 }
1819 }
1820
1821 /// Substrate-canonical reverse projection on the `:children :restart`
1822 /// closed-set axis — parses the `PascalCase` discriminator scalar
1823 /// back to the typed variant, or `None` when `s` is outside the
1824 /// closed-set arm-string set [`Self::as_str`] emits. Dispatches on
1825 /// the same lifted
1826 /// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
1827 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
1828 /// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] constants
1829 /// the [`Self::as_str`] emitter walks, so the parse and emit halves
1830 /// of the round-trip migrate through one caixa-core edit on any
1831 /// future arm addition.
1832 ///
1833 /// Prior to this lift the substrate carried only the forward
1834 /// `Self → &str` projection on the OTP per-child restart-policy
1835 /// axis (the [`Self::as_str`] emitter, the [`std::fmt::Display`]
1836 /// impl routed through it, the `Serialize` derive that emits the
1837 /// same byte-string under [`crate::render::SUPERVISOR_CHILD_KEY_RESTART`])
1838 /// plus the kebab-case dispatcher-catalog identity via
1839 /// [`Self::discriminant`] — every non-serde consumer that wanted to
1840 /// parse a wire-form `PascalCase` policy scalar had to re-inline a
1841 /// three-arm `match s { "Permanent" => …, "Temporary" => …,
1842 /// "Transient" => …, _ => … }` cascade that expressed no
1843 /// compile-time link back to the typed variant's canonical lifted
1844 /// constant. A future variant rename or per-arm serde-attribute
1845 /// drift would silently split the wire byte-string one non-serde
1846 /// consumer parsed from the one the emitter wrote, with the failure
1847 /// surfacing at the operator's reconcile posture (a `:temporary`
1848 /// `oneShot` child being restarted on clean exit, treating the
1849 /// successful-completion signal as failure and re-running the
1850 /// completion-terminal one-shot indefinitely; a `:transient` child
1851 /// that clean-exited being restarted, masking the clean-completion
1852 /// contract) far from the rebrand commit and with no field naming
1853 /// the drift.
1854 ///
1855 /// Distinct axis from the [`std::str::FromStr`] impl the
1856 /// [`gen_platform::FromStrKind`] derive already installs on this
1857 /// enum by design, not by drift: `FromStr` parses the *kebab-case*
1858 /// dispatcher-catalog identity (`"permanent"` / `"temporary"` /
1859 /// `"transient"` — the inverse of [`Self::discriminant`]), while
1860 /// this method inverts the `PascalCase` wire byte-string
1861 /// [`Self::as_str`] emits. The two-axis split lets the dispatcher-
1862 /// catalog identity live in kebab-case (where every peer catalog
1863 /// identifier already lives) without forcing a wire-format rename
1864 /// on the tatara-lisp author surface (`:restart Permanent`,
1865 /// `PascalCase`) — the same two-axis distinction the sibling
1866 /// [`RestartStrategy::from_wire`] (4eec29c) /
1867 /// [`crate::CaixaKind::from_wire`] (2aa6d23) /
1868 /// [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342)
1869 /// carry on their peer closed-set typed-enum wire round-trips.
1870 ///
1871 /// Same closed-set-reverse-projection discipline the sibling
1872 /// [`RestartStrategy::from_wire`] (4eec29c) /
1873 /// [`crate::CaixaKind::from_wire`] (2aa6d23) /
1874 /// [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342) /
1875 /// [`crate::aplicacao::RateLimitUnit::from_suffix`] typed enums
1876 /// carry on the peer wire-side `str → Self` axes — extended onto
1877 /// the M2 OTP-shape per-child restart-policy closed-set axis, the
1878 /// sixth substrate-side closed-set typed enum (and the third and
1879 /// final OTP-shape closed-enum discriminator axis) to converge on
1880 /// the two-way `str ↔ Self` round-trip. Method-named `from_wire`
1881 /// (not `from_str`) to match the peer [`RestartStrategy::from_wire`]
1882 /// shape verbatim and side-step the [`std::str::FromStr`] impl the
1883 /// derive already installs on the sibling kebab-case axis. Returns
1884 /// `Option<Self>` (rather than `Result<Self, _>`) to match the peer
1885 /// shapes: the caller picks the diagnostic form appropriate for
1886 /// its use site.
1887 #[must_use]
1888 pub fn from_wire(s: &str) -> Option<Self> {
1889 match s {
1890 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT => Some(Self::Permanent),
1891 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY => Some(Self::Temporary),
1892 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT => Some(Self::Transient),
1893 _ => None,
1894 }
1895 }
1896}
1897
1898/// [`std::fmt::Display`] routed through [`RestartPolicy::as_str`], so the
1899/// pretty-printed byte-string every consumer that formats the policy as
1900/// user-facing text lands on (the future wasm-operator's per-child
1901/// post-exit restart-decision diagnostic line, the future `feira app
1902/// graph` per-child restart column, the future M4
1903/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-child
1904/// admission-webhook rejection body) reaches for the same lifted
1905/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
1906/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
1907/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
1908/// wire-format `Serialize` derive already emits under
1909/// [`crate::render::SUPERVISOR_CHILD_KEY_RESTART`] and the
1910/// [`RestartPolicy::as_str`] helper already returns.
1911///
1912/// Pre-convergence the two paths structurally disagreed — the
1913/// `#[derive(gen_platform::Discriminant)]` + `#[discriminant(also_display)]`
1914/// route (now retired here) sent [`std::fmt::Display`] through the
1915/// gen-platform discriminant catalog string, which arrives kebab-case as
1916/// `"permanent"` / `"temporary"` / `"transient"` on this three-arm enum
1917/// (whose variant names each collapse to their own lowercase form under
1918/// the kebab-case transform), while the wire format ran as `PascalCase`
1919/// `"Permanent"` / `"Temporary"` / `"Transient"` through the un-`rename`d
1920/// serde derive. Every consumer that formatted the policy for a
1921/// diagnostic line, a graph column, or a rejection body under
1922/// `format!("{v}")` therefore landed under a different byte-string than
1923/// the wire format the operator's per-child-policy dispatch keyed off —
1924/// a silent split whose apply-time symptom (a `format!("{v}")`-carrying
1925/// diagnostic quoting `"permanent"` while the wire scalar the operator
1926/// probed was `"Permanent"`) surfaced as a confused correlate at
1927/// operator-log time far from the two-declaration site.
1928///
1929/// Routing `Display` through [`RestartPolicy::as_str`] closes the third
1930/// path: every `format!("{v}")` call reaches the same lifted
1931/// [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const the wire format
1932/// and the [`RestartPolicy::as_str`] helper route through — `Debug` (the
1933/// compiler-derived variant name), `Display` (via `as_str`), and `Serialize`
1934/// (via the un-`rename`d derive) all resolve to the same `PascalCase`
1935/// byte-string per variant. A future variant rename or
1936/// `#[serde(rename_all = "kebab-case")]` attribute reaches every path at
1937/// exactly one place, structurally.
1938///
1939/// The dispatcher-catalog identity remains kebab-case — [`Self::discriminant`]
1940/// (from `#[derive(gen_platform::Discriminant)]`) still returns
1941/// `"permanent"` / `"temporary"` / `"transient"`, and the fleet-wide
1942/// [`gen_platform::register_dispatcher!("caixa.restart-policy", …)`]
1943/// registration keys the catalog off the same kebab identity. The two
1944/// naming worlds now live on separate typed methods (`Display` /
1945/// `as_str` for the wire byte-string, `discriminant` for the catalog
1946/// identity) rather than sharing one `Display` route that structurally
1947/// disagrees with the wire format.
1948///
1949/// Pin tests
1950/// [`tests::restart_policy_display_routes_through_as_str_helper`]
1951/// and
1952/// [`tests::restart_policy_display_matches_serialized_wire_byte_string`]
1953/// assert the three paths agree byte-for-byte on every variant, so a
1954/// future variant rename or per-arm serde attribute drift is a build
1955/// error visible at caixa-core test time, not a silent per-consumer
1956/// dispatch miss at apply / reconcile time.
1957///
1958/// Mirrors the M3 [`crate::aplicacao::PlacementStrategy`] `Display` impl
1959/// (aplicacao.rs:2306) on the per-Aplicacao distribution-strategy axis
1960/// and the sibling [`RestartStrategy`] `Display` impl on the
1961/// per-supervisor sibling-restart-strategy axis — same three-path-
1962/// convergence discipline, extended to close the third and final of
1963/// three OTP-shaped closed-enum discriminator axes on the caixa typed
1964/// surface.
1965impl std::fmt::Display for RestartPolicy {
1966 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1967 f.write_str(self.as_str())
1968 }
1969}
1970
1971/// Substrate-canonical [`AsRef<str>`] projection on the M2
1972/// per-child-restart-policy [`RestartPolicy`] closed-set typed enum —
1973/// routes through the same [`RestartPolicy::as_str`] `pub const fn`
1974/// scalar accessor the paired [`std::fmt::Display`] impl and the
1975/// un-`rename`d [`serde::Serialize`] derive already key off, so any
1976/// future consumer that binds a [`RestartPolicy`] through the
1977/// standard-library `impl AsRef<str>` bound (a future
1978/// [`caixa-feira`] `feira supervisor --restart <arm>` verb that
1979/// composes the emitted `PascalCase` wire scalar into a
1980/// [`std::process::Command::arg`] shell-out of the future
1981/// wasm-operator's per-child admission gate, a per-child structured-
1982/// log recorder on the future `caixa-operator`'s hierarchical
1983/// reconciliation surface that accepts `impl AsRef<str>` at the
1984/// `tracing::field::Value` `Str`-arm, a [`std::collections::HashMap`]
1985/// lookup keyed on the restart-policy wire byte through
1986/// `map.get::<str>(policy.as_ref())` on a future per-policy
1987/// dispatch table) reaches the paired
1988/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
1989/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
1990/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`]
1991/// lifted-const through one substrate-primitive dispatch rather
1992/// than an open-coded `.as_str()` projection at every wire-up.
1993///
1994/// Peer of the sibling [`std::fmt::Display`] impl on the same
1995/// primitive — both delegate to the shared [`RestartPolicy::as_str`]
1996/// `pub const fn` accessor, so [`format!("{v}")`], `v.as_str()`, and
1997/// `<RestartPolicy as AsRef<str>>::as_ref(&v)` resolve to the same
1998/// byte-string per instance by construction. A future variant rename
1999/// or `#[serde(rename_all = "kebab-case")]` attribute-drift on the
2000/// enum reaches every one of the three paths (plus the wire-format
2001/// `Serialize` derive that already routes through the same lifted
2002/// const) through exactly one caixa-core edit.
2003///
2004/// Same "route the trait impl through the substrate-primitive
2005/// accessor" discipline the sibling [`crate::CaixaVersion`]
2006/// [`AsRef<str>`] impl (16d5c7e) and the paired M2
2007/// [`RestartStrategy`] [`AsRef<str>`] impl (63eb1a4) carry — extends
2008/// the axis onto the paired per-child-restart-decision-policy
2009/// sibling on the same M2 `:supervisor` slot (the second M2
2010/// OTP-shape closed-set typed enum to converge onto the standard-
2011/// library [`AsRef<str>`] projection). Rust-side newtype/typed-enum
2012/// convention pairs [`AsRef<str>`] and [`fmt::Display`] on the same
2013/// primitive so a caller who has one has both; before this lift,
2014/// [`RestartPolicy`] carried [`fmt::Display`] but not the paired
2015/// [`AsRef<str>`] impl the convention names.
2016///
2017/// Pinned load-bearing by
2018/// [`tests::restart_policy_as_ref_str_routes_through_as_str_accessor`]
2019/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2020/// three-arm closed set) and
2021/// [`tests::restart_policy_as_ref_str_routes_through_display_via_shared_accessor`]
2022/// (three-path convergence: `AsRef<str>` + `Display` + `as_str` all
2023/// resolve to the same lifted `SUPERVISOR_CHILD_RESTART_*` const per
2024/// arm) — any future silent detour that routes the impl through a
2025/// divergent projection (a per-arm inline `match self { … }`
2026/// re-inlining that opens a compile-time link to the un-lifted
2027/// arm-literal, a swap onto the kebab-case
2028/// [`gen_platform::Discriminant`] catalog identity that would
2029/// collide the wire axis with the dispatcher-catalog axis) trips at
2030/// caixa-core test time under `assert_eq!` rather than at a
2031/// downstream `impl AsRef<str>`-bound consumer's silent split.
2032impl AsRef<str> for RestartPolicy {
2033 fn as_ref(&self) -> &str {
2034 self.as_str()
2035 }
2036}
2037
2038/// Trait-idiomatic reverse projection on the M2-OTP-shape per-child
2039/// restart-policy [`RestartPolicy`] closed-set typed enum — routes
2040/// byte-for-byte through the paired substrate-primitive
2041/// [`RestartPolicy::from_wire`] `Option<Self>` accessor so every future
2042/// consumer that binds a `PascalCase` `:children :restart` wire
2043/// byte-string through the standard-library `.try_into()` / [`TryFrom`]
2044/// axis (a future [`caixa-feira`] `feira supervisor --restart
2045/// <Permanent|Temporary|Transient>` CLI arg-parse that composes into
2046/// `let restart: RestartPolicy = s.try_into()?`, a future
2047/// `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook that folds a
2048/// `spec.children[*].restart: String` field through
2049/// `RestartPolicy::try_from(&s)?`, a generic
2050/// `<T: TryFrom<&str>>`-bound loader over any of the substrate's closed-
2051/// set typed enums) reaches the same three-arm accept-set the sibling
2052/// [`RestartPolicy::from_wire`] resolver parses through and the sibling
2053/// [`RestartPolicy::as_str`] emits, rather than an open-coded per-arm
2054/// `match s { "Permanent" => …, "Temporary" => …, "Transient" => …, _ =>
2055/// … }` cascade whose arm-set has no compile-time link back to the
2056/// substrate primitive.
2057///
2058/// Complements the pre-existing forward-projection triple
2059/// ([`std::fmt::Display`], [`AsRef<str>`], [`RestartPolicy::as_str`])
2060/// with the paired trait-idiomatic reverse-projection axis: Rust-side
2061/// newtype/typed-enum convention pairs [`AsRef<str>`] with either
2062/// [`std::str::FromStr`] or [`TryFrom<&str>`] on the same primitive so a
2063/// caller who can project *out to* a `&str` can also project *in from*
2064/// one. The [`TryFrom<&str>`] axis is deliberately chosen over
2065/// [`std::str::FromStr`] to sidestep the `clippy::should_implement_trait`
2066/// lint the sibling method-named [`RestartPolicy::from_wire`] would
2067/// trigger under a `FromStr` impl and to avoid colliding with the
2068/// [`std::str::FromStr`] impl the [`gen_platform::FromStrKind`] derive
2069/// already installs on the paired *kebab-case dispatcher-catalog* axis
2070/// (which parses `"permanent"` / `"temporary"` / `"transient"`, the
2071/// inverse of [`Self::discriminant`]) — this impl closes the trait-
2072/// idiomatic reverse axis on the *`PascalCase` wire* half without
2073/// disturbing either the method-named `from_wire` shape every sibling
2074/// closed-set typed enum on the substrate already carries or the
2075/// pre-existing `FromStr` on the dispatcher-catalog half, keeping the
2076/// two-axis split the sibling [`Self::from_wire`] doc block motivates.
2077///
2078/// `type Error = ()` matches the sibling [`RestartPolicy::from_wire`]'s
2079/// `Option<Self>` return-shape's deliberate deferral of error typing: the
2080/// caller picks the diagnostic form appropriate for its use site (a
2081/// future `feira supervisor --restart` arg-parse composes its own
2082/// per-verb "unknown restart: <arg> — accepted: {…}" message enumerating
2083/// [`RestartPolicy::ALL`], a future M4 admission-webhook rejection body
2084/// wraps the `Err(())` outcome with the accepted-set enumeration for
2085/// operator diagnostics, a `Result::map_err` at the call site lifts the
2086/// unit-error to a per-verb error type). Same shape the peer
2087/// [`RestartStrategy`] (5b828ed) on the sibling per-supervisor axis,
2088/// [`crate::CaixaKind`] (3c83606), [`crate::CaixaDialeto`] (bf33136), and
2089/// [`crate::aplicacao::PlacementStrategy`] (6fd00cd) blocks motivate on
2090/// their peer closed-set typed enums' reverse projections.
2091///
2092/// The paired [`TryFrom<&str>`] impl reaches the same three-arm accept-
2093/// set the [`RestartPolicy::from_wire`] resolver dispatches through, so
2094/// any future arm addition (an OTP-`intrinsic` fourth arm the theory
2095/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
2096/// might reach for once the three canonical OTP restart policies stop
2097/// covering the substrate's discovered load-shape) grows the trait-
2098/// idiomatic axis by construction — one caixa-core edit on
2099/// [`RestartPolicy::from_wire`] extends both the method-named reverse
2100/// projection every existing consumer keys off and the trait-idiomatic
2101/// reverse projection this impl exposes, without a coordinated rewrite
2102/// across every future `TryFrom<&str>`-bound consumer's arm-set.
2103///
2104/// Extends the substrate-wide closed-set-enum reverse-projection family
2105/// ([`crate::CaixaKind`] via 3c83606, [`crate::CaixaDialeto`] via
2106/// bf33136, [`crate::aplicacao::PlacementStrategy`] via 6fd00cd, and
2107/// [`RestartStrategy`] via 5b828ed) onto the third and final OTP-shape
2108/// closed-enum discriminator axis on the caixa surface — the paired
2109/// per-child `:children :restart` closed set the future wasm-operator's
2110/// hierarchical reconciliation scheduler's per-child post-exit
2111/// restart-decision branch keys off end-to-end.
2112///
2113/// Pinned load-bearing by
2114/// [`tests::restart_policy_try_from_str_routes_through_from_wire_accessor`]
2115/// (byte-parity pin against [`RestartPolicy::from_wire`] across the
2116/// three-arm accept-set),
2117/// [`tests::restart_policy_try_from_str_rejects_unknown_byte_strings`]
2118/// (rejection witness against silent accept-set widening), and
2119/// [`tests::restart_policy_try_from_str_and_from_wire_partition_the_accept_set`]
2120/// (cross-axis partition pin locking the trait and method-named
2121/// projections onto one accept-set).
2122impl TryFrom<&str> for RestartPolicy {
2123 type Error = ();
2124
2125 fn try_from(s: &str) -> Result<Self, Self::Error> {
2126 Self::from_wire(s).ok_or(())
2127 }
2128}
2129
2130/// Trait-idiomatic forward projection on the M2-OTP-shape per-child
2131/// restart-policy [`RestartPolicy`] closed-set typed enum — routes
2132/// byte-for-byte through the paired substrate-primitive
2133/// [`RestartPolicy::as_str`] `pub const fn` accessor. Return type is
2134/// `&'static str` by construction — every [`RestartPolicy::as_str`] arm
2135/// resolves to a [`crate::render::SUPERVISOR_CHILD_RESTART_*`] `pub const
2136/// &str` with `'static` lifetime, so the trait's return-type promise is
2137/// upheld structurally without a [`String::leak`] cast or a per-arm inline
2138/// literal.
2139///
2140/// Every future consumer that specifically needs `&'static str` lifetime
2141/// bytes on the per-child restart-decision axis (a
2142/// [`tracing::field::valuable::Value::Str`] recording where the `Str`
2143/// arm's typing demands `&'static str`, a
2144/// [`std::borrow::Cow::Borrowed`]`::<'static, str>(policy.into())` composer
2145/// on the future M4 admission-webhook rejection body where the
2146/// `Cow<'static, str>` typing rules out the sibling [`AsRef<str>`]
2147/// borrowed return, a generic `<T: Into<&'static str>>`-bound serializer
2148/// or error formatter that requires the `'static` bound) reaches the same
2149/// lifted [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2150/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2151/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] substrate-
2152/// primitive dispatch rather than an open-coded per-arm literal cascade
2153/// whose arm-set has no compile-time link back to the substrate primitive.
2154///
2155/// Peer of the sibling M2-OTP-shape [`RestartStrategy`] forward-projection
2156/// impl (523157d) on the per-supervisor sibling-restart-strategy axis —
2157/// the second (and second-of-two-in-M2) closed-set typed enum on the
2158/// caixa surface to converge onto the paired trait-idiomatic forward-
2159/// projection axis. With this lift the paired per-child
2160/// `:children :restart` closed-set typed enum carries the full sibling
2161/// quintet ([`std::fmt::Display`], [`AsRef<str>`], [`Self::as_str`],
2162/// [`TryFrom<&str>`] via 6fdd0d9, `From<Self> for &'static str` via this
2163/// lift) plus the round-trip witness through both the trait-idiomatic
2164/// (`From<Self> for &'static str` + `TryFrom<&str>`) and the method-named
2165/// (`as_str` + `from_wire`) axis pairs — mirrors the sibling
2166/// [`RestartStrategy`] surface arm-for-arm, so every future arm addition
2167/// (an OTP-`intrinsic` fourth arm the theory
2168/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
2169/// might reach for once the three canonical OTP restart policies stop
2170/// covering the substrate's discovered load-shape) grows the trait-
2171/// idiomatic forward axis by construction: one caixa-core edit on
2172/// [`RestartPolicy::as_str`] extends every one of the five sibling
2173/// forward-projection paths ([`std::fmt::Display`], [`AsRef<str>`],
2174/// [`Self::as_str`] itself, this `From<Self> for &'static str`, and the
2175/// un-`rename`d [`serde::Serialize`] derive that also emits `as_str`'s
2176/// bytes) without a coordinated rewrite across every future
2177/// `Into<&'static str>`-bound consumer's arm-set.
2178///
2179/// Pinned load-bearing by
2180/// [`tests::restart_policy_from_into_static_str_routes_through_as_str_accessor`]
2181/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2182/// three-arm emit-set, plus a `const`-context materialization witness for
2183/// the `&'static str` lifetime promise) and
2184/// [`tests::restart_policy_from_into_static_str_and_as_str_partition_the_emit_set`]
2185/// (partition pin asserting `<&'static str as From<RestartPolicy>>::from`
2186/// and [`RestartPolicy::as_str`] agree on every arm, plus a two-way
2187/// round-trip witness through the paired trait-idiomatic reverse-
2188/// projection axis [`TryFrom<&str>`] (6fdd0d9): every
2189/// `policy.into::<&'static str>()` output re-parses back through
2190/// [`RestartPolicy::try_from`] to the original variant, closing the two-
2191/// way `Self ↔ &'static str` round-trip on the trait-idiomatic axis pair).
2192impl From<RestartPolicy> for &'static str {
2193 fn from(policy: RestartPolicy) -> &'static str {
2194 policy.as_str()
2195 }
2196}
2197
2198/// Trait-idiomatic *forward* projection on [`RestartPolicy`] from a
2199/// *borrowed* input onto the `&'static str` axis — the borrowed-input
2200/// companion to the paired owned-input [`From<RestartPolicy> for
2201/// &'static str`] impl immediately above. Routes byte-for-byte through
2202/// the same substrate-primitive [`RestartPolicy::as_str`] `pub const
2203/// fn` accessor so every consumer that binds a `&RestartPolicy`
2204/// through the standard-library `.into()` / [`From<&Self> for &'static
2205/// str`] axis (a `RestartPolicy::ALL.iter().map(<&'static
2206/// str>::from).collect::<Vec<_>>()` per-arm accept-set materializer —
2207/// whose iterator over `&'static [RestartPolicy]` yields
2208/// `&RestartPolicy`, not `RestartPolicy`, so the owned-input
2209/// [`From<RestartPolicy>`] axis alone forces every call site through
2210/// an explicit `.copied()` / dereference / [`Copy`]-bound restatement
2211/// rather than the direct trait-idiomatic projection; a future generic
2212/// `<T: Copy + for<'a> Into<&'static str>>`-bound diagnostic column
2213/// that walks the `iter().map(Into::into)` shape verbatim across every
2214/// substrate-wide closed-set typed enum; the future wasm-operator's
2215/// per-child post-exit restart-decision diagnostic line that composes
2216/// the accepted-set enumeration from an iterated
2217/// `RestartPolicy::ALL.iter().map(|p| p.into())` pipe rather than a
2218/// per-arm `match p { … }` cascade; a future
2219/// `HashMap::<&'static str, RestartPolicy>::from_iter(
2220/// RestartPolicy::ALL.iter().map(|p| (p.into(), *p)))`-style
2221/// per-policy reverse-lookup table the sibling [`TryFrom<&str>`] impl
2222/// cannot compose without this borrowed-input axis in place) reaches
2223/// the same three-arm lifted
2224/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2225/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2226/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2227/// paired owned-input [`From<RestartPolicy> for &'static str`], the
2228/// sibling [`std::fmt::Display`], [`AsRef<str>`], and
2229/// [`RestartPolicy::as_str`] surfaces already return.
2230///
2231/// Fifth peer on the substrate-wide trait-idiomatic *borrowed-input*
2232/// forward-projection family opened on [`crate::dep::DepList`]
2233/// (64aa742) and extended onto [`crate::CaixaKind`] (5ab993a),
2234/// [`crate::CaixaDialeto`] (807b0b5), and the paired
2235/// per-supervisor sibling-restart-strategy [`RestartStrategy`]
2236/// (e941836). Rust's `From` trait does not auto-derive the
2237/// `From<&Self>` sibling from a `From<Self>` impl (the blanket
2238/// `impl<T, U> From<&T> for U where T: Copy, U: From<T>` does not
2239/// exist in `core`), so every closed-set typed enum that carries the
2240/// owned-input axis but not the borrowed-input axis forces every
2241/// borrowed-input call site through a `.copied()` /
2242/// `<&'static str>::from(*policy)` / `policy.as_str()` detour whose
2243/// type bounds have no compile-time link to the substrate primitive.
2244/// [`RestartPolicy`] is the second (and second-of-two-in-M2)
2245/// OTP-shape peer to converge onto this campaign — sibling of the
2246/// paired per-supervisor [`RestartStrategy`] borrowed-input axis, so
2247/// with this lift both closed-set typed enums on the M2 `:supervisor`
2248/// slot now carry the full sibling quintet ([`std::fmt::Display`],
2249/// [`AsRef<str>`], [`Self::as_str`], `From<Self> for &'static str`,
2250/// `From<&Self> for &'static str`) plus the paired trait-idiomatic
2251/// reverse projection [`TryFrom<&str>`], closing the borrowed-input
2252/// forward-projection axis on the M2 OTP-shape slot as a unit.
2253///
2254/// Same three-path convergence discipline as the paired owned-input
2255/// impl (this borrowed-input axis, the paired owned-input
2256/// [`From<RestartPolicy> for &'static str`], and
2257/// [`RestartPolicy::as_str`] all route through the same lifted
2258/// [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const), so a future
2259/// variant rename or per-arm serde-attribute drift reaches every one
2260/// of the six sibling forward-projection paths
2261/// ([`std::fmt::Display`], [`AsRef<str>`], [`Self::as_str`],
2262/// [`From<Self> for &'static str`], this [`From<&Self> for &'static
2263/// str`], and the un-`rename`d [`serde::Serialize`] derive that also
2264/// emits [`Self::as_str`]'s bytes) through exactly one caixa-core
2265/// edit.
2266///
2267/// The [`RestartPolicy::as_str`] emit and [`RestartPolicy::from_wire`]
2268/// parse share the same `PascalCase` vocabulary by construction, so
2269/// the borrowed-input forward axis and the reverse axis compose
2270/// directly — the round-trip witness pin below locks this direct
2271/// composition without the intermediate wire-vocab hop the peer
2272/// [`crate::CaixaKind`] axis pair requires.
2273///
2274/// Pinned load-bearing by
2275/// [`tests::restart_policy_from_borrowed_into_static_str_routes_through_as_str_accessor`]
2276/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2277/// three-arm emit-set via a borrowed input, plus a `const`-context
2278/// materialization witness for the `&'static str` lifetime promise,
2279/// plus a blanket `.into()` shape) and
2280/// [`tests::restart_policy_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
2281/// (cross-axis partition pin against the paired owned-input
2282/// [`From<RestartPolicy> for &'static str`] impl, plus a
2283/// `.iter().map(Into::into)` pipe witness over
2284/// [`RestartPolicy::ALL`], plus a direct round-trip witness through
2285/// [`TryFrom<&str>`] that closes the two-way `&Self → &'static str →
2286/// Self` round-trip without the wire-vocab intermediate the peer
2287/// [`crate::CaixaKind`] axis pair requires).
2288impl From<&RestartPolicy> for &'static str {
2289 fn from(policy: &RestartPolicy) -> &'static str {
2290 policy.as_str()
2291 }
2292}
2293
2294/// Trait-idiomatic *owned-`String`* forward projection on the second
2295/// M2 OTP-shape closed-set typed enum ([`RestartPolicy`]) — the
2296/// owned-heap-string companion to the paired `&'static str`-returning
2297/// [`From<RestartPolicy> for &'static str`] / [`From<&RestartPolicy>
2298/// for &'static str`] impls immediately above. Routes byte-for-byte
2299/// through the substrate-primitive [`RestartPolicy::as_str`] `pub
2300/// const fn` accessor (via [`str::to_owned`]) so every consumer that
2301/// binds a [`RestartPolicy`] through the standard-library `.into()` /
2302/// [`From<Self> for String`] (equivalently [`Into<String>`]) axis — a
2303/// future `serde_json::Value::String(policy.into())` structured-payload
2304/// composer where the `Value::String` arm typing demands an owned
2305/// [`String`] and the sibling [`&'static str`]-returning axis forces
2306/// an explicit `.to_owned()` / `String::from` restatement at every
2307/// call site, a future `HashMap::<String, RestartPolicy>::from_iter(
2308/// RestartPolicy::ALL.iter().map(|p| (p.into(), *p)))` per-policy
2309/// lookup where the map's key type is owned [`String`] rather than
2310/// [`&'static str`], a future `Cow::<'static, str>::Owned(policy.into())`
2311/// composer on the future M4 admission-webhook rejection body's
2312/// owned-arm, the future wasm-operator's per-child post-exit
2313/// diagnostic emit `serde_json::json!({ "restart": policy })` where the
2314/// JSON serializer's `Serialize` impl on [`String`] owns the emit-path
2315/// — reaches the same three-arm lifted
2316/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2317/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2318/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2319/// paired [`std::fmt::Display`], [`AsRef<str>`],
2320/// [`RestartPolicy::as_str`], and the two `&'static str`-returning
2321/// forward-projection impls already return.
2322///
2323/// Extends the trait-idiomatic *owned-`String`* forward-projection
2324/// axis onto the second-of-two M2 OTP-shape closed-set typed enums on
2325/// the caixa surface — mirror of the first-mover
2326/// [`From<RestartStrategy> for String`] (7baa18a) that opened this
2327/// axis on the sibling supervisor-level strategy enum. Rust's standard
2328/// library does not carry a blanket `impl<T: AsRef<str>> From<T> for
2329/// String` (nor an `impl<T: fmt::Display> From<T> for String`), so
2330/// every closed-set typed enum that carries the paired `AsRef<str>` /
2331/// `Display` / `From<Self> for &'static str` triple but not the
2332/// owned-[`String`] axis forces every owned-string call site through a
2333/// `.to_string()` / `.as_str().to_owned()` / `String::from(policy.as_str())`
2334/// detour whose type bounds have no compile-time link to the
2335/// substrate primitive.
2336///
2337/// Deliberately routes through the human-readable
2338/// [`RestartPolicy::as_str`] axis — for this enum the wire format
2339/// (`PascalCase`, tatara-lisp author surface `:restart Permanent`) and
2340/// the diagnostic byte-string share the same vocabulary by
2341/// construction (unlike the sibling [`crate::CaixaKind`] enum whose
2342/// two axes diverge), so the owned-[`String`] projection lands
2343/// byte-identically on both the wire vocabulary the paired
2344/// [`serde::Serialize`] derive emits and the diagnostic vocabulary the
2345/// [`RestartPolicy::as_str`] helper returns, and — because the paired
2346/// [`TryFrom<&str>`] / [`RestartPolicy::from_wire`] reverse-projection
2347/// axis parses the same `PascalCase` vocabulary — the direct two-way
2348/// `Self → String → Self` round-trip composes without the wire-vocab
2349/// intermediate hop the peer [`crate::CaixaKind`] owned-[`String`]
2350/// axis pair requires.
2351///
2352/// Pinned load-bearing by
2353/// [`tests::restart_policy_from_into_owned_string_routes_through_as_str_accessor`]
2354/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2355/// three-arm emit-set, plus a blanket `.into::<String>()` shape
2356/// witness) and
2357/// [`tests::restart_policy_from_into_owned_string_and_static_str_agree_on_every_arm`]
2358/// (cross-axis partition pin against the paired owned-input
2359/// [`From<RestartPolicy> for &'static str`] impl and the sibling
2360/// [`ToString::to_string`] surface routed through [`std::fmt::Display`],
2361/// plus a `.iter().copied().map(String::from)` pipe witness over
2362/// [`RestartPolicy::ALL`], plus a direct round-trip witness through
2363/// [`TryFrom<&str>`] on the owned-[`String`]'s [`String::as_str`]
2364/// borrow that closes the two-way `Self → String → Self` round-trip
2365/// on the trait-idiomatic owned-[`String`] forward + reverse axis
2366/// pair).
2367impl From<RestartPolicy> for String {
2368 fn from(policy: RestartPolicy) -> String {
2369 policy.as_str().to_owned()
2370 }
2371}
2372
2373/// Trait-idiomatic *borrowed-input, owned-`String` output* forward
2374/// projection on the second-of-two M2 OTP-shape closed-set typed enum
2375/// ([`RestartPolicy`]) — the fourth (and closing) corner of the
2376/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
2377/// projection family on this enum, mirror of the first-mover
2378/// [`From<&RestartStrategy> for String`] (579385f) that opened the
2379/// 2×2-completion corner on the sibling supervisor-level strategy
2380/// enum. Routes byte-for-byte through the substrate-primitive
2381/// [`RestartPolicy::as_str`] `pub const fn` accessor (via
2382/// [`str::to_owned`]) so every consumer that holds a borrowed
2383/// [`&RestartPolicy`] and needs an owned [`String`] — a future
2384/// `serde_json::Value::String(String::from(&policy))` structured-payload
2385/// composer over a borrowed field, a future `Iterator::map` over
2386/// `&[RestartPolicy]` that projects to owned keys through
2387/// `.iter().map(String::from)`, a future `HashMap::<String,
2388/// RestartPolicy>::from_iter` that keys off a borrowed-iteration axis
2389/// where dereferencing the policy would force an unnecessary `Copy` at
2390/// every step, the future wasm-operator's per-supervisor
2391/// `child_policies.iter().map(String::from).collect()` per-child post-
2392/// exit restart-decision diagnostic emit whose iteration axis is
2393/// borrowed by construction — reaches the same three-arm lifted
2394/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2395/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2396/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2397/// paired [`std::fmt::Display`], [`AsRef<str>`],
2398/// [`RestartPolicy::as_str`], and the three other trait-idiomatic
2399/// forward-projection impls
2400/// ([`From<RestartPolicy> for &'static str`],
2401/// [`From<&RestartPolicy> for &'static str`],
2402/// [`From<RestartPolicy> for String`]) already return.
2403///
2404/// Second peer on the substrate-wide trait-idiomatic *borrowed-input,
2405/// owned-`String` output* forward-projection family opened on
2406/// [`crate::supervisor::RestartStrategy`] (579385f) — closes the
2407/// `{Self, &Self} × {&'static str, String}` 2×2 projection corner on
2408/// both M2 OTP-shape sibling peers (the paired supervisor-level
2409/// sibling-restart-strategy axis and the per-child restart-decision-
2410/// policy axis), so the whole M2 OTP-shape axis pair now carries the
2411/// full four-corner family by construction. Rust's standard library
2412/// does not carry a blanket `impl<T: AsRef<str>> From<&T> for String`
2413/// (nor an `impl<T: fmt::Display> From<&T> for String`), so every
2414/// closed-set typed enum that carries the paired `AsRef<str>` /
2415/// `Display` / `From<Self> for &'static str` / `From<&Self> for
2416/// &'static str` / `From<Self> for String` quintuple but not the
2417/// borrowed-input owned-[`String`] axis forces every borrowed-input
2418/// owned-string call site through a `policy.as_str().to_owned()` /
2419/// `String::from(*policy)` (with a spurious `Copy`) /
2420/// `policy.to_string()` (through `Display`) detour whose type bounds
2421/// have no compile-time link to the substrate primitive.
2422///
2423/// Deliberately routes through the human-readable
2424/// [`RestartPolicy::as_str`] axis — for this enum the wire format
2425/// (`PascalCase`, tatara-lisp author surface `:restart Permanent`) and
2426/// the diagnostic byte-string share the same vocabulary by
2427/// construction (unlike the sibling [`crate::CaixaKind`] enum whose
2428/// two axes diverge), so the borrowed-input owned-[`String`]
2429/// projection lands byte-identically on both the wire vocabulary the
2430/// paired [`serde::Serialize`] derive emits and the diagnostic
2431/// vocabulary the [`RestartPolicy::as_str`] helper returns, and —
2432/// because the paired [`TryFrom<&str>`] / [`RestartPolicy::from_wire`]
2433/// reverse-projection axis parses the same `PascalCase` vocabulary —
2434/// the direct two-way `&Self → String → Self` round-trip composes
2435/// without the wire-vocab intermediate hop the peer
2436/// [`crate::CaixaKind`] axis pair requires.
2437///
2438/// The remaining thirteen closed-set typed enums on the caixa
2439/// substrate surface (`CaixaKind`, `CaixaDialeto`, `DepList`,
2440/// `PlacementStrategy`, `WitShape`, `RateLimitUnit`,
2441/// `PathShapeViolation`, `InvariantKind`, `ArchVerdict`, `Severity`,
2442/// `FixSafety`, `Semantic`, `FerriteRuntime`) are the future targets
2443/// of this 2×2-completion campaign — each carries the same paired
2444/// quintuple that this borrowed-input owned-[`String`] axis extends
2445/// onto.
2446///
2447/// Pinned load-bearing by
2448/// [`tests::restart_policy_from_into_borrowed_owned_string_routes_through_as_str_accessor`]
2449/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2450/// three-arm emit-set through the borrowed-input surface) and
2451/// [`tests::restart_policy_from_into_borrowed_owned_string_agrees_with_paired_axes_on_every_arm`]
2452/// (cross-axis partition pin against the paired owned-input owned-
2453/// [`String`] [`From<RestartPolicy> for String`] impl, the paired
2454/// borrowed-input owned-[`&'static str`] [`From<&RestartPolicy> for
2455/// &'static str`] impl, and the sibling [`ToString::to_string`]
2456/// surface routed through [`std::fmt::Display`], plus a direct round-
2457/// trip witness through [`TryFrom<&str>`] on the owned-[`String`]'s
2458/// [`String::as_str`] borrow that closes the two-way
2459/// `&Self → String → Self` round-trip on the trait-idiomatic
2460/// borrowed-input owned-[`String`] forward + reverse axis pair).
2461impl From<&RestartPolicy> for String {
2462 fn from(policy: &RestartPolicy) -> String {
2463 policy.as_str().to_owned()
2464 }
2465}
2466
2467/// Trait-idiomatic *owned-input, [`std::borrow::Cow<'static, str>`]
2468/// output* forward projection on the M2 OTP-shape per-child-restart
2469/// [`RestartPolicy`] closed-set typed enum — extends the substrate-
2470/// wide [`std::borrow::Cow<'static, str>`] forward-projection family
2471/// opened on [`crate::CaixaKind`] (99c1735 owned-input, d45c409
2472/// borrowed-input) and first extended off it onto the sibling M2
2473/// OTP-shape sibling-restart [`RestartStrategy`] (7dd28b3 owned-input,
2474/// 9b3e4b3 borrowed-input) onto the second (and second-of-two-in-M2)
2475/// M2 OTP-shape closed-set fieldless typed enum peer on the caixa
2476/// surface (`:children :restart`). Routes byte-for-byte through the
2477/// substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
2478/// accessor (via [`std::borrow::Cow::Borrowed`]) so every consumer
2479/// that binds a [`RestartPolicy`] through the trait-idiomatic
2480/// [`std::borrow::Cow<'static, str>`] axis — a future
2481/// `axum::response::IntoResponse` composer whose per-policy
2482/// diagnostic-body typing rules out the sibling [`AsRef<str>`]
2483/// borrowed return, a future M4 admission-webhook rejection body
2484/// that composes the accepted-policy enumeration through the same
2485/// `RestartPolicy::ALL.iter().map(Cow::from)` shape [`crate::CaixaKind`]
2486/// and [`RestartStrategy`] already route through, a generic `<T: for<'a>
2487/// Into<std::borrow::Cow<'static, str>>>`-bound structured-log
2488/// emitter on a per-child-policy diagnostic column — reaches the same
2489/// three-arm lifted [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`]
2490/// / [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2491/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2492/// paired [`std::fmt::Display`], [`AsRef<str>`],
2493/// [`RestartPolicy::as_str`], and the four
2494/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
2495/// forward-projection corners already return.
2496///
2497/// Deliberately returns [`std::borrow::Cow::Borrowed`] rather than
2498/// [`std::borrow::Cow::Owned`] — the substrate-primitive
2499/// [`RestartPolicy::as_str`] accessor's return carries the `&'static
2500/// str` lifetime by construction (each `match` arm resolves to a
2501/// [`crate::render::SUPERVISOR_CHILD_RESTART_*`] `pub const &str`
2502/// with static lifetime), so the zero-alloc borrowed arm is the
2503/// type-correct projection with no runtime allocation.
2504///
2505/// Rust's standard library carries no blanket `impl<T: AsRef<str>>
2506/// From<T> for Cow<'static, str>` (nor an `impl<T: fmt::Display>
2507/// From<T> for Cow<'static, str>`), so the paired sibling
2508/// [`From<RestartPolicy> for &'static str`] (9fb37d0),
2509/// [`From<RestartPolicy> for String`] (7851725), [`AsRef<str>`], and
2510/// [`std::fmt::Display`] surfaces do not implicitly extend to a
2511/// [`Cow<'static, str>`]-bound call site — every such site is forced
2512/// through a `Cow::Borrowed(policy.as_str())` /
2513/// `Cow::Owned(policy.to_string())` open-code whose type bounds have
2514/// no compile-time link back to the substrate primitive until this
2515/// lift.
2516///
2517/// Second peer to extend the substrate-wide trait-idiomatic
2518/// [`std::borrow::Cow<'static, str>`] forward-projection axis off the
2519/// top-level [`crate::CaixaKind`] enum (99c1735 owned-input, d45c409
2520/// borrowed-input) onto the wider substrate — closes the M2 OTP-shape
2521/// tier of the campaign (both sibling peers, `RestartStrategy` and
2522/// `RestartPolicy`, now carry the owned-input Cow<'static, str>
2523/// forward projection) so the remaining eleven peers
2524/// (`PlacementStrategy`, `RateLimitUnit`, `DepList`, `CaixaDialeto`,
2525/// and the outside-`caixa-core` peers `WitShape`, `PathShapeViolation`,
2526/// `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`, `Semantic`,
2527/// `FerriteRuntime`) are the future targets. Every future arm addition
2528/// (an OTP-`intrinsic` fourth restart policy the ABSORPTION-ROADMAP
2529/// might reach for once the three canonical OTP restart policies stop
2530/// covering the substrate's discovered load-shape) grows the
2531/// Cow<'static, str> axis by construction through one caixa-core edit
2532/// on [`RestartPolicy::as_str`] — rather than a coordinated rewrite
2533/// across every future Cow<'static, str>-bound consumer site.
2534///
2535/// Pinned load-bearing by
2536/// [`tests::restart_policy_from_into_static_cow_str_routes_through_as_str_accessor`]
2537/// (byte-parity + zero-alloc [`std::borrow::Cow::Borrowed`]-arm pin
2538/// against [`RestartPolicy::as_str`] across the three-arm
2539/// [`RestartPolicy::ALL`]) and
2540/// [`tests::restart_policy_from_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
2541/// (cross-axis partition pin against the paired [`From<RestartPolicy>
2542/// for &'static str`], [`From<RestartPolicy> for String`], and
2543/// [`ToString`]-through-[`std::fmt::Display`] axes, plus a
2544/// `.iter().copied().map(Cow::from)` pipe witness over
2545/// [`RestartPolicy::ALL`] that materializes the three-arm accept-set
2546/// through the [`Cow<'static, str>`] axis alone and pins the
2547/// zero-alloc discipline on every element).
2548impl From<RestartPolicy> for std::borrow::Cow<'static, str> {
2549 fn from(policy: RestartPolicy) -> std::borrow::Cow<'static, str> {
2550 std::borrow::Cow::Borrowed(policy.as_str())
2551 }
2552}
2553
2554/// Trait-idiomatic *borrowed-input, [`std::borrow::Cow<'static, str>`]
2555/// output* forward projection on the M2 OTP-shape per-child-restart
2556/// [`RestartPolicy`] closed-set typed enum — the borrowed-input
2557/// companion to the paired owned-input
2558/// [`From<RestartPolicy> for std::borrow::Cow<'static, str>`] impl
2559/// immediately above (0612398). Routes byte-for-byte through the same
2560/// substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
2561/// accessor (via [`std::borrow::Cow::Borrowed`]) so every consumer
2562/// that holds a `&RestartPolicy` and needs a
2563/// [`std::borrow::Cow<'static, str>`] — a
2564/// `RestartPolicy::ALL.iter().map(std::borrow::Cow::from).collect::<Vec<_>>()`
2565/// per-arm accept-set materializer (whose iterator over
2566/// `&'static [RestartPolicy]` yields `&RestartPolicy`, not
2567/// `RestartPolicy`, so the paired owned-input
2568/// [`From<RestartPolicy> for std::borrow::Cow<'static, str>`] axis
2569/// alone forces every call site through an explicit `.copied()` /
2570/// dereference / [`Copy`]-bound restatement rather than the direct
2571/// trait-idiomatic projection), a future generic
2572/// `<T: for<'a> Into<std::borrow::Cow<'static, str>>>`-bound emitter
2573/// on a per-child-policy diagnostic column that walks the
2574/// `iter().map(Into::into)` shape verbatim, the future M4 admission-
2575/// webhook rejection body that composes the accepted-policy
2576/// enumeration from an iterated
2577/// `RestartPolicy::ALL.iter().map(|p| p.into())` pipe rather than a
2578/// per-arm `match p { … }` cascade — reaches the same three-arm
2579/// lifted [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2580/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2581/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2582/// paired [`std::fmt::Display`], [`AsRef<str>`],
2583/// [`RestartPolicy::as_str`], the four
2584/// `{Self, &Self} × {&'static str, String}` 2×2 trait-idiomatic
2585/// forward-projection corners, and the paired owned-input
2586/// [`From<RestartPolicy> for std::borrow::Cow<'static, str>`] impl
2587/// already return.
2588///
2589/// Deliberately returns [`std::borrow::Cow::Borrowed`] rather than
2590/// [`std::borrow::Cow::Owned`] — the substrate-primitive
2591/// [`RestartPolicy::as_str`] accessor's return carries the
2592/// `&'static str` lifetime by construction (each `match` arm resolves
2593/// to a [`crate::render::SUPERVISOR_CHILD_RESTART_*`] `pub const &str`
2594/// with static lifetime), so the zero-alloc borrowed arm is the
2595/// type-correct projection with no runtime allocation.
2596///
2597/// Closes the `{Self, &Self}` input-shape corner on the M2 OTP-shape
2598/// per-child-restart [`std::borrow::Cow<'static, str>`] axis opened
2599/// one commit prior (0612398) on the paired owned-input
2600/// [`From<RestartPolicy> for std::borrow::Cow<'static, str>`] impl —
2601/// second-of-two-in-M2 closed-set fieldless typed enum peer on the
2602/// caixa surface (paired with the sibling-restart [`RestartStrategy`]
2603/// which carries both {Self, &Self} × Cow<'static, str> corners since
2604/// 7dd28b3 owned-input, 9b3e4b3 borrowed-input), exactly as d45c409
2605/// closed it on the top-level [`crate::CaixaKind`] one commit after
2606/// the owning half (99c1735) landed. This lift closes the whole M2
2607/// OTP-shape tier of the substrate-wide [`Cow<'static, str>`]
2608/// forward-projection campaign on both input-shape corners
2609/// ({Self, &Self}) of both M2 OTP-shape sibling peers
2610/// ([`RestartStrategy`] and [`RestartPolicy`]), so the remaining
2611/// eleven substrate-wide peers (`PlacementStrategy`, `RateLimitUnit`,
2612/// `DepList`, `CaixaDialeto`, `WitShape`, `PathShapeViolation`,
2613/// `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`, `Semantic`,
2614/// `FerriteRuntime`) become the future targets of the campaign. Rust's
2615/// standard library does not carry a blanket
2616/// `impl<T: AsRef<str>> From<&T> for Cow<'static, str>` (nor an
2617/// `impl<T: fmt::Display> From<&T> for Cow<'static, str>`), so every
2618/// closed-set fieldless typed enum peer on the substrate that carries
2619/// the paired owned-input [`Cow<'static, str>`] axis but not the
2620/// borrowed-input axis forces every borrowed-input
2621/// [`Cow<'static, str>`]-parameterized call site through a spurious
2622/// [`Copy`] deref (`std::borrow::Cow::from(*policy)`) or a
2623/// `std::borrow::Cow::Borrowed(policy.as_str())` open-code whose type
2624/// bounds have no compile-time link to the substrate primitive.
2625///
2626/// Pinned load-bearing by
2627/// [`tests::restart_policy_from_borrowed_into_static_cow_str_routes_through_as_str_accessor`]
2628/// (byte-parity + zero-alloc [`std::borrow::Cow::Borrowed`]-arm pin
2629/// against [`RestartPolicy::as_str`] across the three-arm
2630/// [`RestartPolicy::ALL`] through the borrowed-input surface) and
2631/// [`tests::restart_policy_from_borrowed_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
2632/// (cross-axis partition pin against the paired owned-input
2633/// [`From<RestartPolicy> for std::borrow::Cow<'static, str>`], the
2634/// paired borrowed-input owned-`&'static str`
2635/// [`From<&RestartPolicy> for &'static str`], and the paired
2636/// borrowed-input owned-`String` [`From<&RestartPolicy> for String`]
2637/// impls, plus a `.iter().map(std::borrow::Cow::from)` pipe witness
2638/// over [`RestartPolicy::ALL`] — whose iterator yields
2639/// `&RestartPolicy` by construction, so the borrowed-input
2640/// [`Cow<'static, str>`] axis is what routes the pipe through the
2641/// substrate-primitive [`RestartPolicy::as_str`] accessor with the
2642/// zero-alloc [`Cow::Borrowed`] arm by construction and without a
2643/// spurious [`Copy`] deref).
2644impl From<&RestartPolicy> for std::borrow::Cow<'static, str> {
2645 fn from(policy: &RestartPolicy) -> std::borrow::Cow<'static, str> {
2646 std::borrow::Cow::Borrowed(policy.as_str())
2647 }
2648}
2649
2650/// Trait-idiomatic *owned-input, [`Box<str>`] output* forward
2651/// projection on the M2 OTP-shape per-child-restart [`RestartPolicy`]
2652/// closed-set fieldless typed enum — extends the substrate-wide
2653/// `Box<str>` forward-projection campaign tier opened one commit prior
2654/// (69ef45c) on the paired sibling-restart [`RestartStrategy`] onto
2655/// the second (and third-and-final) M2 OTP-shape closed-set fieldless
2656/// typed enum peer on the caixa surface (`:children :restart`),
2657/// immediately after the paired `Cow<'static, str>` axis (0612398 /
2658/// b4dc55c) closed the
2659/// `{Self, &Self} × {&'static str, String, Cow<'static, str>}` 2×3
2660/// corner on this enum. Routes byte-for-byte through the
2661/// substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
2662/// accessor via [`Box::<str>::from`] on the returned `&'static str`,
2663/// so every consumer that binds a
2664/// `let key: Box<str> = policy.into();`-shaped call site — a
2665/// per-child metric-key materializer that stashes the policy
2666/// discriminator in a `Box<str>`-typed heap-owned scalar for cheap
2667/// clone (a shared-nothing per-policy accept-set the `caixa-operator`
2668/// hierarchical reconciliation scheduler's per-child restart-decision
2669/// fan-out carries), a future admission-webhook rejection body whose
2670/// per-arm `Box<str>` field composes from an owned `RestartPolicy`
2671/// handle — reaches the same three-arm lifted
2672/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2673/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2674/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2675/// sibling
2676/// `{Self, &Self} × {&'static str, String, Cow<'static, str>}`
2677/// forward-projection corner already returns. Rust's standard library
2678/// carries `impl From<&str> for Box<str>` and
2679/// `impl From<String> for Box<str>` but no blanket
2680/// `impl<T: AsRef<str>> From<T> for Box<str>` (nor any
2681/// `impl<T: Copy, U: From<T>> From<T> for U` route from the enum), so
2682/// this axis is a distinct trait-idiomatic surface that a downstream
2683/// `RestartPolicy → Box<str>` `.into()` reaches through this impl and
2684/// no other — without a `Box::from(policy.as_str())` open-code whose
2685/// type bounds have no compile-time link back to the substrate
2686/// primitive.
2687///
2688/// Second peer on the substrate-wide trait-idiomatic [`Box<str>`]
2689/// forward-projection family opened on the sibling-restart
2690/// [`RestartStrategy`] (69ef45c / 59ae5dc) — closes the whole M2
2691/// OTP-shape tier of the substrate-wide [`Box<str>`] forward-
2692/// projection campaign's owned-input corner on both M2 OTP-shape
2693/// sibling peers ([`RestartStrategy`] and [`RestartPolicy`]), the
2694/// paired borrowed-input `From<&RestartPolicy> for Box<str>` closer
2695/// and the remaining fieldless-enum peers on the M3 mesh-shape /
2696/// outside-M3 caixa-core / render-side / outside-caixa-core tiers
2697/// are the future targets of the campaign.
2698///
2699/// Pinned load-bearing by
2700/// [`tests::restart_policy_from_into_box_str_routes_through_as_str_accessor`]
2701/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2702/// three-arm [`RestartPolicy::ALL`] emit-set on the owned-input
2703/// surface, plus a blanket-derived [`Into`] shape witness).
2704impl From<RestartPolicy> for Box<str> {
2705 fn from(policy: RestartPolicy) -> Box<str> {
2706 Box::<str>::from(policy.as_str())
2707 }
2708}
2709
2710/// Trait-idiomatic *borrowed-input, [`Box<str>`] output* forward
2711/// projection on the M2 OTP-shape per-child-restart [`RestartPolicy`]
2712/// closed-set fieldless typed enum — the borrowed-input companion to
2713/// the paired owned-input [`From<RestartPolicy> for Box<str>`] impl
2714/// (0a1b313, one commit prior) that closes the `{Self, &Self}`
2715/// input-shape corner of the substrate-wide [`Box<str>`] forward-
2716/// projection axis on the second (and third-and-final) M2 OTP-shape
2717/// closed-set fieldless typed enum peer on the caixa surface
2718/// (`:children :restart`), routing byte-for-byte through the
2719/// substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
2720/// accessor via [`Box::<str>::from`] on the returned `&'static str`.
2721/// Every consumer that holds a `&RestartPolicy` and needs a
2722/// [`Box<str>`] — a
2723/// `RestartPolicy::ALL.iter().map(Box::<str>::from).collect::<Vec<_>>()`
2724/// per-arm accept-set materializer (whose iterator over
2725/// `&'static [RestartPolicy]` yields `&RestartPolicy`, not
2726/// `RestartPolicy`, so the paired owned-input
2727/// [`From<RestartPolicy> for Box<str>`] axis alone forces every
2728/// call site through an explicit [`Copy`] deref or a
2729/// `.copied()` restatement rather than the direct trait-idiomatic
2730/// projection), a per-child metric-key materializer holding
2731/// `&RestartPolicy` through a `caixa-operator` hierarchical
2732/// reconciliation scheduler's borrow lifetime, a future admission-
2733/// webhook rejection body whose per-arm `Box<str>` field composes
2734/// from a borrowed `&RestartPolicy` handle — reaches the
2735/// substrate-primitive [`RestartPolicy::as_str`] accessor through
2736/// this impl and no other, without a
2737/// `Box::<str>::from(policy.as_str())` open-code whose type bounds
2738/// have no compile-time link back to the substrate primitive.
2739///
2740/// Rust's standard library carries `impl From<&str> for Box<str>`
2741/// and `impl From<String> for Box<str>` but no blanket
2742/// `impl<T: AsRef<str>> From<&T> for Box<str>` (nor a
2743/// `Copy`-based `impl<T: Copy, U: From<&T> for U`), so every closed-
2744/// set fieldless typed enum peer on the substrate that carries the
2745/// paired owned-input `Box<str>` axis but not the borrowed-input
2746/// axis forces every borrowed-input `Box<str>`-parameterized call
2747/// site through a spurious [`Copy`] deref
2748/// (`Box::<str>::from((*policy).as_str())`) or a
2749/// `Box::<str>::from(policy.as_str())` open-code whose type bounds
2750/// have no compile-time link back to the substrate primitive.
2751///
2752/// Fourth (and closing) peer on the substrate-wide trait-idiomatic
2753/// [`Box<str>`] forward-projection family on the M2 OTP-shape tier
2754/// — closes the whole `{Self, &Self}` input-shape corner of the
2755/// [`Box<str>`] axis on both M2 OTP-shape sibling peers
2756/// ([`RestartStrategy`] and [`RestartPolicy`]), exactly as b4dc55c
2757/// closed the paired [`Cow<'static, str>`] axis one commit after
2758/// its owning half (0612398) landed on this enum. The remaining
2759/// fieldless-enum peers on the M3 mesh-shape / outside-M3 caixa-
2760/// core / render-side / outside-caixa-core tiers are the future
2761/// targets of the [`Box<str>`] campaign.
2762///
2763/// Pinned load-bearing by
2764/// [`tests::restart_policy_from_borrowed_into_box_str_routes_through_as_str_accessor`]
2765/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2766/// three-arm [`RestartPolicy::ALL`] emit-set on the borrowed-input
2767/// surface, plus a blanket-derived [`Into`] shape witness, a
2768/// cross-axis partition pin against the paired owned-input
2769/// [`From<RestartPolicy> for Box<str>`] and the sibling borrowed-
2770/// input `{&'static str, String, Cow<'static, str>}` return-shape
2771/// axes, and a `.iter().map(Box::<str>::from)` pipe witness over
2772/// [`RestartPolicy::ALL`] — whose iterator yields `&RestartPolicy`
2773/// by construction, so the borrowed-input [`Box<str>`] axis is
2774/// what routes the pipe through the substrate-primitive
2775/// [`RestartPolicy::as_str`] accessor without a spurious [`Copy`]
2776/// deref).
2777impl From<&RestartPolicy> for Box<str> {
2778 fn from(policy: &RestartPolicy) -> Box<str> {
2779 Box::<str>::from(policy.as_str())
2780 }
2781}
2782
2783/// Trait-idiomatic *owned-input, [`std::sync::Arc<str>`] output*
2784/// forward projection on the M2 OTP-shape per-child-restart
2785/// [`RestartPolicy`] closed-set fieldless typed enum — routes byte-
2786/// for-byte through the substrate-primitive [`RestartPolicy::as_str`]
2787/// `pub const fn` accessor via [`std::sync::Arc::<str>::from`] on the
2788/// returned `&'static str`, so every consumer that binds a
2789/// [`RestartPolicy`] through the standard-library `.into()` /
2790/// [`From<Self> for std::sync::Arc<str>`] (equivalently
2791/// [`Into<std::sync::Arc<str>>`]) axis — a future admission-webhook's
2792/// per-request `Sync` + `Send`-safe structured-log field composed
2793/// across an `.await` boundary through a
2794/// `<T: Into<std::sync::Arc<str>>>`-bound diagnostic-column dispatch,
2795/// a future wasm-operator's per-child post-exit restart-decision
2796/// pipeline holding a shared-ownership per-arm cache key, a
2797/// `<T: Into<std::sync::Arc<str>>>`-bound `tracing`-span attributes
2798/// collector recording a per-child-policy field onto the parent
2799/// span's shared-ownership context — reaches the same three-arm
2800/// lifted [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2801/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2802/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2803/// sibling
2804/// `{Self, &Self} × {&'static str, String, Cow<'static, str>, Box<str>}`
2805/// forward-projection corner already returns.
2806///
2807/// Second peer on the substrate-wide trait-idiomatic
2808/// [`std::sync::Arc<str>`] forward-projection family opened one
2809/// projection tier prior (bca2ec8) on the paired sibling-restart
2810/// [`RestartStrategy`] owned-input first-mover — extends the tier
2811/// onto the second (and third-and-final) M2 OTP-shape closed-set
2812/// fieldless typed enum peer on the caixa surface
2813/// (`:children :restart`), immediately after the paired [`Box<str>`]
2814/// axis (0a1b313 / cb1d068) closed the whole
2815/// `{Self, &Self} × {&'static str, String, Cow<'static, str>, Box<str>}`
2816/// 2×4 corner on this enum. Rust's standard library carries
2817/// `impl From<&str> for std::sync::Arc<str>` and
2818/// `impl From<String> for std::sync::Arc<str>` but no blanket
2819/// `impl<T: AsRef<str>> From<T> for std::sync::Arc<str>` (nor an
2820/// `impl<T: fmt::Display> From<T> for std::sync::Arc<str>`), so this
2821/// axis is a distinct trait-idiomatic surface that a
2822/// `let key: std::sync::Arc<str> = policy.into();`-shaped call site
2823/// reaches through this impl and no other — a paired
2824/// `std::sync::Arc::<str>::from(policy.as_str())` open-code has no
2825/// compile-time link back to the substrate primitive, and a two-step
2826/// `std::sync::Arc::<str>::from(String::from(policy))` composition
2827/// through the owned-`String` axis allocates twice (once into the
2828/// intermediate `String`, once into the [`Arc<str>`] on the
2829/// `From<String>` conversion) where the single-step trait impl
2830/// allocates once.
2831///
2832/// Peer of the sibling [`Box<str>`] second-tier extender (0a1b313) —
2833/// same "extends the substrate-wide projection tier onto the next
2834/// M2 OTP-shape peer" discipline, extended onto the
2835/// [`std::sync::Arc<str>`] axis whose shared-ownership + [`Sync`] +
2836/// [`Send`] contract is the distinct value the [`Box<str>`] axis's
2837/// owned-move return-shape cannot provide.
2838///
2839/// Pinned load-bearing by
2840/// [`tests::restart_policy_from_into_arc_str_routes_through_as_str_accessor`]
2841/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2842/// three-arm [`RestartPolicy::ALL`] emit-set on the owned-input
2843/// surface, plus a blanket-derived [`Into`] shape witness and cross-
2844/// axis byte-parity pins against the sibling owned-input
2845/// `{&'static str, String, Cow<'static, str>, Box<str>}` return-shape
2846/// axes).
2847impl From<RestartPolicy> for std::sync::Arc<str> {
2848 fn from(policy: RestartPolicy) -> std::sync::Arc<str> {
2849 std::sync::Arc::<str>::from(policy.as_str())
2850 }
2851}
2852
2853/// Trait-idiomatic *borrowed-input, [`std::sync::Arc<str>`] output*
2854/// forward projection on the M2 OTP-shape per-child-restart
2855/// [`RestartPolicy`] closed-set fieldless typed enum — closes the
2856/// `{Self, &Self}` input-shape corner of the [`std::sync::Arc<str>`]
2857/// forward-projection axis on the second (and third-and-final) M2
2858/// OTP-shape closed-set fieldless typed enum peer on the caixa
2859/// surface (`:children :restart`), companion to the paired
2860/// owned-input [`From<RestartPolicy> for std::sync::Arc<str>`] impl
2861/// one commit prior (b05724e). Routes byte-for-byte through the
2862/// substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
2863/// accessor (via [`std::sync::Arc::<str>::from`] on the returned
2864/// `&'static str`), so every consumer that binds a
2865/// [`&RestartPolicy`] through the standard-library `.into()` /
2866/// [`From<&Self> for std::sync::Arc<str>`] (equivalently
2867/// [`Into<std::sync::Arc<str>>`]) axis — a future admission-webhook's
2868/// per-request borrowed-`&RestartPolicy` handle rendering a per-arm
2869/// `Sync` + `Send`-safe structured-log field across an `.await`
2870/// boundary through a `<T: Into<std::sync::Arc<str>>>`-bound
2871/// diagnostic-column dispatch, a future wasm-operator's per-child
2872/// post-exit restart-decision pipeline whose
2873/// `.iter().map(std::sync::Arc::<str>::from)` collector reaches
2874/// into the shared-ownership per-arm key without a spurious [`Copy`]
2875/// deref (which would only be reachable through the owned-input
2876/// [`From<RestartPolicy> for std::sync::Arc<str>`] axis by first
2877/// calling `.copied()` on the iterator), a future
2878/// `<T: Into<std::sync::Arc<str>>>`-bound `tracing`-span attributes
2879/// collector recording a borrowed-`&RestartPolicy` per-arm field
2880/// onto the parent span's shared-ownership context — reaches the
2881/// same three-arm lifted
2882/// [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
2883/// [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
2884/// [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`] const the
2885/// paired owned-input [`From<RestartPolicy> for std::sync::Arc<str>`]
2886/// impl and the sibling `{&'static str, String, Cow<'static, str>,
2887/// Box<str>}` forward-projection corner already return.
2888///
2889/// Closes the substrate-wide trait-idiomatic
2890/// [`std::sync::Arc<str>`] forward-projection family opened one
2891/// commit prior (b05724e) on the paired owned-input
2892/// [`From<RestartPolicy> for std::sync::Arc<str>`] impl — closes
2893/// the `{Self, &Self}` input-shape corner of the
2894/// [`std::sync::Arc<str>`] axis on the second (and third-and-final)
2895/// M2 OTP-shape closed-set fieldless typed enum peer on the caixa
2896/// surface, exactly as b3e72d7 closed the paired
2897/// [`std::sync::Arc<str>`] corner on the sibling-restart
2898/// [`RestartStrategy`] first-mover one commit after its owning half
2899/// (bca2ec8) landed, and as cb1d068 closed the paired [`Box<str>`]
2900/// corner on this enum one commit after its owning half (0a1b313)
2901/// landed. Rust's standard library carries `impl From<&str> for
2902/// std::sync::Arc<str>` and `impl From<String> for
2903/// std::sync::Arc<str>` but no blanket `impl<T: AsRef<str>> From<&T>
2904/// for std::sync::Arc<str>` (nor a `Copy`-based `impl<T: Copy,
2905/// U: From<T>> From<&T> for U`), so every closed-set fieldless typed
2906/// enum peer on the substrate that carries the paired owned-input
2907/// [`std::sync::Arc<str>`] axis but not the borrowed-input axis
2908/// forces every borrowed-input [`std::sync::Arc<str>`]-parameterized
2909/// call site through a spurious [`Copy`] deref
2910/// (`std::sync::Arc::<str>::from((*policy).as_str())`) or a
2911/// `std::sync::Arc::<str>::from(policy.as_str())` open-code whose
2912/// type bounds have no compile-time link back to the substrate
2913/// primitive.
2914///
2915/// Pinned load-bearing by
2916/// [`tests::restart_policy_from_borrowed_into_arc_str_routes_through_as_str_accessor`]
2917/// (byte-parity pin against [`RestartPolicy::as_str`] across the
2918/// three-arm [`RestartPolicy::ALL`] emit-set on the borrowed-input
2919/// surface, plus a blanket-derived [`Into`] shape witness, a
2920/// cross-axis pin against the paired owned-input
2921/// [`From<RestartPolicy> for std::sync::Arc<str>`] and the sibling
2922/// borrowed-input `{&'static str, String, Cow<'static, str>,
2923/// Box<str>}` return-shape axes, and a
2924/// `.iter().map(std::sync::Arc::<str>::from)` pipe witness over
2925/// [`RestartPolicy::ALL`]).
2926impl From<&RestartPolicy> for std::sync::Arc<str> {
2927 fn from(policy: &RestartPolicy) -> std::sync::Arc<str> {
2928 std::sync::Arc::<str>::from(policy.as_str())
2929 }
2930}
2931
2932/// Trait-idiomatic byte-view surface on the per-child restart-decision
2933/// policy typed enum.
2934///
2935/// Every consumer that binds its input through the standard-library
2936/// [`AsRef<[u8]>`] trait bound — a byte-keyed
2937/// `HashMap<K: AsRef<[u8]>, V>` per-policy reconciliation-decision
2938/// table lookup on the future wasm-operator supervisor scheduler; a
2939/// `blake3::Hasher::update` / `ring::digest::Context::update` /
2940/// `sha2::Sha256::update` byte-input surface on any future per-child
2941/// content-address digest folded into the [`crate::Lacre`] closure so
2942/// downstream cache-keys partition on the three OTP restart policies
2943/// (`Permanent`, `Temporary`, `Transient`) at content-address time; an
2944/// `std::io::Write::write_all`-bound structured-log per-arm byte-sink —
2945/// reaches the substrate primitive through one trait dispatch rather
2946/// than open-coding the two-hop `restart.as_str().as_bytes()`
2947/// composition at every call site. Routed byte-for-byte through the
2948/// [`RestartPolicy::as_str`] `pub const fn` accessor the paired
2949/// str-view ([`AsRef<str>`], [`std::fmt::Display`],
2950/// [`RestartPolicy::as_str`]) and the five reverse-projection
2951/// (`&'static str`, `String`, `Cow<'static, str>`, `Box<str>`,
2952/// `std::sync::Arc<str>`) return-shape axes already resolve through,
2953/// so any future divergence between the byte-view and str-view axes
2954/// trips at caixa-core test time rather than at a downstream byte-
2955/// consumer's silent split.
2956///
2957/// Peer of the sibling per-supervisor-restart-strategy axis
2958/// [`AsRef<[u8]> for RestartStrategy`] (cd4c4e0, the first M2-OTP-
2959/// shape supervisor slot enum to open this axis) — the sixth
2960/// closed-set fieldless typed enum on the caixa surface to converge
2961/// onto the trait-idiomatic byte-view discipline, and the second (and
2962/// final) M2-OTP-shape sibling to pick it up, closing the byte-view
2963/// axis across the paired `:supervisor :estrategia` +
2964/// `:children :restart` M2 slot pair. Pin load-bearing by the paired
2965/// [`tests::restart_policy_as_ref_bytes_routes_through_as_str_accessor`]
2966/// (fail-before-pass-after byte-parity pin against
2967/// [`RestartPolicy::as_str`] `.as_bytes()` across the three-arm
2968/// [`RestartPolicy::ALL`] emit-set, cross-axis witness against the
2969/// paired str-view [`AsRef<str>`] / [`std::fmt::Display`] /
2970/// [`RestartPolicy::as_str`] axes' `.as_bytes()` byte-tails,
2971/// cross-axis witness against the paired reverse-projection
2972/// `{&'static str, String, Cow<'static, str>, Box<str>,
2973/// std::sync::Arc<str>}` return-shape axes' `.as_bytes()` byte-tails,
2974/// a `<T: AsRef<[u8]>>`-bound-consumer witness that a generic
2975/// byte-input function accepts a [`RestartPolicy`] directly through
2976/// the trait bound, and a `blake3::Hasher::update`-shape byte-input
2977/// surface witness routed through the `<T: AsRef<[u8]>>`-bound
2978/// consumer axis to reach the caixa-lacre compounding target). Any
2979/// future silent detour that routes the byte-view impl off the
2980/// substrate-primitive [`RestartPolicy::as_str`] accessor (a per-arm
2981/// inline `b"Permanent".as_slice()`-shaped re-inlining that opens a
2982/// compile-time link to the un-lifted arm-literal, a swap onto the
2983/// kebab-case [`gen_platform::Discriminant`] catalog identity that
2984/// would collide the wire axis with the dispatcher-catalog axis) trips
2985/// at caixa-core test time rather than at a downstream byte-consumer's
2986/// silent split.
2987impl AsRef<[u8]> for RestartPolicy {
2988 fn as_ref(&self) -> &[u8] {
2989 self.as_str().as_bytes()
2990 }
2991}
2992
2993/// Trait-idiomatic *owned-input, owned-`Vec<u8>` output* byte-owned
2994/// reverse projection on the second (and final) M2 OTP-shape closed-set
2995/// fieldless typed enum peer on the caixa surface ([`RestartPolicy`]) —
2996/// the byte-mirror of the [`From<RestartPolicy> for String`] str-owned
2997/// reverse-projection axis and the owned-`Vec<u8>` reverse-projection
2998/// sibling of the paired [`AsRef<[u8]>`] borrowed byte-view axis
2999/// (98b08fa) lifted on this same enum. Routes byte-for-byte through
3000/// the substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
3001/// accessor via [`str::as_bytes`] + [`slice::to_vec`] so every
3002/// consumer that binds a [`RestartPolicy`] through the standard-
3003/// library `impl From<RestartPolicy> for Vec<u8>` axis
3004/// (equivalently `<T: Into<Vec<u8>>>`) — a future
3005/// [`std::io::Write::write_all`]-shape per-child audit-log byte-sink
3006/// whose input parameter is an owned [`Vec<u8>`] payload, a future
3007/// `bytes::Bytes::from(Vec::<u8>::from(restart))` composer folding
3008/// the per-arm restart-decision-policy byte-tag into the
3009/// [`bytes::Bytes`] framing surface, a future
3010/// `hasher.update(&Vec::<u8>::from(restart))`-shape BLAKE3 content-
3011/// address closure that needs the owned byte-tail buffered before
3012/// folding into the [`crate::Lacre`] closure body, a future per-child
3013/// protobuf/CBOR/msgpack payload composer whose framer takes an owned
3014/// [`Vec<u8>`] rather than a borrowed byte-slice — reaches the
3015/// substrate primitive through one trait dispatch rather than an
3016/// open-coded per-call-site `restart.as_str().as_bytes().to_vec()`
3017/// composition whose type bounds have no compile-time link back to
3018/// the substrate primitive.
3019///
3020/// Closes the substrate-wide trait-idiomatic byte-owned reverse-
3021/// projection axis on the M2-OTP-shape `:supervisor :estrategia` +
3022/// `:children :restart` slot pair the sibling
3023/// [`RestartStrategy`] first-mover (63e5dd0) opened one commit prior,
3024/// matching the discipline the paired [`AsRef<[u8]>`] borrowed byte-
3025/// view axis campaign already carried across the same slot pair
3026/// (cd4c4e0 → 98b08fa). Every future arm addition (an OTP-
3027/// `intrinsic` fourth arm the theory
3028/// [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
3029/// might reach for once the three canonical OTP restart policies
3030/// stop covering the substrate's discovered load-shape) grows the
3031/// byte-owned axis through one edit on the substrate-primitive
3032/// [`RestartPolicy::as_str`] accessor.
3033///
3034/// Pinned load-bearing by
3035/// [`tests::restart_policy_from_into_owned_vec_bytes_routes_through_as_str_accessor`]
3036/// (byte-parity pin against [`RestartPolicy::as_str`] across the
3037/// three-arm [`RestartPolicy::ALL`] emit-set binding the byte-owned
3038/// reverse-projection axis against the paired [`AsRef<[u8]>`]
3039/// borrowed byte-view axis and the str-owned reverse-projection
3040/// family (`String`, `Cow<'static, str>`, `Box<str>`,
3041/// `std::sync::Arc<str>`) `.into_bytes()` / `.as_bytes().to_vec()`
3042/// byte-tails, a `<T: Into<Vec<u8>>>`-bound generic-consumer witness,
3043/// and a `std::io::Write::write_all`-shape owned-byte-sink surface
3044/// witness on both owned and borrowed input shapes).
3045impl From<RestartPolicy> for Vec<u8> {
3046 fn from(policy: RestartPolicy) -> Vec<u8> {
3047 policy.as_str().as_bytes().to_vec()
3048 }
3049}
3050
3051/// Trait-idiomatic *borrowed-input, owned-`Vec<u8>` output* byte-
3052/// owned reverse projection on the second (and final) M2 OTP-shape
3053/// closed-set fieldless typed enum peer on the caixa surface
3054/// ([`RestartPolicy`]) — the borrowed-input peer of
3055/// [`From<RestartPolicy> for Vec<u8>`], closing the
3056/// `{Self, &Self} → Vec<u8>` pair on the byte-owned reverse-projection
3057/// axis in one lift. Routes byte-for-byte through the substrate-
3058/// primitive [`RestartPolicy::as_str`] `pub const fn` accessor so
3059/// every consumer that holds a borrowed [`&RestartPolicy`] and needs
3060/// an owned [`Vec<u8>`] — a future
3061/// `.iter().map(Vec::<u8>::from).collect()` pipe over
3062/// `&[RestartPolicy]` (whose iterator yields `&RestartPolicy`,
3063/// not `RestartPolicy`, so the owned-input axis alone forces every
3064/// call site through an explicit `.copied()` / spurious [`Copy`]
3065/// deref restatement rather than the direct trait-idiomatic
3066/// projection), a future admission-webhook rejection body composer
3067/// that walks [`RestartPolicy::ALL`] through an `Into<Vec<u8>>`-
3068/// bound per-arm byte-writer to surface the accepted `:children
3069/// :restart` set — reaches the substrate primitive through one
3070/// trait dispatch rather than a `Vec::<u8>::from(*policy)` spurious-
3071/// [`Copy`]-deref restatement.
3072impl From<&RestartPolicy> for Vec<u8> {
3073 fn from(policy: &RestartPolicy) -> Vec<u8> {
3074 policy.as_str().as_bytes().to_vec()
3075 }
3076}
3077
3078/// Trait-idiomatic *borrowed byte-slice input* reverse projection on the
3079/// second (and final) M2-OTP-shape closed-set fieldless typed enum peer on
3080/// the caixa surface ([`RestartPolicy`]) — the byte-view mirror of the
3081/// str-view reverse-projection axis carried by the paired
3082/// [`TryFrom<&str> for RestartPolicy`] impl (which routes through the
3083/// substrate-primitive [`RestartPolicy::from_wire`] `Option<Self>` accessor
3084/// on the three-arm `PascalCase` accept-set the sibling
3085/// [`RestartPolicy::as_str`] emitter returns). Routes byte-for-byte through
3086/// the standard-library [`std::str::from_utf8`] UTF-8 validator and then
3087/// through [`RestartPolicy::from_wire`] so every consumer that holds a
3088/// borrowed [`&[u8]`] and needs to project it back into a typed
3089/// [`RestartPolicy`] — a future `bytes::Bytes::as_ref()`-fed reader that
3090/// parses a per-child `:restart` `PascalCase` wire scalar from an
3091/// already-borrowed framing byte-tail (a
3092/// `tracing::field::valuable::Value::Bytes` recorder on the future
3093/// wasm-operator's per-child restart-decision diagnostic emission path, a
3094/// future audit-report re-loader binding a prior
3095/// [`RestartPolicy::as_str`] output from a mmap'd byte-slice back through
3096/// the typed enum for cross-run comparison), a future M4
3097/// `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook rejection body
3098/// that reads a `spec.children[].restart` field off a raw HTTP body
3099/// byte-slice before UTF-8 validation commits allocation, a future generic
3100/// `<T: for<'a> TryFrom<&'a [u8]>>`-bound loader over any of the
3101/// substrate's closed-set typed enums — reaches the same three-arm
3102/// `PascalCase` wire accept-set the sibling method-named
3103/// [`RestartPolicy::from_wire`] resolver and the paired trait-idiomatic
3104/// [`TryFrom<&str>`] axis already resolve against, rather than an open-
3105/// coded per-call-site
3106/// `std::str::from_utf8(bytes).ok().and_then(RestartPolicy::from_wire)`
3107/// composition or a
3108/// `<RestartPolicy as TryFrom<&str>>::try_from(std::str::from_utf8(bytes)?)`
3109/// two-hop shape whose type bounds have no compile-time link to the
3110/// substrate primitive.
3111///
3112/// Closes the substrate-wide trait-idiomatic *byte-view reverse-projection*
3113/// family on the M2-OTP-shape `:supervisor :estrategia` + `:children
3114/// :restart` slot pair the sibling [`RestartStrategy`] first-mover
3115/// (c699a83) opened one commit prior — extends the family from
3116/// [`crate::CaixaKind`] (18d1940), [`crate::CaixaDialeto`] (d102cb8),
3117/// [`crate::dep::DepList`] (b8f25d5), and [`RestartStrategy`] (c699a83)
3118/// onto the second (and final) M2-OTP-shape closed-set fieldless typed
3119/// enum peer on the caixa surface, matching the trajectory the paired
3120/// byte-owned reverse-projection axis campaign already walked across the
3121/// same slot pair (63e5dd0 → 96a522a). Rust's standard library carries no
3122/// blanket `impl<T: for<'a> TryFrom<&'a str>> TryFrom<&[u8]> for T`, so a
3123/// two-hop composition through [`std::str::from_utf8`] + the paired
3124/// [`TryFrom<&str>`] axis is reachable at every call site but has no
3125/// compile-time link back to the byte-view reverse-projection axis. Every
3126/// remaining closed-set fieldless typed enum peer on the substrate
3127/// ([`crate::aplicacao::PlacementStrategy`],
3128/// [`crate::aplicacao::RateLimitUnit`], [`crate::aplicacao::WitShape`],
3129/// and the outside-`caixa-core` peers `PathShapeViolation`,
3130/// `InvariantKind`, `ArchVerdict`, `Severity`, `FixSafety`, `Semantic`,
3131/// `FerriteRuntime`) is a future target of the campaign.
3132///
3133/// `type Error = ()` matches the sibling [`RestartPolicy::from_wire`]'s
3134/// `Option<Self>` return-shape's deliberate deferral of error typing and
3135/// the paired trait-idiomatic [`TryFrom<&str>`] axis's unit-error shape —
3136/// the caller picks the diagnostic form appropriate for its use site (a
3137/// future `feira supervisor --restart …` arg-parse composes its own
3138/// per-verb "unknown restart policy: <arg> — accepted: {…}" message
3139/// enumerating [`RestartPolicy::WIRE_NAMES`]; a future admission-webhook
3140/// rejection body wraps the `Err(())` outcome with the accepted-set
3141/// enumeration for operator diagnostics; a `Result::map_err` at the call
3142/// site lifts the unit-error to a per-verb error type). Two rejection
3143/// paths route through the single unit-error: an invalid UTF-8
3144/// byte-sequence ([`std::str::from_utf8`] returns `Err`) and a valid UTF-8
3145/// byte-string that falls outside the three-arm `PascalCase` accept-set
3146/// ([`RestartPolicy::from_wire`] returns `None`) — both collapse onto
3147/// `Err(())` so the trait signature stays consistent with the sibling
3148/// str-view reverse axis, and a caller that needs to distinguish the two
3149/// failure modes composes [`std::str::from_utf8`] +
3150/// [`RestartPolicy::from_wire`] explicitly.
3151///
3152/// Pinned load-bearing by
3153/// [`tests::restart_policy_try_from_bytes_routes_through_from_wire_accessor`]
3154/// (byte-parity pin against [`RestartPolicy::from_wire`] across the
3155/// three-arm [`RestartPolicy::ALL`] accept-set on the borrowed byte-slice
3156/// surface, plus a cross-axis witness that the byte-view reverse
3157/// projection agrees with the paired [`TryFrom<&str>`] str-view reverse
3158/// axis on every accepted arm, and a forward/reverse byte-view cross-axis
3159/// witness that feeding the paired [`AsRef<[u8]>`] byte-tail back through
3160/// the new impl round-trips to the originating arm) and
3161/// [`tests::restart_policy_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
3162/// (rejection witness against silent accept-set widening on both the
3163/// non-UTF-8 byte-sequence rejection path and the unknown-wire-vocabulary
3164/// rejection path — the latter includes the sibling kebab-case
3165/// dispatcher-catalog byte-strings on the two-axis wire/catalog split so
3166/// a caller that confuses the two axes trips here rather than at a
3167/// downstream K8s-CR round-trip miss).
3168impl TryFrom<&[u8]> for RestartPolicy {
3169 type Error = ();
3170
3171 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
3172 std::str::from_utf8(bytes)
3173 .ok()
3174 .and_then(Self::from_wire)
3175 .ok_or(())
3176 }
3177}
3178
3179// Fleet-wide dispatcher-catalog registrations for caixa's OTP
3180// supervisor surface — two more typed shadows over Erlang/OTP
3181// primitives the substrate now mechanically tracks (see
3182// theory/UNIFIED-COMPUTING-MODEL.md §VI for the roadmap +
3183// theory/TYPED-ABSORPTION.md for the absorption arc).
3184gen_platform::register_dispatcher!("caixa.restart-strategy", RestartStrategy);
3185gen_platform::register_dispatcher!("caixa.restart-policy", RestartPolicy);
3186
3187/// One child entry in the supervisor's `:children` list.
3188///
3189/// Every child references another caixa by `:caixa <nome>` + version
3190/// constraint. The supervisor materializes one ComputeUnit per entry.
3191#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
3192#[serde(rename_all = "camelCase")]
3193pub struct ChildSpec {
3194 /// The child caixa's `:nome`. Must resolve via the same dependency
3195 /// resolution path as `:deps` (caixa-resolver).
3196 pub caixa: String,
3197
3198 /// Semver constraint (`"^0.1"`, `"~0.1.2"`, etc.) — same shape as
3199 /// [`crate::dep::Dep::versao`].
3200 pub versao: String,
3201
3202 /// Restart policy — an author-omitted slot degrades onto the
3203 /// substrate-canonical [`SUPERVISOR_CHILD_RESTART_DEFAULT`]
3204 /// (`permanent`, the Erlang/OTP worker-child default) through the
3205 /// [`Default for RestartPolicy`] impl this `#[serde(default)]` routes
3206 /// to.
3207 #[serde(default)]
3208 pub restart: RestartPolicy,
3209}
3210
3211impl ChildSpec {
3212 /// Substrate-canonical per-`:children` child-caixa `:nome` scalar
3213 /// accessor every consumer that reads the OTP-shape supervised
3214 /// child's identity keys off — returns the author-declared
3215 /// `:children :caixa` byte-string verbatim as a `&str`, borrowed
3216 /// from the typed slot's own [`String`] storage.
3217 ///
3218 /// The `:children :caixa` slot carries the DNS-1123 label — the
3219 /// child caixa's `:nome` — that every emitted cluster artifact
3220 /// derives its `metadata.name` from verbatim: the rendered
3221 /// `wasm.pleme.io/v1alpha1/ComputeUnit.metadata.name` per child, the
3222 /// [`crate::LABEL_PROGRAM`] label value on every child's pod
3223 /// identity, and the per-child K8s Service `metadata.name` the
3224 /// future wasm-operator (M3) provisions for inter-child supervision-
3225 /// tree wiring. Every downstream consumer that fans on the child's
3226 /// caixa-name keys off this scalar (the [`SupervisorSpec::validate`]
3227 /// per-child DNS-1123 gate at
3228 /// `require_valid_dns_1123_label(child.nome(), …)`, the per-child
3229 /// duplicate-detection [`crate::render::insert_first_seen`] key, the
3230 /// [`validate_no_self_supervision`] cross-slot equality check
3231 /// against the parent's `:nome`, every `SupervisorError` variant
3232 /// carrying the offending child caixa verbatim for `feira lint`
3233 /// rendering, the future wasm-operator's hierarchical reconciliation
3234 /// scheduler's per-child ComputeUnit-name projection, the future M4
3235 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-child
3236 /// admission webhook).
3237 ///
3238 /// Prior to this lift the `.caixa` byte-string was accessed inline
3239 /// at seven sites in `supervisor.rs` — the DNS-1123 gate's
3240 /// `&child.caixa`, the four `SupervisorError::{ChildCaixaInvalid,
3241 /// EmptyChildVersion, ChildVersaoInvalid, DuplicateChildCaixa}`
3242 /// carriers' `child.caixa.clone()`, the dedup key's
3243 /// `child.caixa.as_str()`, and the [`validate_no_self_supervision`]
3244 /// `child.caixa == parent_nome` cross-slot check — seven open-coded
3245 /// field-accesses that expressed no compile-time link back to the
3246 /// typed slot. A future extension of the `:children :caixa` axis to
3247 /// a richer author surface (a per-cluster alias table the operator
3248 /// pins through a future `:placement`-scoped slot on the supervisor
3249 /// tree, a namespace-qualified rewrite the M4 CR materializer
3250 /// applies per-CR, a per-child overlay from the future `:children
3251 /// :nome-suffix` slot the MESH-COMPOSITION §III.2 roadmap
3252 /// acknowledges) would have had to be threaded through every
3253 /// open-coded copy in lockstep or one consumer would silently
3254 /// disagree with the peers on which caixa a given child resolves to
3255 /// — a child-set lookup that treated the name as `"cart-worker"`
3256 /// while the peer duplicate-detector treated it as
3257 /// `"tenant-a/cart-worker"` would silently split the
3258 /// `DuplicateChildCaixa` membership-lookup diagnostic from the
3259 /// self-supervision detector's parent-equality check, a two-consumer
3260 /// split at the validator far from the source `caixa.lisp` with no
3261 /// field naming the identity-drift root cause. Lifting the resolution
3262 /// rule to a typed method on the substrate primitive means every
3263 /// downstream consumer of the Supervisor's per-`:children` identity
3264 /// surface reaches for exactly one typed dispatch — the resolver's
3265 /// accept-set migrates as a unit on any future axis addition.
3266 ///
3267 /// Sibling of the peer per-`:membros` [`crate::Membro::nome`]
3268 /// (4a32abf) member-caixa `:nome` scalar accessor on the M3
3269 /// mesh-slot surface — same "one typed dispatch on the substrate
3270 /// primitive, thin projections at each consumer" discipline extended
3271 /// onto the M2 supervisor-tree per-`:children` child-identity axis.
3272 /// The two typed axes (`Membro::nome` on the M3 Aplicacao side,
3273 /// `ChildSpec::nome` on the M2 Supervisor side) now share one
3274 /// accessor discipline for the shared substrate concept "another
3275 /// caixa referenced by `:nome`". Peer of the second M2 slot scalar
3276 /// accessor [`crate::UpgradeFromEntry::prior_versao`] (75d27a8) on
3277 /// the sibling per-`:upgrade-from :from` OTP-appup axis — the M2
3278 /// slot family's typed-accessor discipline now spans both the
3279 /// upgrade axis (`:upgrade-from`) and the supervision axis
3280 /// (`:children`), matching the closed M3 mesh-slot accessor family's
3281 /// shape. Named `nome()` to match the tatara-lisp author-surface
3282 /// term the field's docstring already reaches for ("The child
3283 /// caixa's `:nome`") and the peer [`crate::Membro::nome`] /
3284 /// [`crate::Caixa::nome`] / [`crate::dep::Dep::nome`] field-name
3285 /// discipline the substrate already carries — the accessor's name
3286 /// maps directly onto the canonical caixa-identity vocabulary rather
3287 /// than shadowing the field's storage-side `caixa` label.
3288 #[must_use]
3289 pub const fn nome(&self) -> &str {
3290 self.caixa.as_str()
3291 }
3292
3293 /// Substrate-canonical per-`:children` child-caixa `:versao` semver-
3294 /// requirement scalar accessor every consumer that reads the OTP-shape
3295 /// supervised child's version pin keys off — returns the author-declared
3296 /// `:children :versao` byte-string verbatim as a `&str`, borrowed from
3297 /// the typed slot's own [`String`] storage.
3298 ///
3299 /// The `:children :versao` slot carries the Cargo-shaped semver
3300 /// requirement string (`"^0.1"`, `"~0.1.2"`, `"0.1.0"`, `"*"`) that pins
3301 /// which release of the supervised child caixa the OTP-shape supervisor
3302 /// tree materializes against — the same requirement grammar the peer
3303 /// `:deps :versao` / `:membros :versao` axes carry, resolved through the
3304 /// shared [`crate::render::require_valid_versao_requirement`] cascade
3305 /// and the shared [`crate::version::parse_requirement`] parser. Every
3306 /// downstream consumer that fans on the child's version pin keys off
3307 /// this scalar (the [`SupervisorSpec::validate`] per-child requirement
3308 /// gate at `require_valid_versao_requirement(child.versao_requirement(),
3309 /// …)`, the [`SupervisorError::ChildVersaoInvalid`] variant's carrier
3310 /// for `feira lint` rendering, every future per-cluster version-lock
3311 /// overlay the caixa-operator's hierarchical reconciliation scheduler
3312 /// pins through a future `:placement`-scoped supervisor-tree slot, the
3313 /// future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
3314 /// per-child version resolver, the future wasm-operator's per-child
3315 /// lacre BLAKE3-closure lookup at `ComputeUnit` materialization time).
3316 ///
3317 /// Prior to this lift the `.versao` byte-string was accessed inline at
3318 /// two `&str`-shaped sites in `caixa-core/src/supervisor.rs` — the
3319 /// [`SupervisorSpec::validate`] requirement-gate call
3320 /// `require_valid_versao_requirement(&child.versao, …)` and the
3321 /// [`SupervisorError::ChildVersaoInvalid`] carrier at
3322 /// `versao: child.versao.clone()` — two open-coded field-accesses that
3323 /// expressed no compile-time link back to the typed slot. A future
3324 /// extension of the `:children :versao` axis to a richer author surface
3325 /// (a per-cluster version-pin overlay per MESH-COMPOSITION §III.2 canary
3326 /// flow, a lacre-projected concrete-version rewrite the operator
3327 /// materializes at CR-admission time, a future `:children :versao-lock`
3328 /// per-cluster override slot the wasm-operator's hierarchical
3329 /// reconciliation scheduler authors per-CR) would have had to be
3330 /// threaded through both open-coded copies in lockstep or one consumer
3331 /// would silently disagree with the peer on which release constraint a
3332 /// given child resolves to — the requirement-gate call reading
3333 /// `"^0.1"` while the error-body carrier read `"tenant-a-pin/^0.1"`
3334 /// would silently split the `ChildVersaoInvalid` diagnostic quote from
3335 /// the actual gate rejection input, a two-consumer split at the
3336 /// validator far from the source `caixa.lisp` with no field naming the
3337 /// version-pin drift root cause. Lifting the resolution rule to a typed
3338 /// method on the substrate primitive means every downstream
3339 /// requirement-facing consumer of the Supervisor's per-`:children`
3340 /// version-pin surface reaches for exactly one typed dispatch — the
3341 /// resolver's accept-set migrates as a unit on any future axis addition.
3342 ///
3343 /// Sibling of the peer per-`:membros` [`crate::Membro::versao_requirement`]
3344 /// (a40b0e3) member-caixa `:versao` scalar accessor on the M3 mesh-slot
3345 /// surface — same "one typed dispatch on the substrate primitive, thin
3346 /// projections at each consumer" discipline extended onto the M2
3347 /// supervisor-tree per-`:children` child-version-pin axis. The two typed
3348 /// axes (`Membro::versao_requirement` on the M3 Aplicacao side,
3349 /// `ChildSpec::versao_requirement` on the M2 Supervisor side) now share
3350 /// one accessor discipline for the shared substrate concept "another
3351 /// caixa referenced by a Cargo-shaped semver requirement". Peer of the
3352 /// sibling per-`:children` [`ChildSpec::nome`] (57c61d0) child-caixa
3353 /// `:nome` scalar accessor — the pair
3354 /// `(nome(), versao_requirement())` jointly projects the
3355 /// `(caixa, versao)` field pair every OTP-shape supervisor-tree consumer
3356 /// that fans on per-child identity + version pin keys off, closing the
3357 /// last unlifted per-`:children` `String`-carry axis so every downstream
3358 /// per-`:children` reader now routes through a typed dispatch on the
3359 /// substrate primitive. Named `versao_requirement()` rather than
3360 /// `versao()` because the field's storage-side `.versao` label is
3361 /// already the author-surface term (`:versao`); the accessor's name
3362 /// carries the semantic role — the semver *requirement* string the
3363 /// shared [`crate::version::parse_requirement`] entry-point consumes —
3364 /// so a raw field access and a typed dispatch read differently at every
3365 /// consumer site. Matches the peer [`crate::Membro::versao_requirement`]
3366 /// naming discipline verbatim.
3367 #[must_use]
3368 pub const fn versao_requirement(&self) -> &str {
3369 self.versao.as_str()
3370 }
3371
3372 /// Substrate-canonical per-`:children` `:restart` OTP-shaped
3373 /// per-child post-exit restart-decision policy scalar accessor every
3374 /// consumer that dispatches on the supervised child's post-exit
3375 /// reconcile posture keys off — returns the author-declared
3376 /// `:children :restart` variant verbatim as a [`RestartPolicy`],
3377 /// `Copy`-projected from the typed slot's own [`RestartPolicy`]
3378 /// storage.
3379 ///
3380 /// The `:children :restart` slot carries the closed-set OTP-shaped
3381 /// per-child restart-decision policy discriminator
3382 /// ([`RestartPolicy::Permanent`] — always restart, the OTP `permanent`
3383 /// worker-child default; [`RestartPolicy::Transient`] — restart only
3384 /// on abnormal exit, the OTP `transient` clean-completion-aware
3385 /// default; [`RestartPolicy::Temporary`] — never restart, the OTP
3386 /// `temporary` one-shot default) that every downstream consumer of
3387 /// the Supervisor's per-child post-exit reconcile branch keys off.
3388 /// Every future downstream consumer that fans on the per-child
3389 /// restart-decision keys off this scalar (the future `feira app
3390 /// graph` per-child restart column, the future wasm-operator's
3391 /// per-child post-exit restart-decision branch, the future M4
3392 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-child
3393 /// admission webhook, the `caixa-operator`'s hierarchical
3394 /// reconciliation scheduler's per-child post-exit reconcile branch,
3395 /// the [`RestartPolicy::as_str`] `Serialize`-derive-pinning path the
3396 /// [`tests::restart_policy_variants_serialize_to_lifted_scalar_values`]
3397 /// pin threads through).
3398 ///
3399 /// Peer of the sibling per-`:supervisor` [`SupervisorSpec::estrategia`]
3400 /// (eafb619) `Copy`-return [`RestartStrategy`] sibling-restart-strategy
3401 /// scalar accessor and the M3 mesh-slot
3402 /// [`crate::Placement::estrategia`] (921fe1b) `Copy`-return
3403 /// [`crate::PlacementStrategy`] distribution-strategy scalar accessor
3404 /// — same "one typed dispatch on the substrate primitive,
3405 /// `Copy`-projected closed-set enum-arm discriminator that partitions
3406 /// the downstream renderer's per-arm fan-out" discipline extended
3407 /// onto the M2 supervisor-slot per-`:children` restart-decision-policy
3408 /// `Copy`-composite-enum scalar axis. Third axis on the per-`:children`
3409 /// [`ChildSpec`] type — companion to the sibling per-`:children`
3410 /// [`ChildSpec::nome`] (57c61d0) child-caixa `:nome` scalar accessor
3411 /// and the per-`:children` [`ChildSpec::versao_requirement`]
3412 /// (2c053c8) child-caixa `:versao` semver-requirement scalar accessor
3413 /// on the sibling `String`-carry axes. The triple
3414 /// `(nome(), versao_requirement(), restart())` jointly projects the
3415 /// `(caixa, versao, restart)` field trio every OTP-shape supervisor-
3416 /// tree consumer that fans on per-child identity + version pin +
3417 /// restart-decision keys off, closing the last unlifted per-`:children`
3418 /// axis so every downstream per-`:children` reader now routes through
3419 /// a typed dispatch on the substrate primitive. Named `restart()` to
3420 /// match the storage field's name and the author-surface
3421 /// `:children :restart` slot term verbatim; the accessor's identity
3422 /// name maps onto the canonical OTP-shape per-child restart-decision-
3423 /// policy vocabulary the [`RestartPolicy`] enum's docstring already
3424 /// carries.
3425 ///
3426 /// Declared `pub const fn` to close the last non-`const`
3427 /// `Copy`-return raw-field-getter posture on the M2
3428 /// per-`:children` [`ChildSpec`] substrate-primitive surface — peer
3429 /// of the sibling M2 per-`:supervisor`
3430 /// [`SupervisorSpec::estrategia`] (converted in this commit)
3431 /// `Copy`-composite-enum accessor, the sibling M2 per-`:supervisor`
3432 /// [`SupervisorSpec::max_restarts`] (b698ec0) `Copy`-`u32` accessor
3433 /// already lifted, and the peer M3 mesh-slot per-`:entrada`
3434 /// [`crate::Entrada::port`] (bafa004) / per-`:placement`
3435 /// [`crate::Placement::estrategia`] (bafa004) `Copy`-return
3436 /// `pub const fn` scalar accessors on the sibling M3 surface. Every
3437 /// downstream substrate-side `const`-context consumer of the
3438 /// per-`:children` restart-decision-policy scalar (a future
3439 /// module-scope `const _:() = assert!(matches!(child.restart(),
3440 /// RestartPolicy::Permanent))` invariant pin on a typed fixture, a
3441 /// future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer
3442 /// admission-webhook `const fn` per-child restart-decision floor
3443 /// over a typed [`ChildSpec`], any future `const fn` supervisor-tree
3444 /// composer over the substrate primitive that fans on the per-child
3445 /// restart-decision policy at compile time) now reaches through the
3446 /// same typed dispatch on the substrate primitive at const-eval
3447 /// time as at runtime. A future non-`Copy`-return promotion of the
3448 /// scalar (an `Option<RestartPolicy>`-shape migration on the
3449 /// per-child restart-decision axis once heterogeneous per-cluster
3450 /// restart-policy overlays land, a per-tenant restart-policy-alias
3451 /// table the M4 CR materializer resolves per-CR) that would drop
3452 /// the `const` qualifier fails the fail-before-pass-after pin
3453 /// [`tests::child_spec_restart_accessor_is_const_fn`] at caixa-core
3454 /// build time rather than surfacing as a downstream consumer
3455 /// regression.
3456 #[must_use]
3457 pub const fn restart(&self) -> RestartPolicy {
3458 self.restart
3459 }
3460}
3461
3462/// Supervisor-typed slots that live alongside the standard Caixa
3463/// fields when `:kind Supervisor`. Held flat in [`crate::Caixa`] so
3464/// the manifest stays a single typed form; this struct exists for
3465/// validation + conversion.
3466#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
3467#[serde(rename_all = "camelCase")]
3468pub struct SupervisorSpec {
3469 /// Restart strategy. Defaults to [`RestartStrategy::OneForOne`].
3470 #[serde(default)]
3471 pub estrategia: RestartStrategy,
3472
3473 /// Max restarts within [`Self::restart_window`] before the
3474 /// supervisor itself terminates (and its parent supervisor decides
3475 /// what to do). Default 5.
3476 #[serde(default = "default_max_restarts")]
3477 pub max_restarts: u32,
3478
3479 /// Sliding window for `max_restarts`. Authored as a duration
3480 /// string (`"60s"`, `"5m"`); absent = "never reset". A `Some(0s)`
3481 /// is rejected by [`Self::validate`] — Erlang/OTP's
3482 /// `MaxIntensity / Period` invariant requires a positive window
3483 /// (a zero-period supervisor either trips on the first failure or
3484 /// never trips, depending on operator interpretation, neither of
3485 /// which is the author's intent). Omit the slot to express "no
3486 /// reset"; carry a positive duration to express the sliding window.
3487 #[serde(
3488 default,
3489 skip_serializing_if = "Option::is_none",
3490 with = "duration_codec"
3491 )]
3492 pub restart_window: Option<Duration>,
3493
3494 /// Static children. Empty for `SimpleOneForOne` (children added
3495 /// dynamically); required for the other three strategies.
3496 #[serde(default)]
3497 pub children: Vec<ChildSpec>,
3498}
3499
3500const fn default_max_restarts() -> u32 {
3501 // Route the private serde-`#[serde(default = "…")]` helper through
3502 // the substrate-canonical [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] typed
3503 // `pub const` rather than the raw `5` literal — one source of truth
3504 // for the Erlang/OTP-canonical `{intensity, 5, 60}` `MaxIntensity`
3505 // default across the two production consumers that currently
3506 // dispatch on it (this helper via `#[serde(default = "…")]` on
3507 // `SupervisorSpec::max_restarts` and the [`Default for SupervisorSpec`]
3508 // impl at line 962). Pinned by
3509 // `default_max_restarts_helper_routes_through_lifted_default` +
3510 // `supervisor_spec_default_max_restarts_routes_through_lifted_default`
3511 // in the tests module; peer of the sibling caixa-core
3512 // [`crate::manifest::Caixa::supervisor_view`] `unwrap_or(…)` fold
3513 // that now routes its author-omitted `:max-restarts` arm through
3514 // the same lifted constant.
3515 SUPERVISOR_MAX_RESTARTS_DEFAULT
3516}
3517
3518/// Substrate-canonical Erlang/OTP-shaped `MaxIntensity` restart-budget-
3519/// count default for the `:supervisor :max-restarts` axis — the
3520/// canonical `{intensity, 5, 60}` `MaxIntensity` half of Learn You Some
3521/// Erlang's worker-supervisor default, extracted as a typed `pub const`
3522/// so every substrate-side consumer that resolves "what
3523/// [`SupervisorSpec::max_restarts`] value does an author-omitted
3524/// `:max-restarts` slot degrade onto?" reaches for exactly one
3525/// substrate-primitive `u32`.
3526///
3527/// The `:max-restarts` default axis has two production consumers on the
3528/// substrate side today (both prior to this lift folded onto raw `5`
3529/// literals with no compile-time link back to a shared truth): the
3530/// serde-`#[serde(default = "default_max_restarts")]` helper on
3531/// [`SupervisorSpec::max_restarts`] that every author-omitted
3532/// `:supervisor :max-restarts` slot lands in past the derive-macro's
3533/// wire-format compose, and the [`crate::manifest::Caixa::supervisor_view`]
3534/// `.max_restarts().unwrap_or(5)` fold that every downstream consumer of
3535/// the composed [`SupervisorSpec`] altitude reaches through
3536/// (`feira app graph`, the future wasm-operator's per-supervisor
3537/// restart-intensity counter, the future M4
3538/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission
3539/// webhook, the caixa-operator's hierarchical reconciliation scheduler).
3540/// A pair of open-coded `5`s across two files that expressed no
3541/// compile-time link back to the shared OTP-canonical default — a
3542/// future rebrand of the default (a tightening to Elixir's
3543/// `Supervisor.max_restarts: 3`, a widening to a per-cluster overlay
3544/// the operator pins through a future
3545/// `:supervisor :max-restarts-overrides` slot the MESH-COMPOSITION
3546/// §III.2 supervision-canary roadmap acknowledges, a promotion of the
3547/// plain `u32` count to a richer `{MaxR, MaxT}` per-child-cohort
3548/// restart-budget-partition once the INSPIRATIONS §II.2 Erlang/OTP
3549/// per-child-cohort roadmap lands) would have had to be threaded
3550/// through both open-coded copies in lockstep or the wire-format
3551/// author-omitted arm and the view-construction author-omitted arm
3552/// would silently disagree on which restart-budget an omitted
3553/// `:max-restarts` resolves to (an author writing `:supervisor
3554/// (:max-restarts ())` would round-trip through serde with the new
3555/// default while `supervisor_view` silently continued to compose the
3556/// stale `5`, or vice versa), a two-consumer split at the composition
3557/// boundary far from the source `caixa.lisp` with no field naming the
3558/// default-drift root cause. Lifting the resolution rule to a typed
3559/// `pub const` on the substrate primitive means every downstream
3560/// consumer of the per-Supervisor default-restart-budget-count surface
3561/// reaches for exactly one substrate-primitive `u32` — the resolver's
3562/// accepted value migrates as a unit on any future axis change.
3563///
3564/// The `5` value pins Learn You Some Erlang's `{intensity, 5, 60}`
3565/// worker-supervisor default (the closest canonical OTP-shape
3566/// production reference the substrate carries, matching the sibling
3567/// `60s` `Period` default the [`Default for SupervisorSpec`] impl pairs
3568/// this constant with on the paired sliding-window axis). Two orders of
3569/// magnitude below the [`SUPERVISOR_MAX_RESTARTS_MAX`] `1000` ceiling
3570/// (the upper bracket on the same axis, sibling of this lower default;
3571/// both are typed `u32` const bounds on the `:supervisor :max-restarts`
3572/// axis and now share one accessor discipline on the substrate) and
3573/// above the OTP-`supervisor` callback-module `MaxR = 1` minimum-
3574/// restart floor — the "one restart, then escalate" default is
3575/// deliberately loose enough to absorb a short burst of transient
3576/// child failures without escalating past the supervisor's parent
3577/// while remaining tight enough to trip the `MaxIntensity / Period`
3578/// ratio's escalation on a genuinely-stuck child within the sibling
3579/// `60s` sliding window.
3580///
3581/// Lifted as a typed `pub const` so the bound has exactly one source
3582/// of truth — the serde-side wire-format author-omitted arm at
3583/// [`default_max_restarts`], the [`Default for SupervisorSpec`] impl's
3584/// struct-literal default field, and the caixa-core
3585/// [`crate::manifest::Caixa::supervisor_view`] fold's author-omitted
3586/// arm all read from one place. Same shape every other typed default
3587/// in this crate carries (the sibling
3588/// [`SUPERVISOR_MAX_RESTARTS_MAX`] upper cap on the same axis, the
3589/// paired [`SUPERVISOR_RESTART_WINDOW_MAX`] upper cap on the
3590/// sibling `:restart-window` axis, and the peer
3591/// [`crate::render::DEFAULT_NAMESPACE`] / [`crate::render::DEFAULT_LIBRARY_NAME`]
3592/// per-renderer defaults on the caixa-flux / caixa-helm rendering
3593/// axes).
3594pub const SUPERVISOR_MAX_RESTARTS_DEFAULT: u32 = 5;
3595
3596/// Upper-bound ceiling on the `:supervisor :max-restarts` axis — every
3597/// validated [`SupervisorSpec::max_restarts`] past
3598/// [`SupervisorSpec::validate`] lies in `1..=SUPERVISOR_MAX_RESTARTS_MAX`.
3599///
3600/// The typed field is `u32` (the zero-floor arm
3601/// [`SupervisorError::ZeroMaxRestarts`] already brackets the bottom edge),
3602/// so a programmatic struct literal
3603/// (`SupervisorSpec { max_restarts: u32::MAX, .. }`) and the equivalent
3604/// author-surface form (`:max-restarts 4294967295` or any
3605/// `:max-restarts 100000`-shape typo landing in the slot) both round-trip
3606/// cleanly through serde — a structurally unbounded `u32` ceiling. The
3607/// runtime substrate consuming the value (Erlang/OTP's
3608/// `MaxIntensity / Period` ratio, the future wasm-operator's
3609/// per-supervisor restart-intensity counter, the M4
3610/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission webhook)
3611/// then turned a typed `:max-restarts` policy into a no-op supervisor: the
3612/// escalation threshold is structurally so high that no realistic
3613/// restarts-per-`:restart-window` traffic shape can reach it, the
3614/// supervisor never escalates to its parent, and a bad child can loop
3615/// inside the window indefinitely with the parent supervisor structurally
3616/// never receiving the "this subtree has exceeded its restart budget"
3617/// signal the typed slot is meant to express — the canonical
3618/// "supervisor intensity declared, no escalation" footgun, exactly the
3619/// peer of the [`crate::aplicacao::POLICY_BREAKER_MAX_FAILURES_MAX`] cap
3620/// on the `:politicas :circuit-breaker :max-failures` axis (both are
3621/// "trip the next-higher protection layer after N events in a rolling
3622/// window" counters with identical degenerate-at-the-high-end shape).
3623///
3624/// The `1000` ceiling matches the sibling
3625/// [`crate::aplicacao::POLICY_BREAKER_MAX_FAILURES_MAX`] (the closest
3626/// peer — same "events-per-window trip threshold" semantics, same `u32`
3627/// type, same no-op-at-the-high-end failure mode) so the M4
3628/// `mesh.pleme.io/v1alpha1/Supervisor` / `.../Aplicacao` CR materializers
3629/// and the future wasm-operator's per-supervisor restart-intensity
3630/// counter reach for either field knowing the value is in `1..=1000`
3631/// without re-validating at the reconciler layer. The cap sits two
3632/// orders of magnitude above every documented Erlang/OTP production
3633/// playbook recommendation (Learn You Some Erlang's
3634/// `{intensity, 5, 60}` worker-supervisor default, Elixir's `Supervisor`
3635/// `max_restarts: 3` default, OTP's `supervisor` callback module
3636/// `MaxR = 1` / `MaxT = 5` "minimal-restart" default, Riak Core's
3637/// typical `MaxR ∈ 5..=100`, RabbitMQ's broker-supervisor `MaxR = 5`
3638/// default) and below the clearly-pathological "effectively no
3639/// escalation" floor (`10_000`, `100_000`, `u32::MAX`): a value the
3640/// author can plausibly want at hyperscale (a long-running supervisor
3641/// over a very-flaky pool tolerating thousands of transient restarts
3642/// before escalating), but a hard wall above which the typed policy is
3643/// structurally a no-op carried verbatim on every emitted child-restart
3644/// reconciliation contract.
3645///
3646/// Lifted as a typed `pub const` so the bound has exactly one source of
3647/// truth — the future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
3648/// materializer's admission webhook and the wasm-operator-side
3649/// per-supervisor restart-intensity reconciler read from one place. Same
3650/// shape every other typed upper bound in this crate carries
3651/// ([`crate::aplicacao::POLICY_BREAKER_MAX_FAILURES_MAX`],
3652/// [`crate::aplicacao::POLICY_RETRIES_MAX`],
3653/// [`crate::aplicacao::POLICY_RATE_LIMIT_MAX`],
3654/// [`crate::LIMITS_MEMORY_WASM32_MAX_BYTES`],
3655/// [`crate::render::DNS_1123_LABEL_MAX_LEN`],
3656/// [`crate::render::NATS_SUBJECT_MAX_LEN`]).
3657pub const SUPERVISOR_MAX_RESTARTS_MAX: u32 = 1000;
3658
3659/// Upper-bound ceiling on the `:supervisor :restart-window` axis —
3660/// every validated `Some(`[`SupervisorSpec::restart_window`]`)` past
3661/// [`SupervisorSpec::validate`] lies in `1ms..=SUPERVISOR_RESTART_WINDOW_MAX`
3662/// (inclusive on both ends, integer-millisecond magnitudes by the
3663/// canonical-form gate immediately preceding).
3664///
3665/// The typed field is `Option<Duration>` (the zero-floor arm
3666/// [`SupervisorError::RestartWindowZero`] already rejects
3667/// `Some(Duration::ZERO)`, and the canonical-form arm
3668/// [`SupervisorError::RestartWindowNotCanonical`] already rejects
3669/// sub-millisecond residue), so a programmatic struct literal
3670/// (`SupervisorSpec { restart_window: Some(Duration::from_secs(86_400)),
3671/// .. }` — 24h) and the equivalent author-surface form
3672/// (`(:supervisor (:restart-window "24h"))` — the shared duration codec
3673/// emits `"<n>h"` for any integer-hour magnitude) both round-trip
3674/// cleanly through serde — a structurally unbounded `Duration` ceiling.
3675/// A `:restart-window` value far above the documented Erlang/OTP
3676/// `MaxIntensity / Period` production-playbook band (Learn You Some
3677/// Erlang's `{intensity, 5, 60}` worker-supervisor `Period = 60s`
3678/// default, Elixir's `Supervisor` `max_seconds: 5` default, OTP's
3679/// `supervisor` callback module `MaxT = 5..=60` typical, Riak Core's
3680/// `MaxT ∈ 10s..=300s`, RabbitMQ broker-supervisor `MaxT = 5s` default)
3681/// degenerates the supervisor's restart-intensity counter into a
3682/// lifetime counter: the rolling failure-counting window is structurally
3683/// so long that transient restarts are never forgotten, so the
3684/// `MaxIntensity / Period` ratio degenerates from "trip the parent
3685/// supervisor when the child has exceeded its restart budget *within
3686/// the recent window*" to "trip the parent when the child has exceeded
3687/// its restart budget *over its lifetime*" — every transient restart
3688/// counts against the budget forever, the supervisor's reset semantic
3689/// never reaches the child, and the typed `:restart-window` slot
3690/// becomes a no-op rolling window carried on every emitted hierarchical
3691/// reconciliation contract. The canonical
3692/// rolling-window-degenerates-to-lifetime-counter footgun the sibling
3693/// [`crate::POLICY_BREAKER_WINDOW_MAX`] cap closes on the peer
3694/// `:politicas :circuit-breaker :window` axis with identical shape (both
3695/// are "rolling failure-counting window with a per-`Period` reset" Duration
3696/// axes whose lifetime-counter degenerate at the high end is the same
3697/// "the reset semantic never fires" CSE invariant violation).
3698///
3699/// The `1h` (3600s = `3_600_000` ms) ceiling matches the largest unit
3700/// the shared duration codec emits (`"<n>h"` for any integer-hour
3701/// magnitude) — every value in the canonical authoring form's
3702/// `<integer><unit>` grammar at or below this cap renders to a clean
3703/// canonical string — and matches the three sibling typed-`Duration`
3704/// caps already lifted to this surface
3705/// ([`crate::LIMITS_WALL_CLOCK_MAX`], [`crate::POLICY_TIMEOUT_MAX`],
3706/// [`crate::POLICY_BREAKER_WINDOW_MAX`]). All four typed-`Duration`
3707/// axes — per-process `:limits :wall-clock`, per-edge `:politicas
3708/// :timeout`, per-breaker `:politicas :circuit-breaker :window`, and
3709/// per-supervisor `:supervisor :restart-window` — now share a single
3710/// uniform top edge at the codec's largest emitted unit so the next
3711/// typed-slot wiring (the future wasm-operator's per-supervisor
3712/// `MaxIntensity / Period` reconciler, the M4
3713/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission
3714/// webhook, the `caixa-operator`'s hierarchical reconciliation
3715/// scheduler) reaches for any of the four knowing the value is in
3716/// `1ms..=1h` without re-validating at the renderer layer. The cap sits
3717/// two orders of magnitude above every documented Erlang/OTP / Elixir /
3718/// Riak Core / RabbitMQ production-playbook recommendation band
3719/// (`5s..=300s`) and below the clearly-pathological "rolling window
3720/// degenerates to lifetime counter" floor (`24h`, `7d`, `Duration::MAX`):
3721/// a value the author can plausibly want for a very-low-traffic
3722/// long-tail failure-restart window over a hyperscale-flaky child pool,
3723/// but a hard wall above which the rolling-window contract is
3724/// structurally a lifetime-counter contract.
3725///
3726/// Lifted as a typed `pub const` so the bound has exactly one source
3727/// of truth — the future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
3728/// materializer's admission webhook, the wasm-operator-side
3729/// per-supervisor `MaxIntensity / Period` reconciler, and the
3730/// `caixa-operator`'s hierarchical reconciliation scheduler all read
3731/// from one place. Same shape every other typed upper bound in this
3732/// crate carries ([`SUPERVISOR_MAX_RESTARTS_MAX`],
3733/// [`crate::aplicacao::POLICY_BREAKER_MAX_FAILURES_MAX`],
3734/// [`crate::aplicacao::POLICY_RETRIES_MAX`],
3735/// [`crate::aplicacao::POLICY_RATE_LIMIT_MAX`],
3736/// [`crate::LIMITS_MEMORY_WASM32_MAX_BYTES`],
3737/// [`crate::LIMITS_WALL_CLOCK_MAX`], [`crate::POLICY_TIMEOUT_MAX`],
3738/// [`crate::POLICY_BREAKER_WINDOW_MAX`],
3739/// [`crate::render::DNS_1123_LABEL_MAX_LEN`],
3740/// [`crate::render::NATS_SUBJECT_MAX_LEN`]).
3741pub const SUPERVISOR_RESTART_WINDOW_MAX: Duration = Duration::from_secs(3600);
3742
3743/// Substrate-canonical Erlang/OTP-shaped `Period` sliding-window-duration
3744/// default for the `:supervisor :restart-window` axis — the canonical
3745/// `{intensity, 5, 60}` `Period` half of Learn You Some Erlang's
3746/// worker-supervisor default, extracted as a typed `pub const` so every
3747/// substrate-side consumer that resolves "what
3748/// [`SupervisorSpec::restart_window`] value does an author-omitted
3749/// `:restart-window` slot degrade onto?" reaches for exactly one
3750/// substrate-primitive [`Duration`].
3751///
3752/// The `:restart-window` default axis has one production consumer on the
3753/// substrate side today: the [`Default for SupervisorSpec`] impl's
3754/// struct-literal `restart_window` field, which prior to this lift folded
3755/// onto a raw `Duration::from_secs(60)` literal with no compile-time link
3756/// back to the paired [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `MaxIntensity`
3757/// half of the same `{intensity, 5, 60}` OTP-canonical default. The
3758/// [`crate::manifest::Caixa::supervisor_view`] fold deliberately does
3759/// *not* fall back to this default on the sibling `:restart-window` axis
3760/// — an author-omitted `:supervisor :restart-window` composes to
3761/// `restart_window: None` (the shared codec's soft-swallow shape),
3762/// keeping author-declared intent ("no reset — never escalate on rolling
3763/// window") distinct from the [`Default for SupervisorSpec`] "canonical
3764/// 60s Period" arm every programmatic `SupervisorSpec::default()` caller
3765/// resolves to. Prior to this lift the paired `{intensity, 5, 60}` OTP
3766/// default was split across two files with no compile-time link between
3767/// the halves: [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] pinned the
3768/// `MaxIntensity` half at the substrate primitive while the `Period`
3769/// half rode as an open-coded literal at the composition site, so a
3770/// future coherent rebrand of the paired canonical (a tightening to
3771/// Elixir's `{max_restarts: 3, max_seconds: 5}`, a widening to a
3772/// per-cluster overlay the operator pins through a future
3773/// `:supervisor :restart-window-overrides` slot the MESH-COMPOSITION
3774/// §III.2 supervision-canary roadmap acknowledges, a promotion of the
3775/// paired constants to a per-child-cohort `{MaxR, MaxT}` restart-budget-
3776/// partition once the INSPIRATIONS §II.2 Erlang/OTP per-child-cohort
3777/// roadmap lands) would have had to migrate the `MaxIntensity` half
3778/// through the lifted constant and the `Period` half through a raw
3779/// literal in lockstep or the two halves of the same OTP-canonical
3780/// default would silently drift out of pairing. Lifting the resolution
3781/// rule to a typed `pub const` on the substrate primitive means the
3782/// paired OTP-canonical default migrates as one unit on any future
3783/// axis change.
3784///
3785/// The `60s` value pins Learn You Some Erlang's `{intensity, 5, 60}`
3786/// worker-supervisor default (the closest canonical OTP-shape
3787/// production reference the substrate carries, matching the paired
3788/// [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `5` `MaxIntensity` half this
3789/// constant is the `Period` denominator of on the same
3790/// `MaxIntensity / Period` restart-intensity ratio). Two orders of
3791/// magnitude below the [`SUPERVISOR_RESTART_WINDOW_MAX`] `3600s`
3792/// (`1h`) ceiling (the upper bracket on the same axis, sibling of
3793/// this lower default; both are typed [`Duration`] const bounds on the
3794/// `:supervisor :restart-window` axis and now share one accessor
3795/// discipline on the substrate) and above the OTP-`supervisor`
3796/// callback-module `MaxT = 5` seconds "minimal-window" floor — the "60s
3797/// rolling window" default is deliberately loose enough to absorb a
3798/// short burst of transient child failures without escalating past the
3799/// supervisor's parent while remaining tight enough for the paired
3800/// `MaxIntensity / Period` ratio's escalation to trip on a genuinely-
3801/// stuck child within a human-scale observation window.
3802///
3803/// Lifted as a typed `pub const` so the paired OTP-canonical default has
3804/// exactly one source of truth on each half — the sibling
3805/// [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `MaxIntensity` `5` half and this
3806/// `Period` `60s` half now share the same substrate-primitive lift
3807/// discipline. Same shape every other typed default in this crate
3808/// carries (the sibling [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] paired
3809/// `MaxIntensity` half on the same OTP-canonical `{intensity, 5, 60}`,
3810/// the sibling [`SUPERVISOR_RESTART_WINDOW_MAX`] upper cap on the same
3811/// axis, and the peer [`crate::render::DEFAULT_NAMESPACE`] /
3812/// [`crate::render::DEFAULT_LIBRARY_NAME`] per-renderer defaults on the
3813/// caixa-flux / caixa-helm rendering axes).
3814pub const SUPERVISOR_RESTART_WINDOW_DEFAULT: Duration = Duration::from_secs(60);
3815
3816/// Substrate-canonical Erlang/OTP-shaped sibling-restart-strategy default
3817/// for the `:supervisor :estrategia` axis — the canonical `one_for_one`
3818/// half of Learn You Some Erlang's `{one_for_one, intensity, 5, 60}`
3819/// worker-supervisor default, extracted as a typed `pub const` so every
3820/// substrate-side consumer that resolves "what
3821/// [`SupervisorSpec::estrategia`] variant does an author-omitted
3822/// `:estrategia` slot degrade onto?" reaches for exactly one substrate-
3823/// primitive [`RestartStrategy`].
3824///
3825/// The `:estrategia` default axis has three production consumers on the
3826/// substrate side today: the [`Default for RestartStrategy`] impl's
3827/// return arm, the [`Default for SupervisorSpec`] impl's struct-literal
3828/// `estrategia` field, and the
3829/// [`crate::manifest::Caixa::supervisor_view`] fold's
3830/// `.unwrap_or(SUPERVISOR_ESTRATEGIA_DEFAULT)` `Option<RestartStrategy>`
3831/// collapse arm — three entry points onto the same OTP-canonical
3832/// `one_for_one` value that prior to this lift folded onto a raw
3833/// `Self::OneForOne` arm at the [`Default for RestartStrategy`] impl and
3834/// implicit `RestartStrategy::default()` routes at the sibling consumers,
3835/// with no compile-time link back to the paired
3836/// [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `MaxIntensity` half + the paired
3837/// [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] `Period` half of the same
3838/// `{one_for_one, intensity, 5, 60}` OTP-canonical default. The paired
3839/// triple was split across three altitudes with no compile-time link
3840/// between the halves: the `MaxIntensity` half rode through the lifted
3841/// [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] constant (b698ec0) and the `Period`
3842/// half rode through the lifted [`SUPERVISOR_RESTART_WINDOW_DEFAULT`]
3843/// constant (f7dcd0e) while the `one_for_one` half rode as an open-coded
3844/// discriminator at the [`Default for RestartStrategy`] impl, so a future
3845/// coherent rebrand of the triple (Elixir's `{:one_for_one,
3846/// max_restarts: 3, max_seconds: 5}` — same strategy, different
3847/// intensity/period; an OTP `rest_for_one` widening once the substrate
3848/// discovers startup-order-coupled child cohorts as the more common
3849/// worker-supervisor default; a per-cluster overlay the operator pins
3850/// through a future `:estrategia-overrides` slot the MESH-COMPOSITION
3851/// §III.2 supervision-canary roadmap acknowledges) would have had to
3852/// migrate the `MaxIntensity` + `Period` halves through the lifted
3853/// constants and the `one_for_one` half through an open-coded arm in
3854/// lockstep or the three halves of the same OTP-canonical default would
3855/// silently drift out of pairing. Lifting the resolution rule to a typed
3856/// `pub const` on the substrate primitive means the paired OTP-canonical
3857/// worker-supervisor default migrates as one unit on any future axis
3858/// change.
3859///
3860/// The [`RestartStrategy::OneForOne`] value pins Learn You Some Erlang's
3861/// `{one_for_one, intensity, 5, 60}` worker-supervisor default (the
3862/// closest canonical OTP-shape production reference the substrate
3863/// carries, matching the paired [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `5`
3864/// `MaxIntensity` half and the paired [`SUPERVISOR_RESTART_WINDOW_DEFAULT`]
3865/// `60s` `Period` half). The `one_for_one` strategy — restart only the
3866/// failed child, leaving siblings untouched — is the default for tree-of-
3867/// independent-workers use cases the substrate's [`RestartStrategy`]
3868/// discriminator's own docstring already carries as the default arm; it
3869/// composes with the `{5, 60}` restart-intensity ratio to name the same
3870/// substrate-canonical "canonical worker-supervisor" shape the paired
3871/// halves close on their respective axes.
3872///
3873/// Lifted as a typed `pub const` so the paired OTP-canonical default has
3874/// exactly one source of truth on each of its three halves — the sibling
3875/// [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] `MaxIntensity` `5` half, the
3876/// sibling [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] `Period` `60s` half, and
3877/// this `one_for_one` strategy half now share the same substrate-
3878/// primitive lift discipline. Same shape every other typed default in
3879/// this crate carries (the sibling [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] +
3880/// [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] paired halves on the same OTP-
3881/// canonical `{one_for_one, intensity, 5, 60}`, the sibling
3882/// [`SUPERVISOR_MAX_RESTARTS_MAX`] + [`SUPERVISOR_RESTART_WINDOW_MAX`]
3883/// upper caps on the paired sibling axes, and the peer
3884/// [`crate::render::DEFAULT_NAMESPACE`] / [`crate::render::DEFAULT_LIBRARY_NAME`]
3885/// per-renderer defaults on the caixa-flux / caixa-helm rendering axes).
3886pub const SUPERVISOR_ESTRATEGIA_DEFAULT: RestartStrategy = RestartStrategy::OneForOne;
3887
3888/// Substrate-canonical Erlang/OTP-shaped per-child restart-decision-policy
3889/// default for the `:children :restart` axis — the OTP `permanent`
3890/// worker-child default (`{ChildId, StartFunc, permanent, …}` in a
3891/// `supervisor`'s `init/1` child-spec tuple), extracted as a typed
3892/// `pub const` so every substrate-side consumer that resolves "what
3893/// [`ChildSpec::restart`] variant does an author-omitted `:children
3894/// :restart` slot degrade onto?" reaches for exactly one substrate-
3895/// primitive [`RestartPolicy`].
3896///
3897/// Completes the OTP-shape supervisor-tree default set at the substrate
3898/// primitive. The per-`:supervisor` axis already carries all three of its
3899/// halves as lifted typed constants — [`SUPERVISOR_ESTRATEGIA_DEFAULT`]
3900/// (`one_for_one`, 95ffacc), [`SUPERVISOR_MAX_RESTARTS_DEFAULT`]
3901/// (`MaxIntensity` `5`, b698ec0), [`SUPERVISOR_RESTART_WINDOW_DEFAULT`]
3902/// (`Period` `60s`, f7dcd0e) — while the per-`:children` axis's own
3903/// OTP-canonical default rode as an open-coded `Self::Permanent` arm in
3904/// the [`Default for RestartPolicy`] impl, the last un-lifted default on
3905/// the M2 `:supervisor` slot family. The split mattered because the two
3906/// axes resolve *together* on every author-omitted supervisor: a
3907/// `(defcaixa :kind Supervisor :children ((:caixa "worker" :versao
3908/// "^0.1")))` with no `:estrategia` and no per-child `:restart` degrades
3909/// onto `{one_for_one, 5, 60}` through three lifted constants and onto
3910/// `permanent` through an open-coded enum arm, so a future coherent
3911/// rebrand of the OTP-shape default set (an Elixir-shaped
3912/// `{:one_for_one, max_restarts: 3, max_seconds: 5}` tightening, a
3913/// per-cluster overlay the operator pins through the MESH-COMPOSITION
3914/// §III.2 supervision-canary roadmap slots, an OTP-`transient` widening
3915/// once the substrate discovers clean-completion-aware children as the
3916/// more common child shape) would have had to migrate three halves
3917/// through typed constants and the fourth through a raw enum arm in
3918/// lockstep or the supervisor-level and child-level defaults would
3919/// silently drift apart.
3920///
3921/// The `:children :restart` default axis has two production consumers on
3922/// the substrate side today: the [`Default for RestartPolicy`] impl's
3923/// return arm, and the serde-side `#[serde(default)]` on
3924/// [`ChildSpec::restart`] that resolves an author-omitted `:children
3925/// :restart` slot through that same impl. Both now key off this one
3926/// substrate primitive, so the future wasm-operator's per-child post-exit
3927/// restart-decision branch, the future M4
3928/// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-child
3929/// admission webhook, and the `caixa-operator`'s hierarchical
3930/// reconciliation scheduler's per-child fan-out all reach for one typed
3931/// identifier when they resolve an omitted per-child restart posture.
3932///
3933/// The [`RestartPolicy::Permanent`] value pins Erlang/OTP's `permanent`
3934/// worker-child restart type — always restart the child regardless of how
3935/// it died, the canonical posture for long-running services that must
3936/// always be up, matching the sibling [`SUPERVISOR_ESTRATEGIA_DEFAULT`]
3937/// `one_for_one` tree-of-independent-workers strategy this constant pairs
3938/// with under the same `{one_for_one, intensity, 5, 60}` worker-supervisor
3939/// shape. The two alternatives the closed [`RestartPolicy::ALL`] accept-set
3940/// carries ([`RestartPolicy::Transient`] — restart only on abnormal exit;
3941/// [`RestartPolicy::Temporary`] — never restart) express deliberate
3942/// one-shot / clean-completion-aware postures an author declares
3943/// explicitly, never a posture an omitted slot should silently assume.
3944pub const SUPERVISOR_CHILD_RESTART_DEFAULT: RestartPolicy = RestartPolicy::Permanent;
3945
3946/// Route the manually-authored [`Default`] impl on [`SupervisorSpec`]
3947/// through the substrate-canonical [`SupervisorSpec::otp_canonical`]
3948/// `pub const fn` constructor rather than a struct-literal cascade over
3949/// the paired [`SUPERVISOR_ESTRATEGIA_DEFAULT`] /
3950/// [`default_max_restarts`] / [`SUPERVISOR_RESTART_WINDOW_DEFAULT`]
3951/// lifted consts — one source of truth for the Erlang/OTP-canonical
3952/// `{one_for_one, 5, 60}` worker-supervisor baseline across the two
3953/// paths every downstream consumer already reaches through (the
3954/// hand-authored-until-now [`Default::default`] the
3955/// `..SupervisorSpec::default()` struct-update-syntax on every
3956/// one-axis-under-test fixture in this crate's test module rests on,
3957/// and the `pub const fn` [`SupervisorSpec::otp_canonical`] constructor
3958/// every `const`-context consumer reaches through).
3959///
3960/// Extends the [`Default`]-through-const-ctor fold discipline the
3961/// [`crate::LimitsSpec`] [`Default`]-through-[`crate::LimitsSpec::empty`]
3962/// (abd52c2), [`crate::aplicacao::MeshPolicy`]
3963/// [`Default`]-through-[`crate::aplicacao::MeshPolicy::empty`] (91641a4),
3964/// and [`crate::BehaviorSpec`]
3965/// [`Default`]-through-[`crate::BehaviorSpec::empty`] (0c1752c) folds
3966/// closed on the M2 / M3 `Option`-only "canonical unset baseline"
3967/// typed-slot spec family — extended here onto the M2 supervisor-slot
3968/// [`SupervisorSpec`] whose canonical baseline is not "everything
3969/// `None`" but the OTP-canonical `{one_for_one, 5, 60}` worker-
3970/// supervisor triple. The `empty()` peer's naming did not fit
3971/// (`SupervisorSpec` carries a discriminator-shaped `estrategia` field
3972/// and a non-zero `max_restarts`/`restart_window` pair whose canonical
3973/// shape is Erlang/OTP-descended, not the "no axis declared" bottom
3974/// the sibling `Option`-only slots fold to), so this peer is named
3975/// [`SupervisorSpec::otp_canonical`] instead — the same phrasing the
3976/// existing per-arm pin tests
3977/// [`tests::supervisor_estrategia_default_pins_otp_canonical_value`] /
3978/// [`tests::supervisor_max_restarts_default_pins_otp_canonical_value`] /
3979/// [`tests::supervisor_restart_window_default_pins_otp_canonical_value`]
3980/// already reach for. Pinned load-bearing by
3981/// [`tests::supervisor_spec_default_routes_through_otp_canonical_ctor`]
3982/// (byte-parity pin against [`SupervisorSpec::otp_canonical`] under
3983/// [`PartialEq`], sharpening the sibling
3984/// `supervisor_spec_default_*_routes_through_lifted_default` per-arm
3985/// pins from a per-field lift into a whole-struct one-source-of-truth
3986/// pin — the derived-until-now [`Default::default`] and the
3987/// [`SupervisorSpec::otp_canonical`] constructor are byte-equal by
3988/// construction, not by coincidence).
3989impl Default for SupervisorSpec {
3990 #[inline]
3991 fn default() -> Self {
3992 Self::otp_canonical()
3993 }
3994}
3995
3996impl SupervisorSpec {
3997 /// `const`-context peer of the [`Default for SupervisorSpec`]
3998 /// impl (which routes through this constructor) — returns the
3999 /// Erlang/OTP-canonical `{one_for_one, 5, 60}` worker-supervisor
4000 /// baseline this crate reaches for in every fixture-builder
4001 /// `..SupervisorSpec::default()` struct-update expression and
4002 /// every downstream `SupervisorSpec::default()` seed.
4003 ///
4004 /// Each field routes through the same substrate-canonical
4005 /// [`SUPERVISOR_ESTRATEGIA_DEFAULT`] / [`default_max_restarts`] /
4006 /// [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] lifted consts the
4007 /// per-arm pin tests
4008 /// [`tests::supervisor_estrategia_default_pins_otp_canonical_value`]
4009 /// / [`tests::supervisor_max_restarts_default_pins_otp_canonical_value`]
4010 /// / [`tests::supervisor_restart_window_default_pins_otp_canonical_value`]
4011 /// already assert, so a future coherent rebrand of the OTP-canonical
4012 /// triple (Elixir's `{max_restarts: 3, max_seconds: 5}`, a per-
4013 /// cluster overlay via a future `:restart-window-overrides` slot, a
4014 /// per-child-cohort promotion the INSPIRATIONS.md §II.2 Erlang/OTP
4015 /// absorption roadmap acknowledges) migrates through three typed
4016 /// constants in lockstep, and the paired [`Default`] impl inherits
4017 /// every future extension by construction.
4018 ///
4019 /// `pub const fn` rather than the derived-style `Default::default`
4020 /// or a `pub const SUPERVISOR_SPEC_DEFAULT: SupervisorSpec` item —
4021 /// [`Default::default`] is not `const` on stable Rust, and
4022 /// `SupervisorSpec` is non-`Copy` so a `pub const` item would force
4023 /// every consumer through a [`Clone::clone`]. The `pub const fn`
4024 /// discipline lets `const`-context callers construct the OTP-
4025 /// canonical baseline at compile time without runtime dispatch on
4026 /// the derived [`Default::default`], the same posture the sibling
4027 /// [`crate::LimitsSpec::empty`] (9739971) /
4028 /// [`crate::aplicacao::MeshPolicy::empty`] (6df969b) /
4029 /// [`crate::BehaviorSpec::empty`] (f9b18e3) `Option`-only typed-slot
4030 /// spec `pub const fn` constructors carry on the sibling
4031 /// "everything `None`" baseline axis.
4032 ///
4033 /// Fourth peer on the M2 / M3 typed-slot-spec "const-context peer
4034 /// of the derived-style [`Default`]" family — sibling of the
4035 /// [`crate::LimitsSpec::empty`] / [`crate::aplicacao::MeshPolicy::empty`]
4036 /// / [`crate::BehaviorSpec::empty`] `Option`-only "canonical unset
4037 /// baseline" trio, extended here onto the M2 supervisor-slot
4038 /// [`SupervisorSpec`] whose canonical baseline is not "everything
4039 /// `None`" but the Erlang/OTP-canonical `{one_for_one, 5, 60}`
4040 /// worker-supervisor triple. Named [`Self::otp_canonical`] rather
4041 /// than `empty()` to name the actual invariant the return value
4042 /// pins — the same phrasing already used in the per-arm pin tests
4043 /// on this file. Pinned load-bearing by
4044 /// [`tests::supervisor_spec_otp_canonical_byte_equals_default`] and
4045 /// [`tests::supervisor_spec_otp_canonical_is_usable_in_const_context`].
4046 #[must_use]
4047 pub const fn otp_canonical() -> Self {
4048 Self {
4049 estrategia: SUPERVISOR_ESTRATEGIA_DEFAULT,
4050 max_restarts: default_max_restarts(),
4051 restart_window: Some(SUPERVISOR_RESTART_WINDOW_DEFAULT),
4052 children: Vec::new(),
4053 }
4054 }
4055
4056 /// Substrate-canonical per-`:supervisor` `:estrategia` OTP-shaped
4057 /// sibling-restart-strategy scalar accessor every consumer that
4058 /// dispatches on the supervisor's per-sibling restart-decision shape
4059 /// keys off — returns the author-declared `:supervisor :estrategia`
4060 /// variant verbatim as a [`RestartStrategy`], `Copy`-projected from
4061 /// the typed slot's own [`RestartStrategy`] storage.
4062 ///
4063 /// The `:supervisor :estrategia` slot carries the closed-set
4064 /// OTP-shaped sibling-restart-strategy discriminator ([`RestartStrategy::OneForOne`]
4065 /// — restart only the failed child, the Erlang/OTP `one_for_one` default;
4066 /// [`RestartStrategy::OneForAll`] — restart every child on any child
4067 /// failure, the Erlang/OTP `one_for_all` shared-state cohort default;
4068 /// [`RestartStrategy::RestForOne`] — restart the failed child and
4069 /// every child started after it, the Erlang/OTP `rest_for_one`
4070 /// startup-order default; [`RestartStrategy::SimpleOneForOne`] —
4071 /// dynamic children of the same shape, the Erlang/OTP
4072 /// `simple_one_for_one` per-session default) that every downstream
4073 /// consumer of the Supervisor's per-sibling restart-decision fan-out
4074 /// shape keys off. Validated by [`SupervisorSpec::validate`] to be
4075 /// paired coherently with the sibling `:children` axis
4076 /// (`SimpleOneForOne ↔ children.is_empty()` — the cross-slot
4077 /// partition the strategy-arm's [`SupervisorError::SimpleOneForOneWithStaticChildren`]
4078 /// / [`SupervisorError::NoChildren`] refusal cascade pins), and every
4079 /// downstream consumer that reads the strategy keys off this scalar
4080 /// (the [`SupervisorSpec::validate`] `SimpleOneForOne ↔ non-SimpleOneForOne`
4081 /// partition-dispatch `match` arm, the non-`SimpleOneForOne`-arm
4082 /// declared-but-empty [`SupervisorError::NoChildren`] error carrier's
4083 /// `estrategia:` field, the future `feira app graph` per-Supervisor
4084 /// strategy print line, the future wasm-operator's per-supervisor
4085 /// sibling-restart-strategy branch, the future M4
4086 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-strategy
4087 /// admission-webhook resolver, the `caixa-operator`'s hierarchical
4088 /// reconciliation scheduler's per-strategy fan-out).
4089 ///
4090 /// Prior to this lift the `.estrategia` field was accessed inline at
4091 /// two production sites in `caixa-core/src/supervisor.rs` — the
4092 /// [`SupervisorSpec::validate`] `SimpleOneForOne ↔ non-SimpleOneForOne`
4093 /// `match self.estrategia { … }` partition dispatch, and the
4094 /// non-`SimpleOneForOne`-arm [`SupervisorError::NoChildren`] error
4095 /// carrier at `estrategia: self.estrategia` — two open-coded
4096 /// field-accesses that expressed no compile-time link back to the
4097 /// typed slot. A future extension of the `:supervisor :estrategia`
4098 /// axis to a richer author surface (a per-cluster strategy override
4099 /// the operator pins through a future `:supervisor :estrategia-overrides`
4100 /// slot the MESH-COMPOSITION §III.2 supervision-canary roadmap
4101 /// acknowledges, a per-tenant strategy-alias table the M4 CR
4102 /// materializer resolves per-CR, a per-Supervisor dynamic strategy
4103 /// derivation the future adaptive-supervision engine computes from
4104 /// child-failure-history topology, a per-child-cohort strategy split
4105 /// the future `RestForCohort` extension acknowledged by the
4106 /// INSPIRATIONS.md §II.2 Erlang/OTP absorption roadmap acknowledges)
4107 /// would have had to be threaded through every open-coded copy in
4108 /// lockstep — one consumer reading the raw variant while a peer read
4109 /// the operator-resolved variant would silently split the
4110 /// [`SupervisorError::NoChildren`] diagnostic's quoted strategy from
4111 /// the actual partition-dispatch input the empty-children refusal
4112 /// arm reached under, a two-consumer split at the validator far from
4113 /// the source `caixa.lisp` with no field naming the strategy-drift
4114 /// root cause. Lifting the resolution rule to a typed method on the
4115 /// substrate primitive means every downstream consumer of the
4116 /// Supervisor's per-`:supervisor` sibling-restart-strategy surface
4117 /// reaches for exactly one typed dispatch — the resolver's accept-set
4118 /// migrates as a unit on any future axis addition.
4119 ///
4120 /// Peer of the sibling M3 mesh-slot [`crate::Placement::estrategia`]
4121 /// (921fe1b) `Copy`-return `PlacementStrategy` scalar accessor on the
4122 /// per-`:placement` distribution-strategy axis — same "one typed
4123 /// dispatch on the substrate primitive, thin projections at each
4124 /// consumer" discipline extended onto the M2 supervisor-slot
4125 /// per-`:supervisor` sibling-restart-strategy `Copy`-composite-enum
4126 /// scalar axis. The two typed axes (`Placement::estrategia` on the
4127 /// M3 Aplicacao side, `SupervisorSpec::estrategia` on the M2
4128 /// Supervisor side) now share one accessor discipline for the shared
4129 /// substrate concept "a `Copy`-projected closed-set enum-arm
4130 /// discriminator that partitions the downstream renderer's per-arm
4131 /// fan-out". First `Copy`-return accessor on the M2 supervisor-slot
4132 /// `SupervisorSpec` type — companion to the sibling per-`:children`
4133 /// [`crate::ChildSpec::nome`] (57c61d0) /
4134 /// [`crate::ChildSpec::versao_requirement`] (2c053c8) child-caixa
4135 /// scalar accessors on the sibling per-`:children` `String`-carry
4136 /// axes. Named `estrategia()` to match the storage field's name and
4137 /// the peer [`crate::Placement::estrategia`] method-name discipline
4138 /// verbatim; the accessor's identity name maps onto the canonical
4139 /// OTP-shape supervision vocabulary the [`RestartStrategy`] enum's
4140 /// docstring already carries.
4141 ///
4142 /// Declared `pub const fn` to close the M2 supervisor-slot
4143 /// `Copy`-return raw-field-getter `const`-eval-surface pass —
4144 /// sibling of the peer M2 per-`:children` [`ChildSpec::restart`]
4145 /// (converted in this commit) `Copy`-composite-enum accessor, peer
4146 /// of the sibling M2 per-`:supervisor`
4147 /// [`SupervisorSpec::max_restarts`] (b698ec0) `Copy`-`u32` accessor
4148 /// already lifted, and mirror of the peer M3 mesh-slot
4149 /// per-`:placement` [`crate::Placement::estrategia`] (bafa004)
4150 /// `Copy`-return `pub const fn` scalar accessor whose method-name
4151 /// discipline this accessor was authored to match. Every downstream
4152 /// substrate-side `const`-context consumer of the per-`:supervisor`
4153 /// sibling-restart-strategy scalar (a future module-scope `const
4154 /// _:() = assert!(matches!(sup.estrategia(),
4155 /// RestartStrategy::OneForOne))` invariant pin on a typed fixture,
4156 /// a future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer
4157 /// admission-webhook `const fn` per-supervisor strategy-arm floor
4158 /// over a typed [`SupervisorSpec`], any future `const fn`
4159 /// supervisor-tree composer over the substrate primitive that fans
4160 /// on the sibling-restart-strategy at compile time) now reaches
4161 /// through the same typed dispatch on the substrate primitive at
4162 /// const-eval time as at runtime. A future non-`Copy`-return
4163 /// promotion of the scalar (an `Option<RestartStrategy>`-shape
4164 /// migration once the substrate grows per-cluster strategy overlays
4165 /// the [`SupervisorSpec`] docstring already anticipates, a
4166 /// per-tenant strategy-alias table the M4 CR materializer resolves
4167 /// per-CR) that would drop the `const` qualifier fails the
4168 /// fail-before-pass-after pin
4169 /// [`tests::supervisor_spec_estrategia_accessor_is_const_fn`] at
4170 /// caixa-core build time rather than surfacing as a downstream
4171 /// consumer regression.
4172 #[must_use]
4173 pub const fn estrategia(&self) -> RestartStrategy {
4174 self.estrategia
4175 }
4176
4177 /// Substrate-canonical per-`:supervisor` `:max-restarts` OTP-shaped
4178 /// `MaxIntensity` restart-budget scalar accessor every consumer that
4179 /// reads the supervisor's per-`:restart-window` restart-budget count
4180 /// keys off — returns the author-declared `:supervisor :max-restarts`
4181 /// typed `u32` verbatim, `Copy`-projected from the typed slot's own
4182 /// `u32` storage (`u32` is `Copy`, so the accessor returns by value; no
4183 /// borrow of `&self` past the call). Non-optional (the `u32` field
4184 /// carries the restart-budget count as a required axis with a
4185 /// [`default_max_restarts`]-supplied default; the zero-floor arm
4186 /// [`SupervisorError::ZeroMaxRestarts`] and the cap arm
4187 /// [`SupervisorError::MaxRestartsExceedsCap`] jointly bracket the
4188 /// accept-set to `1..=SUPERVISOR_MAX_RESTARTS_MAX`).
4189 ///
4190 /// The `:supervisor :max-restarts` slot carries the Erlang/OTP
4191 /// `MaxIntensity` restart-budget count that pairs with the sibling
4192 /// `:restart-window` `Period` to form the `MaxIntensity / Period`
4193 /// restart-intensity ratio the supervisor trips its own escalation on
4194 /// (`theory/RUNTIME-PATTERNS.md` §II.2, Learn You Some Erlang's
4195 /// `{intensity, 5, 60}` worker-supervisor default). Every downstream
4196 /// consumer of the Supervisor's per-`:supervisor` restart-budget count
4197 /// keys off this scalar (the [`SupervisorSpec::validate`] zero-floor +
4198 /// upper-cap bracket at
4199 /// `require_positive_bounded_u32(self.max_restarts(), …)`, the future
4200 /// wasm-operator's per-supervisor restart-intensity counter's
4201 /// budget-vs-count comparator, the future M4
4202 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission
4203 /// webhook, the `caixa-operator`'s hierarchical reconciliation
4204 /// scheduler's per-supervisor escalation-decision branch, every
4205 /// `SupervisorError::MaxRestartsExceedsCap` variant carrying the
4206 /// offending count verbatim for `feira lint` rendering).
4207 ///
4208 /// Prior to this lift the `.max_restarts` field was accessed inline at
4209 /// one production site in `caixa-core/src/supervisor.rs` — the
4210 /// [`SupervisorSpec::validate`] `require_positive_bounded_u32(self
4211 /// .max_restarts, …)` bracket-gate call — one open-coded field-access
4212 /// that expressed no compile-time link back to the typed slot. A
4213 /// future extension of the `:max-restarts` axis to a richer author
4214 /// surface (a per-cluster restart-budget override the operator pins
4215 /// through a future `:supervisor :max-restarts-overrides` slot the
4216 /// MESH-COMPOSITION §III.2 supervision-canary roadmap acknowledges,
4217 /// a per-tenant restart-budget-alias table the M4 CR materializer
4218 /// resolves per-CR, a per-supervisor dynamic restart-budget derivation
4219 /// the future adaptive-supervision engine computes from child-failure-
4220 /// history topology, a promotion of the plain `u32` count to a richer
4221 /// `{MaxR, MaxT}` tuple once Erlang/OTP's per-child-cohort restart-
4222 /// budget-partition slot comes into scope) would have had to be
4223 /// threaded through every open-coded copy in lockstep or the validate
4224 /// gate and the future M4 emit path would silently disagree on which
4225 /// restart-budget count a given supervisor resolves to — an author's
4226 /// `:max-restarts 5` would satisfy validate while the emit path
4227 /// silently read a drifted other value (a `:max-restarts 10000`
4228 /// no-op supervisor at the emit boundary would carry the author's
4229 /// declared `5` verbatim in `feira lint` output while the future
4230 /// wasm-operator's restart-intensity counter operated under the
4231 /// drifted count), a two-consumer split at the validator far from the
4232 /// source `caixa.lisp` with no field naming the restart-budget-drift
4233 /// root cause. Lifting the resolution rule to a typed method on the
4234 /// substrate primitive means every downstream consumer of the
4235 /// Supervisor's per-`:supervisor` restart-budget-count surface reaches
4236 /// for exactly one typed dispatch — the resolver's accept-set migrates
4237 /// as a unit on any future axis addition.
4238 ///
4239 /// Peer of the sibling M3 mesh-slot [`crate::CircuitBreaker::max_failures`]
4240 /// (3a74062) `Copy`-return `u32` sub-struct required-scalar accessor
4241 /// on the per-`:politicas :circuit-breaker :max-failures` Envoy-
4242 /// outlier-detection trip-threshold axis — same "one typed dispatch on
4243 /// the substrate primitive, thin projections at each consumer"
4244 /// discipline extended onto the M2 supervisor-slot per-`:supervisor`
4245 /// restart-budget-count `Copy`-`u32` scalar axis. The two typed axes
4246 /// (`CircuitBreaker::max_failures` on the M3 Aplicacao side,
4247 /// `SupervisorSpec::max_restarts` on the M2 Supervisor side) now share
4248 /// one accessor discipline for the shared substrate concept "a
4249 /// `Copy`-projected required `u32` count that trips the next-higher
4250 /// protection layer after N events in a rolling window" — both are
4251 /// counters with identical degenerate-at-the-high-end shape and share
4252 /// the paired [`crate::POLICY_BREAKER_MAX_FAILURES_MAX`] /
4253 /// [`SUPERVISOR_MAX_RESTARTS_MAX`] `1000` cap. Second `Copy`-return
4254 /// accessor on the M2 supervisor-slot `SupervisorSpec` type, sibling
4255 /// to the [`SupervisorSpec::estrategia`] (eafb619) `Copy`-composite-
4256 /// enum `RestartStrategy` accessor. Named `max_restarts()` to match
4257 /// the storage field's name verbatim and the peer
4258 /// [`crate::CircuitBreaker::max_failures`] method-name discipline; the
4259 /// accessor's identity maps onto the canonical OTP-shape supervision
4260 /// vocabulary the [`SupervisorSpec::max_restarts`] field's docstring
4261 /// already carries.
4262 #[must_use]
4263 pub const fn max_restarts(&self) -> u32 {
4264 self.max_restarts
4265 }
4266
4267 /// Substrate-canonical per-`:supervisor` `:restart-window` OTP-shaped
4268 /// `Period` sliding-window scalar accessor every consumer of the
4269 /// supervisor's `MaxIntensity / Period` restart-intensity denominator
4270 /// keys off — returns the author-declared `:supervisor :restart-window`
4271 /// typed [`Duration`] verbatim as an `Option<Duration>`, copied out of
4272 /// the typed slot's own `Option<Duration>` storage (`Duration` is
4273 /// `Copy`, so `Option<Duration>` is `Copy` and the accessor returns by
4274 /// value; no borrow of `&self` past the call). `None` when the slot is
4275 /// absent (the canonical "never reset — every restart across the
4276 /// supervisor's lifetime counts against the sibling `:max-restarts`
4277 /// budget" sentinel the field's own docstring names and the peer
4278 /// `validate_accepts_none_restart_window` pin locks in on the
4279 /// [`SupervisorSpec::validate`] entry-side).
4280 ///
4281 /// The `:supervisor :restart-window` slot carries the Erlang/OTP
4282 /// `Period` sliding-observation-interval that pairs with the sibling
4283 /// `:max-restarts` `MaxIntensity` restart-budget count to form the
4284 /// `MaxIntensity / Period` restart-intensity ratio the supervisor
4285 /// trips its own escalation on (`theory/RUNTIME-PATTERNS.md` §II.2,
4286 /// Learn You Some Erlang's `{intensity, 5, 60}` worker-supervisor
4287 /// default). The typed slot's `Option<Duration>` accept-set —
4288 /// zero-floor rejected through [`SupervisorError::RestartWindowZero`]
4289 /// (Erlang/OTP's `MaxIntensity / Period` invariant requires
4290 /// `Period > 0`; a zero period either trips on the first failure or
4291 /// never trips depending on operator interpretation, neither of which
4292 /// is the author's intent — omit the slot to express "no reset";
4293 /// carry a positive duration to express the sliding window),
4294 /// integer-millisecond canonical form enforced through
4295 /// [`SupervisorError::RestartWindowNotCanonical`] (the duration
4296 /// codec's canonical form emits `"1500ms"` not `"1.5s"` and the
4297 /// future wasm-operator's per-supervisor restart-intensity counter
4298 /// quantizes at milliseconds), upper-bounded by
4299 /// [`SUPERVISOR_RESTART_WINDOW_MAX`] (1h — the coarsest per-
4300 /// supervisor rolling window any operationally-reachable supervisor
4301 /// can honor without spanning multiple scheduler epochs the
4302 /// hierarchical-reconciliation scheduler treats as independent) —
4303 /// maps onto the future wasm-operator (M3) per-supervisor
4304 /// restart-intensity counter's rolling-observation-interval, the
4305 /// future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
4306 /// per-`spec.restartWindow` admission webhook, and the sibling
4307 /// `duration_codec`-serialized wire scalar every downstream consumer
4308 /// of the supervisor's per-`:supervisor` restart-intensity denominator
4309 /// keys off.
4310 ///
4311 /// Prior to this lift the `.restart_window` field was accessed inline
4312 /// at one production site in `caixa-core/src/supervisor.rs` — the
4313 /// [`SupervisorSpec::validate`] `if let Some(w) = self.restart_window {
4314 /// … }` zero-floor + canonical-form + upper-cap bracket arm — one
4315 /// open-coded field-access that expressed no compile-time link back to
4316 /// the typed slot. A future extension of the `:restart-window` axis to
4317 /// a richer author surface (a per-cluster restart-window override the
4318 /// operator pins through a future `:supervisor :restart-window-overrides`
4319 /// slot the MESH-COMPOSITION §III.2 supervision-canary roadmap
4320 /// acknowledges, a per-tenant restart-window-alias table the M4 CR
4321 /// materializer resolves per-CR, a per-supervisor dynamic
4322 /// restart-window derivation the future adaptive-supervision engine
4323 /// computes from child-failure-history topology, a promotion of the
4324 /// plain `Option<Duration>` window to a richer `{observation, cooldown}`
4325 /// pair once Erlang/OTP's per-child-cohort observation-interval-
4326 /// partition slot comes into scope) would have had to be threaded
4327 /// through every open-coded copy in lockstep or the validate gate and
4328 /// the future M4 emit path would silently disagree on which
4329 /// restart-window a given supervisor resolves to — an author's
4330 /// `:restart-window "60s"` would satisfy validate while the emit path
4331 /// silently read a drifted other value (a `Some(Duration::from_secs(60))`
4332 /// authored slot at the emit boundary would carry the author's
4333 /// declared window verbatim in `feira lint` output while the future
4334 /// wasm-operator's restart-intensity counter operated under a
4335 /// drifted window, or vice versa: an author's `:restart-window ()`
4336 /// would carry the "never reset" sentinel through validate while the
4337 /// emit path silently substituted a default sliding window), a
4338 /// two-consumer split at the validator far from the source
4339 /// `caixa.lisp` with no field naming the restart-window-drift root
4340 /// cause. Lifting the resolution rule to a typed method on the
4341 /// substrate primitive means every downstream consumer of the
4342 /// Supervisor's per-`:supervisor` restart-intensity-denominator
4343 /// surface reaches for exactly one typed dispatch — the resolver's
4344 /// accept-set migrates as a unit on any future axis addition.
4345 ///
4346 /// Third `Copy`-return accessor on the M2 supervisor-slot
4347 /// `SupervisorSpec` type, closing the last unlifted per-`:supervisor`
4348 /// scalar-value axis (`children: Vec<ChildSpec>` carries a `Vec`
4349 /// payload rather than a `Copy`-scalar, and the per-`:children`
4350 /// [`crate::ChildSpec::nome`] (57c61d0) /
4351 /// [`crate::ChildSpec::versao_requirement`] (2c053c8) child-caixa
4352 /// scalar accessors already close the per-element `String`-carry
4353 /// axes). Sibling to the peer M2 [`crate::LimitsSpec::wall_clock`]
4354 /// (8cb717b) `Option<Duration>` accessor on the `:limits` slot's
4355 /// per-outermost-call wall-clock-deadline axis and the peer M3
4356 /// [`crate::MeshPolicy::timeout`] (7073d0f) `Option<Duration>`
4357 /// accessor on the `:politicas` slot's per-call-deadline axis — all
4358 /// three share the shared substrate concept "a `Copy`-projected
4359 /// optional `Duration` that carries a positive integer-millisecond
4360 /// canonical value with a `1ms..=<axis-specific>_MAX` accept-set and
4361 /// the paired zero-floor / non-canonical / above-cap refusal cascade"
4362 /// through the same [`crate::render::require_positive_canonical_bounded_duration`]
4363 /// bracket-helper the three axes each route through. Named
4364 /// `restart_window()` to match the storage field's name verbatim and
4365 /// the peer [`crate::LimitsSpec::wall_clock`] /
4366 /// [`crate::MeshPolicy::timeout`] method-name discipline; the
4367 /// accessor's identity maps onto the canonical OTP-shape supervision
4368 /// vocabulary the [`SupervisorSpec::restart_window`] field's docstring
4369 /// already carries.
4370 #[must_use]
4371 pub const fn restart_window(&self) -> Option<Duration> {
4372 self.restart_window
4373 }
4374
4375 /// Substrate-canonical per-`:supervisor` `:children` OTP-shaped
4376 /// static-child-list slice accessor every consumer that walks the
4377 /// supervisor's declared child set keys off — returns the author-
4378 /// declared `:supervisor :children` `Vec<ChildSpec>` verbatim as a
4379 /// `&[ChildSpec]` slice-view, borrowed from the typed slot's own
4380 /// `Vec<ChildSpec>` storage (a zero-copy slice-view over the same
4381 /// backing buffer the `Serialize`/`Deserialize` derives round-trip
4382 /// through). Non-optional: an empty slice is the load-bearing
4383 /// "author declared `:children ()`" sentinel every consumer of the
4384 /// cross-slot `SimpleOneForOne ↔ children.is_empty()` partition
4385 /// keys off (`SimpleOneForOne` requires the empty slice; the peer
4386 /// three strategies require a non-empty slice — the paired
4387 /// [`SupervisorError::SimpleOneForOneWithStaticChildren`] /
4388 /// [`SupervisorError::NoChildren`] refusal cascade pins the
4389 /// partition on both arms).
4390 ///
4391 /// The `:supervisor :children` slot carries the OTP-shaped static
4392 /// child list the supervisor materializes one ComputeUnit per
4393 /// entry from — the Erlang/OTP `supervisor:init/1`'s
4394 /// `{ok, {SupFlags, ChildSpecs}}` `ChildSpecs` list, projected
4395 /// through the tatara-lisp `:children` author surface onto a typed
4396 /// `Vec<ChildSpec>` whose per-element `(nome(),
4397 /// versao_requirement(), restart)` triple the per-child
4398 /// [`SupervisorSpec::validate`] loop already gates through the
4399 /// lifted [`ChildSpec::nome`] (57c61d0) /
4400 /// [`ChildSpec::versao_requirement`] (2c053c8) scalar accessors.
4401 /// Every downstream consumer that fans on the static child list
4402 /// keys off this slice (the [`SupervisorSpec::validate`]
4403 /// `SimpleOneForOne ↔ non-SimpleOneForOne` partition dispatch's
4404 /// `.is_empty()` probe on both arms, the [`SupervisorSpec::validate`]
4405 /// per-child DNS-1123 / semver-requirement / duplicate-detection
4406 /// fan-out loop, every future wasm-operator (M3) per-supervisor
4407 /// hierarchical-reconciliation scheduler's per-child ComputeUnit
4408 /// materialization loop, the future M4
4409 /// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's per-child
4410 /// admission-webhook fan-out, the future `feira app graph`
4411 /// per-supervisor tree-print traversal).
4412 ///
4413 /// Prior to this lift the `.children` `Vec<ChildSpec>` was accessed
4414 /// inline at three production sites in `caixa-core/src/supervisor.rs`
4415 /// — the [`SupervisorSpec::validate`] `SimpleOneForOne`-arm
4416 /// `!self.children.is_empty()` cross-slot refusal probe, the peer
4417 /// non-`SimpleOneForOne`-arm `self.children.is_empty()`
4418 /// [`SupervisorError::NoChildren`] refusal probe, and the per-child
4419 /// validate loop's `for child in &self.children` traversal head —
4420 /// three open-coded field-accesses that expressed no compile-time
4421 /// link back to the typed slot. A future extension of the
4422 /// `:supervisor :children` axis to a richer author surface (a
4423 /// per-cluster child-set overlay the operator pins through a future
4424 /// `:supervisor :children-overrides` slot the MESH-COMPOSITION §III.2
4425 /// supervision-canary roadmap acknowledges, a per-tenant
4426 /// child-set-alias table the M4 CR materializer resolves per-CR,
4427 /// a per-supervisor dynamic-child derivation the future adaptive-
4428 /// supervision engine computes from child-failure-history topology,
4429 /// a promotion of the plain `Vec<ChildSpec>` to a richer
4430 /// `{static, dynamic}` partition once Erlang/OTP's
4431 /// `simple_one_for_one` dynamic-child slot comes into typed scope)
4432 /// would have had to be threaded through all three open-coded copies
4433 /// in lockstep or one consumer would silently disagree with the
4434 /// peers on which child-set a given supervisor resolves to — the
4435 /// `SimpleOneForOne`-arm probe reading the raw slot while the peer
4436 /// non-`SimpleOneForOne`-arm probe read an operator-resolved slot
4437 /// would silently split the partition-dispatch's two-arm coherence
4438 /// (a supervisor that satisfies neither arm's precondition, or that
4439 /// satisfies both, at the cost of the paired
4440 /// `SimpleOneForOneWithStaticChildren`/`NoChildren` refusal cascade
4441 /// silently drifting from the per-child validate loop's actual
4442 /// traversal input), a three-consumer split at the validator far
4443 /// from the source `caixa.lisp` with no field naming the
4444 /// child-set-drift root cause. Lifting the resolution rule to a
4445 /// typed method on the substrate primitive means every downstream
4446 /// consumer of the Supervisor's per-`:supervisor` static-child-list
4447 /// surface reaches for exactly one typed dispatch — the resolver's
4448 /// accept-set migrates as a unit on any future axis addition.
4449 ///
4450 /// First slice-return (`&[T]`) accessor on any M2 or M3 typed slot
4451 /// — the seed for the same "one typed dispatch on the substrate
4452 /// primitive, thin projections at each consumer" discipline the
4453 /// closed [`crate::LimitsSpec`] / [`BehaviorSpec`] /
4454 /// [`crate::UpgradeFromEntry`] scalar-accessor families each carry
4455 /// on their `Copy` / `Option<Copy>` / `Option<&str>` axes, extended
4456 /// onto the first `Vec`-carry axis on the substrate. The four peer
4457 /// `Vec`-carry axes still unlifted at the time of this seed —
4458 /// [`crate::Placement::clusters`] (`Vec<String>` per-cluster
4459 /// distribution-target list), [`crate::AplicacaoSpec::membros`]
4460 /// (`Vec<Membro>` per-Aplicacao member list),
4461 /// [`crate::AplicacaoSpec::contratos`] (`Vec<WitContract>`
4462 /// per-Aplicacao WIT-typed edge list),
4463 /// [`crate::UpgradeFromEntry::instructions`]
4464 /// (`Vec<UpgradeInstruction>` per-appup migration-instruction list)
4465 /// — inherit this accessor's discipline as future compounding runs
4466 /// migrate their consumers onto the shared slice-return shape.
4467 /// Fourth (and final) accessor on the M2 supervisor-slot
4468 /// `SupervisorSpec` type, sibling to the three `Copy`-return
4469 /// [`SupervisorSpec::estrategia`] (eafb619) /
4470 /// [`SupervisorSpec::max_restarts`] (7844f4e) /
4471 /// [`SupervisorSpec::restart_window`] (7e7b32f) accessors — closes
4472 /// the last unlifted per-`:supervisor` field axis (the
4473 /// `Vec<ChildSpec>` static-child-list carrier) so every downstream
4474 /// per-`:supervisor` reader now routes through a typed dispatch on
4475 /// the substrate primitive. Named `children()` to match the storage
4476 /// field's name verbatim and the tatara-lisp author-surface term
4477 /// (`:children`) the field's own docstring already carries; the
4478 /// accessor's identity maps onto the canonical OTP-shape
4479 /// supervision vocabulary the [`SupervisorSpec::children`] field's
4480 /// docstring already reaches for ("Static children ..."). Returns
4481 /// `&[ChildSpec]` (not `&Vec<ChildSpec>`) because every downstream
4482 /// consumer of the child list treats it as a read-only sequence —
4483 /// the slice-view is the narrowest borrow that supports every
4484 /// present + roadmapped consumer (`.is_empty()`, `.iter()`,
4485 /// index, `.len()`) without leaking the backing `Vec`'s
4486 /// grow/push/reserve surface that no consumer of the typed view
4487 /// reaches for (the storage-side `Vec` remains reachable through
4488 /// the `pub children` field for the mutation-carrying
4489 /// `Caixa::supervisor_view` fold-in path in
4490 /// `manifest.rs:supervisor_view`).
4491 #[must_use]
4492 pub const fn children(&self) -> &[ChildSpec] {
4493 self.children.as_slice()
4494 }
4495
4496 /// Validate the supervisor's typed shape — strategy ↔ children
4497 /// invariants, max_restarts > 0, restart_window > 0 when set,
4498 /// per-child non-empty + duplicate-free names.
4499 ///
4500 /// Mirrors the value-shape discipline applied to every other
4501 /// typed slot:
4502 ///
4503 /// - `Some(Duration::ZERO)` on a Duration-bearing axis is the
4504 /// same "0 means the opposite of what you think" footgun
4505 /// closed for `:politicas :timeout` (Envoy interprets a zero
4506 /// timeout as `infinite`), `:politicas :circuit-breaker
4507 /// :window`, and `:limits :wall-clock`. The
4508 /// `MaxIntensity / Period` ratio in Erlang/OTP's
4509 /// `supervisor` requires `Period > 0`; a zero period either
4510 /// trips on the first failure or never trips depending on
4511 /// operator interpretation, neither of which is the
4512 /// author's intent. Omit `:restart-window` to express "no
4513 /// reset"; carry a positive duration to express the window.
4514 /// - duplicate `:children` `:caixa` names are the same
4515 /// graph-node-set / multiset distinction closed for
4516 /// `:membros` (4bb3f3d), `:placement :clusters` (c7c7799),
4517 /// and `:entrada :paths` (eb3456d). Two children with the
4518 /// same `:caixa` materialize as two ComputeUnits with the
4519 /// same name in the cluster's HelmRelease values, one
4520 /// silently overwriting the other. Erlang/OTP's
4521 /// `child_spec.id` is required-unique per supervisor;
4522 /// pleme-io enforces the same set-not-multiset shape on
4523 /// `:caixa` (the load-bearing identity in our renderer).
4524 pub fn validate(&self) -> Result<(), SupervisorError> {
4525 // Route the `SimpleOneForOne ↔ non-SimpleOneForOne` partition
4526 // dispatch and the non-`SimpleOneForOne`-arm [`SupervisorError::NoChildren`]
4527 // error carrier's `estrategia:` field through the lifted
4528 // [`SupervisorSpec::estrategia`] accessor rather than the raw
4529 // `self.estrategia` field access — the two production consumers
4530 // of the per-`:supervisor` sibling-restart-strategy scalar now
4531 // key off exactly one typed dispatch on the substrate primitive,
4532 // so any future rebrand on the axis (a per-cluster strategy
4533 // override the operator pins through a future `:supervisor
4534 // :estrategia-overrides` slot, a per-tenant strategy-alias table
4535 // the M4 CR materializer resolves per-CR) migrates as a single
4536 // caixa-core edit rather than a coordinated rewrite of the two
4537 // call sites — sibling of the peer M3 [`crate::Placement::estrategia`]
4538 // (921fe1b) four-consumer migration on the per-`:placement`
4539 // distribution-strategy axis.
4540 // Route the `SimpleOneForOne ↔ non-SimpleOneForOne` partition-
4541 // dispatch's paired `.is_empty()` cross-slot refusal probes
4542 // (the `SimpleOneForOne`-arm
4543 // [`SupervisorError::SimpleOneForOneWithStaticChildren`] refusal
4544 // and the non-`SimpleOneForOne`-arm [`SupervisorError::NoChildren`]
4545 // refusal) through the lifted [`SupervisorSpec::children`]
4546 // slice-return accessor rather than the raw `self.children`
4547 // field access — the two paired production consumers of the
4548 // per-`:supervisor` static-child-list scalar-shape now key off
4549 // exactly one typed dispatch on the substrate primitive, so any
4550 // future rebrand on the axis (a per-cluster child-set overlay
4551 // the operator pins through a future `:supervisor
4552 // :children-overrides` slot, a per-tenant child-set-alias table
4553 // the M4 CR materializer resolves per-CR) migrates as a single
4554 // caixa-core edit rather than a coordinated rewrite of the
4555 // paired arms — first slice-return migration on any typed slot,
4556 // seed for the peer per-`:placement :clusters`,
4557 // per-`:membros`, per-`:contratos`, and per-`:upgrade-from
4558 // :instructions` `Vec`-carry axes.
4559 match self.estrategia() {
4560 RestartStrategy::SimpleOneForOne => {
4561 // SimpleOneForOne: children added at runtime. Static
4562 // list must be empty (one shape declared elsewhere).
4563 if !self.children().is_empty() {
4564 return Err(SupervisorError::SimpleOneForOneWithStaticChildren);
4565 }
4566 }
4567 _ => {
4568 if self.children().is_empty() {
4569 return Err(SupervisorError::no_children(self.estrategia()));
4570 }
4571 }
4572 }
4573 // Zero-floor + upper-cap bracket on the typed `:max-restarts`
4574 // axis. See [`crate::render::require_positive_bounded_u32`] for
4575 // the ordering discipline (zero-floor arm strictly precedes cap
4576 // arm so `0` surfaces the self-locating `ZeroMaxRestarts`
4577 // diagnostic with its counter-axis remediation directly named,
4578 // not the misleading `0 > SUPERVISOR_MAX_RESTARTS_MAX == false`
4579 // cap-arm miss). Until this bracket landed the top edge ran all
4580 // the way to `u32::MAX` and a struct-literal
4581 // `SupervisorSpec { max_restarts: 100_000, .. }` (or the
4582 // equivalent author-surface `:max-restarts 100000` /
4583 // `:max-restarts 4294967295` typo landing in the slot) silently
4584 // passed validate. The runtime substrate consuming the value
4585 // (Erlang/OTP's `MaxIntensity / Period` ratio, the future
4586 // wasm-operator's per-supervisor restart-intensity counter, the
4587 // M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
4588 // admission webhook) then turned a typed `:max-restarts`
4589 // policy into a no-op supervisor: the escalation threshold is
4590 // structurally so high that no realistic
4591 // restarts-per-`:restart-window` traffic shape can reach it,
4592 // the supervisor never escalates to its parent, and a bad
4593 // child can loop inside the window indefinitely with the
4594 // parent supervisor structurally never receiving the "this
4595 // subtree has exceeded its restart budget" signal the typed
4596 // slot is meant to express. The bracket set is
4597 // `1..=SUPERVISOR_MAX_RESTARTS_MAX`, peer with the
4598 // [`crate::aplicacao::POLICY_BREAKER_MAX_FAILURES_MAX`] cap on
4599 // the sibling `:politicas :circuit-breaker :max-failures` axis:
4600 // both are "trip the next-higher protection layer after N
4601 // events in a rolling window" counters with identical
4602 // degenerate-at-the-high-end shape and now share one canonical
4603 // bracket helper. The bracket precedes the sibling
4604 // `:restart-window` zero-floor / canonical-millisecond arms so
4605 // an over-cap `max_restarts` paired with a structurally invalid
4606 // window surfaces the bracket diagnostic first, mirroring the
4607 // `PolicyBreakerMaxFailuresExceedsCap` / window-axis cross-arm
4608 // ordering on the peer `:politicas :circuit-breaker` slot.
4609 // Route the [`SupervisorSpec::validate`] `:max-restarts` zero-floor +
4610 // upper-cap bracket-gate through the lifted [`SupervisorSpec::max_restarts`]
4611 // accessor rather than the raw `self.max_restarts` field access —
4612 // the one production consumer of the per-`:supervisor`
4613 // restart-budget-count scalar now keys off exactly one typed
4614 // dispatch on the substrate primitive, so any future rebrand on
4615 // the axis (a per-cluster restart-budget override the operator
4616 // pins through a future `:supervisor :max-restarts-overrides`
4617 // slot, a per-tenant restart-budget-alias table the M4 CR
4618 // materializer resolves per-CR) migrates as a single caixa-core
4619 // edit rather than a coordinated rewrite — sibling of the peer M3
4620 // [`crate::CircuitBreaker::max_failures`] (3a74062) migration on
4621 // the per-`:politicas :circuit-breaker :max-failures` axis.
4622 crate::render::require_positive_bounded_u32(
4623 self.max_restarts(),
4624 SUPERVISOR_MAX_RESTARTS_MAX,
4625 || SupervisorError::ZeroMaxRestarts,
4626 SupervisorError::max_restarts_exceeds_cap,
4627 )?;
4628 // Route the [`SupervisorSpec::validate`] `:restart-window`
4629 // zero-floor + integer-millisecond canonical-form + upper-cap
4630 // bracket-gate through the lifted [`SupervisorSpec::restart_window`]
4631 // accessor rather than the raw `self.restart_window` field access —
4632 // the one production consumer of the per-`:supervisor`
4633 // restart-intensity-denominator scalar now keys off exactly one
4634 // typed dispatch on the substrate primitive, so any future rebrand
4635 // on the axis (a per-cluster restart-window override the operator
4636 // pins through a future `:supervisor :restart-window-overrides`
4637 // slot, a per-tenant restart-window-alias table the M4 CR
4638 // materializer resolves per-CR) migrates as a single caixa-core
4639 // edit rather than a coordinated rewrite — sibling of the peer M2
4640 // [`crate::LimitsSpec::wall_clock`] (8cb717b) validate-arm-route
4641 // on the per-`:limits :wall-clock` axis and the peer M3
4642 // [`crate::MeshPolicy::timeout`] (7073d0f) accessor-route on the
4643 // per-`:politicas :timeout` axis.
4644 if let Some(w) = self.restart_window() {
4645 // Zero-floor + integer-millisecond canonical-form +
4646 // upper-cap bracket on the typed `:restart-window` axis.
4647 // See
4648 // [`crate::render::require_positive_canonical_bounded_duration`]
4649 // for the full three-arm ordering discipline (zero-floor
4650 // strictly precedes canonical-form so `Duration::ZERO`
4651 // surfaces the self-locating `RestartWindowZero`
4652 // diagnostic; canonical-form strictly precedes the cap arm
4653 // so a sub-millisecond above-cap value surfaces the more
4654 // fundamental round-trip-shape diagnostic first) and the
4655 // three peer typed-`Duration` sites that share this
4656 // canonical bracket ([`crate::MeshPolicy::timeout`],
4657 // [`crate::CircuitBreaker::window`],
4658 // [`crate::LimitsSpec::wall_clock`]). Every validated
4659 // value lies in `1ms..=SUPERVISOR_RESTART_WINDOW_MAX`
4660 // (1ms..=1h), integer-millisecond granularity.
4661 crate::render::require_positive_canonical_bounded_duration(
4662 w,
4663 SUPERVISOR_RESTART_WINDOW_MAX,
4664 || SupervisorError::RestartWindowZero,
4665 SupervisorError::restart_window_not_canonical,
4666 SupervisorError::restart_window_exceeds_cap,
4667 )?;
4668 }
4669 // Route the per-child DNS-1123 / semver-requirement / duplicate-
4670 // detection fan-out loop through the lifted named per-slot gate
4671 // [`SupervisorSpec::validate_children`] rather than an inline
4672 // three-per-child cascade — every future consumer that wants to
4673 // re-check only the `:children` slot's per-entry axes (the M4
4674 // `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
4675 // admission webhook re-validating one added/renamed child, the
4676 // future wasm-operator's per-child dynamic-add re-validator on
4677 // the `SimpleOneForOne` runtime-add path once dynamic-children
4678 // graduate to a typed slot, a future partial re-validator on a
4679 // per-`:children`-entry patch) reaches every per-entry axis
4680 // through one dispatch rather than re-inlining the three-arm
4681 // cascade in lockstep with `validate` or paying the peer
4682 // `:estrategia`/`:max-restarts`/`:restart-window` gates to
4683 // reach one entry check. Sibling of the peer M3 mesh-slot
4684 // per-slot gate family (`validate_membros` — the exact peer on
4685 // the M3 side, [`crate::AplicacaoSpec::validate_membros`];
4686 // `validate_contratos` — 906a5c6; `validate_entrada` — 20cd523;
4687 // `validate_placement`; `validate_politicas` routing through
4688 // `MeshPolicy::validate` — f03a154) — the M2 supervisor-slot
4689 // per-slot gate discipline now spans both the M3 mesh-slot
4690 // family and the M2 `:children` per-child-cascade axis on one
4691 // shape: one named per-slot gate per typed per-entry loop.
4692 self.validate_children()?;
4693 Ok(())
4694 }
4695
4696 /// Named per-slot gate on the M2 `:supervisor :children` per-entry
4697 /// axis — folds the per-child DNS-1123 name gate, semver-requirement
4698 /// gate, and duplicate-`:caixa` dedup arm into one call every
4699 /// consumer that wants to re-validate one `:children` entry (or the
4700 /// whole list) against the same accept-set [`SupervisorSpec::validate`]
4701 /// admits reaches through.
4702 ///
4703 /// Peer of the M3 mesh-slot [`crate::AplicacaoSpec::validate_membros`]
4704 /// per-slot gate on the analogous per-entry axis (`:membros`) — same
4705 /// three-per-entry shape (DNS-1123 name + semver-requirement +
4706 /// duplicate-`:caixa` dedup), lifted to one named substrate
4707 /// primitive per slot. The M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
4708 /// materializer's admission webhook re-checking one added or renamed
4709 /// child, the future wasm-operator's per-child dynamic-add
4710 /// re-validator on the `SimpleOneForOne` runtime-add path once
4711 /// dynamic-children graduate to a typed slot, a future partial
4712 /// re-validator on a per-`:children`-entry patch — each reaches the
4713 /// three per-entry axes through this one dispatch rather than
4714 /// re-inlining the three-arm cascade in lockstep with `validate`
4715 /// (the duplication the PRIME DIRECTIVE names as a bug) or paying
4716 /// the peer `:estrategia`/`:max-restarts`/`:restart-window` gates to
4717 /// reach one entry check.
4718 ///
4719 /// Self-contained on `&self` — resolves its own dedup `HashSet`
4720 /// through [`SupervisorSpec::children`] rather than borrowing one
4721 /// threaded down from `validate`, the same posture the peer M3
4722 /// mesh-slot per-slot gates ([`crate::AplicacaoSpec::validate_membros`],
4723 /// [`crate::AplicacaoSpec::validate_contratos`],
4724 /// [`crate::AplicacaoSpec::validate_entrada`],
4725 /// [`crate::AplicacaoSpec::validate_placement`]) each carry, so a
4726 /// consumer that reaches this gate directly (without first calling
4727 /// `validate`) still runs the full per-child cascade — pinned by
4728 /// `validate_children_matches_gate_on_per_axis_refusal_shapes` +
4729 /// `validate_children_matches_gate_on_versao_invalid_and_clean_pass`
4730 /// + `validate_children_is_self_contained_on_children_slot`.
4731 ///
4732 /// The three per-entry arms run in the same canonical order the
4733 /// pre-lift inline cascade encoded (DNS-1123 → semver → dedup), so
4734 /// the diagnostic every author-declared per-`:children` entry surfaces
4735 /// through `validate` is byte-equal to the diagnostic this gate
4736 /// surfaces when called directly — the equivalence-pin pair
4737 /// `validate_children_matches_gate_on_per_axis_refusal_shapes` +
4738 /// `validate_children_matches_gate_on_versao_invalid_and_clean_pass`
4739 /// asserts the two altitudes discriminate the same set on every
4740 /// per-entry-covered input.
4741 pub fn validate_children(&self) -> Result<(), SupervisorError> {
4742 let mut seen = std::collections::HashSet::new();
4743 for child in self.children() {
4744 // Every emitted cluster artifact's `metadata.name` for a
4745 // supervised child derives from this `:children :caixa` value
4746 // verbatim — the rendered `wasm.pleme.io/v1alpha1/ComputeUnit
4747 // .metadata.name` per child, the [`crate::LABEL_PROGRAM`]
4748 // label value on every child's pod identity, and the per-
4749 // child K8s [`Service`][svc] `metadata.name` the future
4750 // wasm-operator (M3) provisions for inter-child supervision
4751 // tree wiring. Each apiserver-side schema on each landing
4752 // site enforces the DNS-1123 label rule on admission; a
4753 // structurally invalid child name (`"Worker"`, `"my_worker"`,
4754 // `"team.worker"`, `"-worker"`, `"worker-"`, the >63-byte
4755 // UUID-shaped mistaken-identity slug) silently passes the
4756 // prior empty-/duplicate-only gate and the failure surfaces
4757 // at `kubectl apply` time as a `metadata.name: Invalid value`
4758 // rejection, far from the source caixa.lisp, with no field
4759 // naming the offending `:children` entry. Lifting the gate
4760 // to caixa-build time mirrors the `:membros :caixa` value-
4761 // shape trajectory (3f9d7a0) and the `:placement :clusters`
4762 // trajectory (6cbb900) onto the third DNS-1123-label-shaped
4763 // identifier axis — the supervisor tree's child names —
4764 // through the lifted
4765 // [`crate::render::require_valid_dns_1123_label`] gate the
4766 // seven peer name axes (`:membros :caixa`, `:placement
4767 // :clusters`, `:placement :affinity`, `:contratos :de`/`:para`,
4768 // `:entrada :para`, `:nome`, `:upgrade-from :module`) each
4769 // route through, so drift between the eight axes' accepted
4770 // DNS-1123-label sets is structurally impossible.
4771 //
4772 // [svc]: https://kubernetes.io/docs/concepts/services-networking/service/
4773 crate::render::require_valid_dns_1123_label(
4774 child.nome(),
4775 || SupervisorError::EmptyChildName,
4776 |reason| SupervisorError::child_caixa_invalid(child.nome(), reason),
4777 )?;
4778 // The author surface for `:children :versao` is the same
4779 // Cargo-shaped semver requirement string `:deps :versao` and
4780 // `:membros :versao` carry — and the lacre pipeline resolves
4781 // all three axes through the same
4782 // [`crate::version::parse_requirement`] entry-point. The
4783 // shared [`crate::render::require_valid_versao_requirement`]
4784 // helper brackets the empty-first + parse cascade both peer
4785 // axes ([`crate::dep::Dep::validate`] on `:deps :versao`,
4786 // [`crate::AplicacaoSpec::validate_membros`] on `:membros
4787 // :versao`) route through, so drift between the three axes'
4788 // accepted requirement sets is structurally impossible and
4789 // the parse-side no-op the empty-first arm closes (semver's
4790 // empty parse yields an implicit `*`) lives in exactly one
4791 // predicate. Every `ChildSpec::versao` past validate is
4792 // round-trippable through [`crate::parse_requirement`]
4793 // without re-checking at the resolver layer, and the three
4794 // `:versao` typed surfaces (`:deps`, `:membros`, `:children`)
4795 // are now structurally equivalent by construction.
4796 crate::render::require_valid_versao_requirement(
4797 child.versao_requirement(),
4798 || SupervisorError::empty_child_version(child.nome()),
4799 |reason| {
4800 SupervisorError::child_versao_invalid(
4801 child.nome(),
4802 child.versao_requirement(),
4803 reason,
4804 )
4805 },
4806 )?;
4807 crate::render::insert_first_seen(&mut seen, child.nome(), || {
4808 SupervisorError::duplicate_child_caixa(child.nome())
4809 })?;
4810 }
4811 Ok(())
4812 }
4813}
4814
4815/// Cross-slot coherence gate on the supervision tree: no
4816/// `:children :caixa` entry may name the supervisor's own `:nome`.
4817///
4818/// A supervisor that lists itself as a child is a degenerate self-parent
4819/// — the supervision tree is a DAG rooted at the supervisor (OTP child
4820/// specs reference *distinct* child processes; a supervisor is never its
4821/// own child), and the wasm-operator's hierarchical reconciliation would
4822/// otherwise be handed a node that is its own parent: a one-node cycle it
4823/// either rejects far from the source `caixa.lisp` or recurses on. Because
4824/// every `:nome` is a globally-unique substrate identity (DNS-1123 label +
4825/// lacre closure root), a child whose `:caixa` equals the supervisor's
4826/// `:nome` *is* the supervisor itself, not a coincidentally-named peer.
4827///
4828/// Lives outside [`SupervisorSpec::validate`] because the typed view
4829/// carries the children but not the parent `:nome`; mirrors the
4830/// cross-slot precedence gate `validate_upgrade_from_against_versao`
4831/// (which likewise reads one slot against another at the
4832/// [`crate::layout`] wire-up site) and the mesh self-edge gate
4833/// `AplicacaoSpec`'s `ContratoSelfLoop` — the same "an edge from a graph
4834/// node to itself is structurally not a tree/mesh edge" discipline, here
4835/// on the supervision-tree axis.
4836pub fn validate_no_self_supervision(
4837 children: &[ChildSpec],
4838 parent_nome: &str,
4839) -> Result<(), SupervisorError> {
4840 for child in children {
4841 if child.nome() == parent_nome {
4842 return Err(SupervisorError::child_supervises_self(parent_nome));
4843 }
4844 }
4845 Ok(())
4846}
4847
4848#[derive(Debug, Error, PartialEq, Eq)]
4849pub enum SupervisorError {
4850 #[error("supervisor :estrategia {estrategia:?} requires at least one :children entry")]
4851 NoChildren { estrategia: RestartStrategy },
4852 #[error(
4853 "SimpleOneForOne supervisors must declare zero static children (children spawn dynamically)"
4854 )]
4855 SimpleOneForOneWithStaticChildren,
4856 #[error(":max-restarts must be > 0")]
4857 ZeroMaxRestarts,
4858 #[error(
4859 ":supervisor :max-restarts ({max_restarts}) exceeds the supervisor-policy ceiling \
4860 (SUPERVISOR_MAX_RESTARTS_MAX = 1000) — a value above this cap turns the typed \
4861 restart-intensity policy into a no-op supervisor: the escalation threshold is \
4862 structurally so high that no realistic restarts-per-:restart-window traffic shape \
4863 can reach it, so the supervisor never escalates to its parent and a bad child can \
4864 loop inside the window indefinitely. Every typed-slot consumer (Erlang/OTP's \
4865 MaxIntensity/Period ratio, the future wasm-operator's per-supervisor \
4866 restart-intensity counter, the M4 mesh.pleme.io/v1alpha1/Supervisor CR \
4867 materializer's admission webhook) emits a `:max-restarts` declaration that is \
4868 structurally never reached. Pin a value in 1..=1000 (Erlang/OTP / Elixir / Riak \
4869 Core / RabbitMQ production playbooks recommend 3..=100; the OTP `supervisor` \
4870 callback module's `MaxR = 1` minimal-restart default sits at the bottom of the \
4871 band) or restructure the supervision tree (split the flaky child into its own \
4872 sub-supervisor with a tighter budget) if you need a higher restart tolerance."
4873 )]
4874 MaxRestartsExceedsCap { max_restarts: u32 },
4875 #[error(
4876 ":restart-window must be > 0 when set — Erlang/OTP's MaxIntensity/Period \
4877 requires Period > 0; a zero window either trips on the first failure or \
4878 never trips depending on operator interpretation. Omit :restart-window to \
4879 express `never reset`; carry a positive duration to express the window."
4880 )]
4881 RestartWindowZero,
4882 #[error(
4883 ":supervisor :restart-window ({window:?}) carries a sub-millisecond residue the shared `duration_codec` cannot round-trip — \
4884 the codec truncates to `as_millis()` before picking the canonical unit, so a value with `subsec_nanos() % 1_000_000 != 0` either \
4885 truncates on first serialize (e.g. `Duration::from_micros(1500)` → \"1ms\" → `Duration::from_millis(1)` ≠ original) or renders \
4886 as \"0s\" the `RestartWindowZero` arm then rejects on re-validate. Pin an integer-millisecond magnitude in the canonical authoring form \
4887 (`<integer><unit>` for unit ∈ {{ms, s, m, h}}, e.g. `\"500ms\"`, `\"30s\"`, `\"2m\"`, `\"1h\"`) or omit the field for `never reset`"
4888 )]
4889 RestartWindowNotCanonical { window: Duration },
4890 #[error(
4891 ":supervisor :restart-window ({window:?}) exceeds the supervisor-policy ceiling \
4892 (SUPERVISOR_RESTART_WINDOW_MAX = 1h = 3600s) — a value above this cap turns the typed \
4893 per-supervisor rolling-window restart-intensity counter into a lifetime counter: the \
4894 failure-counting window is structurally so long that transient restarts are never \
4895 forgotten, the MaxIntensity/Period ratio degenerates from `trip the parent supervisor \
4896 when the child has exceeded its restart budget within the recent window` to `trip the \
4897 parent when the child has exceeded its restart budget over its lifetime`, and the \
4898 supervisor's reset semantic never reaches the child — every typed-slot consumer \
4899 (Erlang/OTP's MaxIntensity/Period reconciler, the future wasm-operator's \
4900 per-supervisor restart-intensity counter, the M4 mesh.pleme.io/v1alpha1/Supervisor CR \
4901 materializer's admission webhook, the caixa-operator's hierarchical reconciliation \
4902 scheduler) emits a `:restart-window` declaration that is structurally a no-op rolling \
4903 window. Pin a value in 1ms..=1h (Learn You Some Erlang's `{{intensity, 5, 60}}` \
4904 worker-supervisor `Period = 60s` default, Elixir's `Supervisor` `max_seconds: 5` \
4905 default, OTP's `supervisor` callback module `MaxT = 5..=60` typical, Riak Core's \
4906 `MaxT ∈ 10s..=300s`, RabbitMQ broker-supervisor `MaxT = 5s` default — every Erlang/OTP \
4907 / Elixir production playbook sits in the 5s..=300s band; the longest documented \
4908 per-supervisor restart-window any pleme-io substrate playbook recommends maxes at \
4909 ~30m) or omit :restart-window to express `never reset` (the supervisor's restart \
4910 budget then becomes a strict lifetime counter by design, not a degenerate one — the \
4911 author surfaces the lifetime-counter semantic explicitly at the slot, rather than \
4912 hiding it behind a rolling-window declaration the cap arm rejects)"
4913 )]
4914 RestartWindowExceedsCap { window: Duration },
4915 #[error("child entry has empty :caixa name")]
4916 EmptyChildName,
4917 #[error(
4918 "child :caixa {caixa:?} is not a valid DNS-1123 label: {reason} \
4919 (the K8s apiserver enforces this rule on every `metadata.name` / Service \
4920 name / label value the child name lands in — the per-child \
4921 `wasm.pleme.io/v1alpha1/ComputeUnit.metadata.name`, the `LABEL_PROGRAM` \
4922 label value, and the future wasm-operator per-child Service `metadata.name` \
4923 — each apiserver-side schema rejects names that don't match; use a \
4924 lowercase alphanumeric + hyphen identifier like `\"worker\"` or `\"cache-v2\"`)"
4925 )]
4926 ChildCaixaInvalid { caixa: String, reason: String },
4927 #[error("child {caixa:?} has empty :versao constraint")]
4928 EmptyChildVersion { caixa: String },
4929 #[error(
4930 "child {caixa:?} :versao {versao:?} is not a valid semver requirement: \
4931 {reason} (use Cargo-shaped forms like `\"^0.1\"`, `\"~0.1.2\"`, \
4932 `\"0.1.0\"`, or `\"*\"` — the same shape `:deps :versao` and \
4933 `:membros :versao` carry; the lacre pipeline resolves all three \
4934 through the same parser)"
4935 )]
4936 ChildVersaoInvalid {
4937 caixa: String,
4938 versao: String,
4939 reason: String,
4940 },
4941 #[error(
4942 "child {caixa:?} appears more than once (Erlang/OTP requires unique \
4943 child_spec.id per supervisor; duplicate children materialize as duplicate \
4944 ComputeUnits in the rendered chart, one silently overwriting the other)"
4945 )]
4946 DuplicateChildCaixa { caixa: String },
4947 #[error(
4948 "supervisor {caixa:?} lists itself as a :children entry — a supervisor is \
4949 never its own child (the supervision tree is a DAG rooted at the supervisor; \
4950 OTP child specs reference distinct child processes). Since every :nome is a \
4951 globally-unique substrate identity, a child naming the supervisor's own :nome \
4952 is a one-node reconciliation cycle, not a coincidentally-named peer; drop the \
4953 self-referential :children entry or rename it to the actual child caixa."
4954 )]
4955 ChildSupervisesSelf { caixa: String },
4956}
4957
4958// Fold the three `SupervisorError::<Variant> { caixa: <&str>.to_string() }`
4959// caixa-only struct-variant wire-up sites at [`SupervisorSpec::validate_children`]
4960// and [`validate_no_self_supervision`] onto one substrate primitive per
4961// typed variant — the sibling on `SupervisorError` of the four uniform-shape
4962// `LayoutError`-envelope constructor families the peer
4963// [`crate::layout::layout_violation_ctors!`] macro closed (131ca0d, 16
4964// variants on `{ caixa, issue }`), the [`crate::layout::layout_slot_kind_ctors!`]
4965// macro closed (0419438, 4 variants on `{ caixa, kind, slots }`), the
4966// [`crate::LayoutError::missing_entry`] one-variant ctor closed (1b09f9d,
4967// on `{ kind, path }`), and the [`crate::layout::layout_nome_only_ctors!`]
4968// macro closed (3fe3dd7, 6 variants on `<Variant>(String)`), plus the
4969// [`crate::AplicacaoError::entrada_host_invalid`] one-variant ctor
4970// (17dd504, `{ host, reason }`), the [`crate::aplicacao::contrato_target_ctors!`]
4971// macro (14b81d5, 2 variants on `{ de, para, wit, expected }`), and the
4972// [`crate::aplicacao::contrato_empty_pair_ctors!`] macro (8580068, 4
4973// variants on `{ de, para }`) already at that discipline on the peer
4974// `AplicacaoError` envelopes.
4975//
4976// Each of the three wire-up sites on this shape (`EmptyChildVersion` at
4977// the per-`:children` semver-requirement empty-first arm, `DuplicateChildCaixa`
4978// at the per-`:children` dedup arm, `ChildSupervisesSelf` at the cross-slot
4979// self-supervision arm) opened the identical
4980// `SupervisorError::<Variant> { caixa: <&str>.to_string() }` struct-literal —
4981// the exact "same block re-inlined at every consumer" shape the PRIME
4982// DIRECTIVE names as a bug, on the same altitude the peer `LayoutError` /
4983// `AplicacaoError` families each closed on their sibling envelopes. The
4984// three variants share one `{ caixa: String }` shape, so the fold routes
4985// each wire-up site through one dispatch per typed variant.
4986//
4987// The macro below generates one static constructor per variant of shape
4988// `fn <slot>(caixa: &str) -> SupervisorError`, so every wire-up site
4989// collapses onto one dispatch:
4990// `SupervisorError::<slot>(<&str>)`, byte-equal to the pre-lift
4991// struct-literal on the same `&str` fixture. The uniform one-field
4992// construction (`caixa: caixa.to_string()`) is spelled once — inside the
4993// macro — rather than at every wire-up site. Every constructor is
4994// `#[must_use]` so a caller who mistakenly discards the constructed error
4995// trips a compile warning at the wire-up site.
4996//
4997// Every future consumer that wants to construct one of these three
4998// variants outside `SupervisorSpec::validate_children` /
4999// `validate_no_self_supervision` — a deferred
5000// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission
5001// webhook re-checking one added/renamed child, a future
5002// `feira validate --supervisor` per-caixa admission verb, a per-child
5003// dynamic-add re-validator on the `SimpleOneForOne` runtime-add path
5004// once dynamic-children graduate to a typed slot, a per-Supervisor
5005// overlay resolver rejecting a duplicate/self-supervising child against
5006// a cluster-local snapshot — now reaches each variant through one call
5007// rather than re-inlining the three-line struct-literal in lockstep
5008// with the three in-crate wire-up sites.
5009macro_rules! supervisor_caixa_only_ctors {
5010 ($($ctor:ident => $variant:ident),* $(,)?) => {
5011 impl SupervisorError {
5012 $(
5013 #[doc = concat!(
5014 "Construct a [`SupervisorError::",
5015 stringify!($variant),
5016 "`] naming the offending `:children :caixa` (or ",
5017 "supervisor `:nome`, on the self-supervision arm). ",
5018 "Folds the uniform `Self::",
5019 stringify!($variant),
5020 " { caixa: caixa.to_string() }` one-field ",
5021 "struct-literal onto one substrate primitive so ",
5022 "every [`SupervisorSpec::validate_children`] / ",
5023 "[`validate_no_self_supervision`] wire-up on this ",
5024 "variant reads through one dispatch rather than the ",
5025 "pre-lift open-coded struct-literal block."
5026 )]
5027 #[must_use]
5028 pub fn $ctor(caixa: &str) -> Self {
5029 Self::$variant { caixa: caixa.to_string() }
5030 }
5031 )*
5032 }
5033 };
5034}
5035
5036supervisor_caixa_only_ctors! {
5037 empty_child_version => EmptyChildVersion,
5038 duplicate_child_caixa => DuplicateChildCaixa,
5039 child_supervises_self => ChildSupervisesSelf,
5040}
5041
5042// Fold the two `SupervisorError::{ChildCaixaInvalid, ChildVersaoInvalid}`
5043// struct-variant wire-up sites at [`SupervisorSpec::validate_children`] onto
5044// one substrate primitive per typed variant — the M2 supervisor-side siblings
5045// of the peer [`crate::AplicacaoError::membro_caixa_invalid`] two-slot ctor
5046// already lifted through the sibling
5047// [`crate::aplicacao::aplicacao_field_reason_ctors!`] macro (981060b) on the
5048// peer `AplicacaoError { caixa: String, reason: String }` envelope. The
5049// `ChildCaixaInvalid` variant carries the same `{ <name>: String, reason:
5050// String }` two-slot shape the peer seven-variant
5051// [`crate::aplicacao::aplicacao_field_reason_ctors!`] fold closed on the
5052// `AplicacaoError` envelope (`MembroCaixaInvalid`, `EntradaParaInvalid`,
5053// `EntradaHostInvalid`, `EntradaPathInvalid`, `PlacementClusterInvalid`,
5054// `PlacementAffinityInvalid`, `ShardKeyInvalid`); the `ChildVersaoInvalid`
5055// variant carries the `{ caixa: String, versao: String, reason: String }`
5056// three-slot shape the sibling `AplicacaoError::MembroVersaoInvalid` axis
5057// carries on the same `:versao` value-shape.
5058//
5059// Each of the two wire-up sites opened the same closure-shaped
5060// `|reason| SupervisorError::<Variant> { caixa: child.nome().to_string(),
5061// [versao: child.versao_requirement().to_string(),] reason }` block inside
5062// the paired [`crate::render::require_valid_dns_1123_label`] and
5063// [`crate::render::require_valid_versao_requirement`] callbacks — the exact
5064// "same block re-inlined at every consumer" shape the PRIME DIRECTIVE names
5065// as a bug, on the same altitude the peer `AplicacaoError` /
5066// `SupervisorError` / `LayoutError` / `DepError` / `LimitsError` ctor
5067// families already closed on their sibling envelopes.
5068//
5069// The two `#[must_use]` inherent constructors below fold each wire-up onto
5070// one dispatch: `SupervisorError::child_caixa_invalid(<name>, <reason>)`
5071// and `SupervisorError::child_versao_invalid(<name>, <versao>, <reason>)`,
5072// byte-equal to the pre-lift struct-literal on the same scalar fixtures.
5073// The uniform per-field `.to_string()` / `.into()` construction is spelled
5074// once — inside each ctor body — rather than at every wire-up site. The
5075// `reason: impl Into<String>` bound accepts both `&str` literals and
5076// `format!(…)` outputs verbatim so no wire-up site changes its per-arm
5077// diagnostic shape at the lift, matching the peer
5078// [`aplicacao_field_reason_ctors!`] and
5079// [`crate::aplicacao::contrato_pair_value_reason_ctors!`] bounds on the
5080// sibling envelopes.
5081//
5082// Every future consumer that wants to construct one of these two variants
5083// outside `SupervisorSpec::validate_children` — a deferred
5084// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission webhook
5085// re-checking one added/renamed child's `:caixa` or `:versao`, a future
5086// `feira validate --supervisor` per-caixa admission verb, a per-child
5087// dynamic-add re-validator on the `SimpleOneForOne` runtime-add path once
5088// dynamic-children graduate to a typed slot, a per-Supervisor overlay
5089// resolver rejecting a shape-invalid child `:caixa`/`:versao` against a
5090// cluster-local snapshot — now reaches each variant through one call rather
5091// than re-inlining the per-shape struct-literal block in lockstep with the
5092// two in-crate wire-up sites.
5093impl SupervisorError {
5094 /// Construct a [`SupervisorError::ChildCaixaInvalid`] naming the
5095 /// offending `:children :caixa` value under the given `reason`. Folds
5096 /// the uniform `Self::ChildCaixaInvalid { caixa: caixa.to_string(),
5097 /// reason: reason.into() }` two-slot struct-literal onto one substrate
5098 /// primitive so every wire-up on this variant reads through one
5099 /// dispatch, matching the peer
5100 /// [`crate::AplicacaoError::membro_caixa_invalid`] ctor's shape on the
5101 /// sibling `AplicacaoError { caixa: String, reason: String }`
5102 /// envelope. `reason` accepts both `&str` literals and `format!(…)`
5103 /// outputs through the `impl Into<String>` bound.
5104 #[must_use]
5105 pub fn child_caixa_invalid(caixa: &str, reason: impl Into<String>) -> Self {
5106 Self::ChildCaixaInvalid {
5107 caixa: caixa.to_string(),
5108 reason: reason.into(),
5109 }
5110 }
5111
5112 /// Construct a [`SupervisorError::ChildVersaoInvalid`] naming the
5113 /// offending `:children :caixa` and its `:versao` requirement under
5114 /// the given `reason`. Folds the uniform `Self::ChildVersaoInvalid {
5115 /// caixa: caixa.to_string(), versao: versao.to_string(), reason:
5116 /// reason.into() }` three-slot struct-literal onto one substrate
5117 /// primitive so every wire-up on this variant reads through one
5118 /// dispatch, matching the sibling `AplicacaoError::MembroVersaoInvalid
5119 /// { caixa, versao, reason }` three-slot axis on the peer
5120 /// `AplicacaoError` envelope. `reason` accepts both `&str` literals
5121 /// and `format!(…)` outputs through the `impl Into<String>` bound.
5122 #[must_use]
5123 pub fn child_versao_invalid(caixa: &str, versao: &str, reason: impl Into<String>) -> Self {
5124 Self::ChildVersaoInvalid {
5125 caixa: caixa.to_string(),
5126 versao: versao.to_string(),
5127 reason: reason.into(),
5128 }
5129 }
5130}
5131
5132// Fold the four `SupervisorError::<Variant> { <field>: <Copy> }` one-field
5133// Copy-scalar struct-variant wire-up sites at [`SupervisorSpec::validate`]'s
5134// three bracket-arms — one struct-literal at the `:children`-empty
5135// non-`SimpleOneForOne` refusal cascade (`NoChildren { estrategia }`) plus
5136// three `impl FnOnce(<ty>) -> SupervisorError` bracket-closures at the
5137// [`crate::render::require_positive_bounded_u32`] `:max-restarts` cap arm
5138// (`MaxRestartsExceedsCap { max_restarts }`) and the paired
5139// [`crate::render::require_positive_canonical_bounded_duration`]
5140// `:restart-window` canonical-form + cap arms (`RestartWindowNotCanonical
5141// { window }`, `RestartWindowExceedsCap { window }`) — onto one substrate
5142// primitive per typed variant, matching the sibling
5143// [`crate::aplicacao::aplicacao_policy_scalar_ctors!`] macro (7ef425e, 8
5144// variants on the same `{ <field>: Duration | u32 }` shape) at that
5145// discipline on the peer `AplicacaoError` envelope's per-`:politicas`
5146// scalar axis. Every variant is a one-field `Copy`-pass-through struct-
5147// literal — `RestartStrategy | u32 | Duration` — so the fold routes each
5148// wire-up site through one dispatch per typed variant without a runtime-
5149// work delta.
5150//
5151// Each of the four wire-up sites opened the identical
5152// `SupervisorError::<Variant> { <field>: <val> }` struct-literal — the
5153// exact "same block re-inlined at every consumer" shape the PRIME
5154// DIRECTIVE names as a bug, on the same altitude the peer
5155// `aplicacao_policy_scalar_ctors!` fold closed on the sibling
5156// `AplicacaoError` envelope's per-`:politicas` per-axis cap / canonical-
5157// form arms. The four variants share one `{ <field>: <Copy> }` shape, so
5158// the fold routes each wire-up site through one dispatch per typed
5159// variant.
5160//
5161// The macro below generates one static constructor per variant of shape
5162// `const fn <ctor>(<field>: <ty>) -> SupervisorError`, so every wire-up
5163// site collapses onto one dispatch: `SupervisorError::<ctor>(<val>)`,
5164// byte-equal to the pre-lift struct-literal on the same `Copy`-`<ty>`
5165// fixture — as a direct call at the [`SupervisorSpec::validate`]
5166// `:children`-empty refusal, or as a bare function pointer in the
5167// `impl FnOnce(<ty>) -> SupervisorError` bracket-closure slot every
5168// [`crate::render::require_positive_bounded_u32`] /
5169// [`crate::render::require_positive_canonical_bounded_duration`] gate
5170// carries — rather than the pre-lift open-coded one-line closure over
5171// the same one-field struct-literal. `const fn` preserves the `Copy`-
5172// pass-through's zero-runtime-work property verbatim. Every constructor
5173// is `#[must_use]` so a caller who mistakenly discards the constructed
5174// error trips a compile warning at the wire-up site.
5175//
5176// Every future consumer that wants to construct one of these four
5177// variants outside `SupervisorSpec::validate` — a deferred
5178// `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's admission
5179// webhook re-checking one edited `:estrategia` / `:max-restarts` /
5180// `:restart-window` slot against the cap + canonical-form cascade, a
5181// future `feira validate --supervisor` per-caixa admission verb re-
5182// running the shape gates on demand, a per-Supervisor overlay resolver
5183// rejecting an author-supplied slot against a cluster-local snapshot —
5184// now reaches each variant through one call rather than re-inlining the
5185// per-shape struct-literal block in lockstep with the four in-crate
5186// wire-up sites.
5187macro_rules! supervisor_scalar_ctors {
5188 ($($ctor:ident => $variant:ident { $field:ident: $ty:ty }),* $(,)?) => {
5189 impl SupervisorError {
5190 $(
5191 #[doc = concat!(
5192 "Construct a [`SupervisorError::",
5193 stringify!($variant),
5194 "`] naming the offending per-`:supervisor` `",
5195 stringify!($field),
5196 "` scalar. Folds the uniform `Self::",
5197 stringify!($variant),
5198 " { ",
5199 stringify!($field),
5200 " }` one-field `Copy`-pass-through struct-literal onto ",
5201 "one substrate primitive so every per-axis wire-up on ",
5202 "this variant reads through one dispatch — as a direct ",
5203 "call (`SupervisorError::",
5204 stringify!($ctor),
5205 "(<val>)`, byte-equal to the pre-lift struct-literal on ",
5206 "the same `Copy`-`",
5207 stringify!($ty),
5208 "` fixture) or as a bare function pointer in the ",
5209 "`impl FnOnce(",
5210 stringify!($ty),
5211 ") -> SupervisorError` bracket-closure slot every ",
5212 "`crate::render::require_positive_bounded_*` / ",
5213 "`crate::render::require_positive_canonical_bounded_*` ",
5214 "gate carries — rather than the pre-lift open-coded ",
5215 "one-line closure over the same one-field struct-",
5216 "literal. `const fn` preserves the `Copy`-pass-through's ",
5217 "zero-runtime-work property verbatim."
5218 )]
5219 #[must_use]
5220 pub const fn $ctor($field: $ty) -> Self {
5221 Self::$variant { $field }
5222 }
5223 )*
5224 }
5225 };
5226}
5227
5228supervisor_scalar_ctors! {
5229 no_children => NoChildren { estrategia: RestartStrategy },
5230 max_restarts_exceeds_cap => MaxRestartsExceedsCap { max_restarts: u32 },
5231 restart_window_not_canonical => RestartWindowNotCanonical { window: Duration },
5232 restart_window_exceeds_cap => RestartWindowExceedsCap { window: Duration },
5233}
5234
5235/// Shared duration string codec for the typed slots that take a
5236/// duration (`restart_window`, `MeshPolicy::timeout`,
5237/// `CircuitBreaker::window`, …). Public so [`crate::aplicacao`] can
5238/// reuse it without duplicating the parser.
5239pub mod duration_codec {
5240 use super::Duration;
5241 use serde::{Deserializer, Serializer};
5242
5243 pub fn serialize<S: Serializer>(v: &Option<Duration>, s: S) -> Result<S::Ok, S::Error> {
5244 // Route through the canonical [`crate::render::serialize_option_via_str`]
5245 // — the substrate-side single-owner primitive for the forward
5246 // arm of the typed-magnitude codec family. See its docstring
5247 // for the full sibling roster.
5248 crate::render::serialize_option_via_str(v, s, render)
5249 }
5250
5251 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Option<Duration>, D::Error> {
5252 // Route through the canonical [`crate::render::deserialize_option_via_str`]
5253 // — the substrate-side single-owner primitive for the reverse
5254 // arm of the typed-magnitude codec family. See its docstring
5255 // for the full sibling roster.
5256 crate::render::deserialize_option_via_str(d, parse)
5257 }
5258
5259 pub(crate) fn parse(s: &str) -> Result<Duration, String> {
5260 // Paired whitespace-rejection arm — same canonical-form
5261 // render-determinism discipline as the peer
5262 // `limits::parse_byte_size` / `limits::parse_duration` /
5263 // `limits::parse_millicores` /
5264 // `aplicacao::rate_limit_codec::parse` sites: the ASCII
5265 // byte-scan closes the WhatWG-conformant whitespace bytes
5266 // (`0x20`, `0x09`, `0x0A`, `0x0C`, `0x0D`), the non-ASCII
5267 // `char::is_whitespace` scan closes the strictly-complementary
5268 // Unicode `White_Space` class (NBSP `\u{00A0}`, LINE SEPARATOR
5269 // `\u{2028}`, EM-SPACE `\u{2003}`, and the peer typography
5270 // codepoints) that `str::trim` at parse entry silently strips.
5271 // Either drift class would round-trip through `render` to a
5272 // *different* canonical form on next emit — breaking the
5273 // THEORY.md Part V render-determinism contract on three typed-
5274 // duration slots at once (`:supervisor :restart-window`,
5275 // `:politicas :timeout`, `:politicas :circuit-breaker :window`)
5276 // via the shared codec.
5277 //
5278 // Routed through the lifted [`crate::render::reject_whitespace`]
5279 // primitive — the substrate-side single-owner paired-arm gate
5280 // every typed-magnitude codec in caixa-core shares.
5281 crate::render::reject_whitespace::<String, _, _>(
5282 s,
5283 |b| {
5284 format!(
5285 "duration: value {s:?} contains whitespace byte 0x{b:02x} — the canonical \
5286 authoring form for the typed duration slots routed through this shared codec \
5287 (`:supervisor :restart-window`, `:politicas :timeout`, \
5288 `:politicas :circuit-breaker :window`) is `<integer><unit>` (e.g. \
5289 `\"30s\"`, `\"500ms\"`, `\"2m\"`, `\"1h\"`) with no whitespace bytes \
5290 anywhere. A whitespace-carrying shape (`\" 30s\"`, `\"30s \"`, `\"30 s\"`, \
5291 `\"\\t30s\"`, `\"30s\\n\"`) round-trips through `render` to a *different* \
5292 canonical form (`\"30s\"`) on first serialize — breaking the THEORY.md \
5293 Part V render-determinism contract every typed slot carries. Strip every \
5294 whitespace byte (write `\"30s\"` verbatim)"
5295 )
5296 },
5297 |ch| {
5298 format!(
5299 "duration: value {s:?} contains non-ASCII Unicode whitespace character \
5300 {ch:?} (U+{cp:04X}) — the canonical authoring form for the typed \
5301 duration slots routed through this shared codec (`:supervisor \
5302 :restart-window`, `:politicas :timeout`, `:politicas :circuit-breaker \
5303 :window`) is `<integer><unit>` (e.g. `\"30s\"`, `\"500ms\"`, `\"2m\"`, \
5304 `\"1h\"`) with no whitespace characters anywhere (ASCII or Unicode). A \
5305 non-ASCII-whitespace-carrying shape (`\"\\u{{00A0}}30s\"`, \
5306 `\"30s\\u{{2028}}\"`, `\"30\\u{{2003}}s\"`) survives the ASCII byte-scan \
5307 but `str::trim` (which uses `char::is_whitespace` — the Unicode \
5308 `White_Space` property, strictly wider than the ASCII byte set) silently \
5309 strips it at parse entry, and the value round-trips through `render` to \
5310 a *different* canonical form (`\"30s\"`) on first serialize — breaking \
5311 the THEORY.md Part V render-determinism contract every typed slot \
5312 carries. Strip every non-ASCII whitespace character (write `\"30s\"` \
5313 verbatim with only ASCII bytes)",
5314 cp = ch as u32
5315 )
5316 },
5317 )?;
5318 let s = s.trim();
5319 // Routed through the lifted
5320 // [`crate::render::split_magnitude_and_alpha_unit`] primitive —
5321 // the single-owner split every ASCII-alphabetic-unit typed-
5322 // magnitude codec in caixa-core (`limits::parse_byte_size` /
5323 // `limits::parse_duration` / this shared duration codec) shares.
5324 // See its docstring for the full sibling roster on the same
5325 // primitive altitude.
5326 let (num_part, unit) = crate::render::split_magnitude_and_alpha_unit(s);
5327 let num_trim = num_part.trim();
5328 // The canonical authoring form for every typed slot routed
5329 // through this shared codec — `:supervisor :restart-window`,
5330 // `:politicas :timeout`, `:politicas :circuit-breaker :window`
5331 // — is `<integer><unit>`. Every magnitude [`render`] emits is a
5332 // non-negative integer with no decimal point and no leading
5333 // sign, so the parser's accepted set must match for
5334 // serialize/deserialize to round-trip without canonical-form
5335 // drift. Until this gate landed the parser accepted any
5336 // `f64`-shaped magnitude (`"1.5s"` → 1500ms, `"1.0s"` → 1s,
5337 // `"0.5m"` → 30s, `"+30s"` → 30s) and serde silently round-
5338 // tripped the value to a *different* canonical string on the
5339 // next emit (`"1.5s"` → 1500ms → `"1500ms"`, `"1.0s"` → 1s →
5340 // `"1s"`, `"0.5m"` → 30s → `"30s"`, `"+30s"` → 30s → `"30s"`)
5341 // — breaking the THEORY.md Part V render-determinism contract
5342 // on three typed slots at once. Same canonical-form discipline
5343 // `crate::limits::parse_duration` (818dd38, the immediate
5344 // predecessor on the peer `:limits :wall-clock` codec) applies;
5345 // this gate lifts the discipline onto the shared codec that
5346 // backs the remaining three typed-duration slots in caixa-core.
5347 //
5348 // Strict canonical form: every byte of the magnitude is an
5349 // ASCII digit (no `.`, no `+`, no `-`). On non-digit-only
5350 // inputs the gate distinguishes "non-canonical-but-numeric"
5351 // (parses as f64 or i64 — surfaced with a self-locating
5352 // diagnostic naming the canonical authoring form, the
5353 // round-trip drift each rejected shape would produce on first
5354 // serialize, and the canonical-form remediation) from
5355 // "garbage" (parses as neither — surfaced with the existing
5356 // narrower "bad duration magnitude" wording so its diagnostic
5357 // shape remains stable for the parser-shape footgun case).
5358 // The pre-existing `num < 0.0` arm is now unreachable — the
5359 // digit-only gate strictly precedes magnitude parsing, and a
5360 // leading `-` is not an ASCII digit, so `"-30s"` lands on the
5361 // non-canonical-but-numeric branch with the `-30` named
5362 // verbatim in the diagnostic rather than the prior
5363 // value-laundered "negative duration in \"-30s\"" wording.
5364 //
5365 // Routed through the lifted
5366 // [`crate::render::is_digit_only_magnitude`] predicate — the
5367 // same source of truth the four peer typed-magnitude codec
5368 // sites share.
5369 let digit_only = crate::render::is_digit_only_magnitude(num_trim);
5370 if !digit_only {
5371 let numeric = num_trim.parse::<f64>().is_ok() || num_trim.parse::<i64>().is_ok();
5372 if numeric {
5373 return Err(format!(
5374 "duration: magnitude {num_trim:?} is not a non-negative integer — the \
5375 canonical authoring form for the typed duration slots routed through \
5376 this shared codec (`:supervisor :restart-window`, `:politicas :timeout`, \
5377 `:politicas :circuit-breaker :window`) is `<integer><unit>` (e.g. \
5378 `\"30s\"`, `\"500ms\"`, `\"2m\"`, `\"1h\"`) with no decimal point and \
5379 no leading `+` / `-` sign. A fractional / decimal-shaped magnitude \
5380 (`\"1.5s\"`, `\"1.0s\"`, `\"0.5m\"`, `\"+30s\"`, `\"-30s\"`) round-trips \
5381 through `render` to a *different* canonical form (`\"1500ms\"`, `\"1s\"`, \
5382 `\"30s\"`, `\"30s\"`, `\"30s\"`) on first serialize — breaking the \
5383 THEORY.md Part V render-determinism contract every typed slot carries. \
5384 Pick an integer magnitude in the unit that divides cleanly (write \
5385 `\"1500ms\"` instead of `\"1.5s\"`; `\"30s\"` instead of `\"0.5m\"`)"
5386 ));
5387 }
5388 return Err(format!("bad duration magnitude in {s:?}"));
5389 }
5390 // Leading-zero arm — peer with the `rate_limit_codec` leading-
5391 // zero arm (4f46830) on the same canonical-form render-
5392 // determinism axis. The digit-only gate accepts `"030s"`,
5393 // `"00s"`, `"01h"`, `"0500ms"` as `u64::from_str` parses them
5394 // losslessly (= 30, 0, 1, 500), but `render` emits the leading-
5395 // zero-stripped form (`"30s"`, `"0s"`, `"1h"`, `"500ms"`) — a
5396 // *different* canonical string on the next emit, breaking the
5397 // THEORY.md Part V render-determinism contract the same way
5398 // `"+30s"` did before the leading-`+` arm landed. The single-
5399 // byte magnitude `"0"` (or `"0s"` / `"0ms"`) round-trips
5400 // losslessly through `render` (`render(Duration::ZERO)` emits
5401 // `"0s"`) — the downstream semantic-zero gates (e.g.
5402 // `SupervisorError::ZeroRestartWindow` on
5403 // `:supervisor :restart-window`,
5404 // `AplicacaoError::PolicyTimeoutZero` /
5405 // `PolicyCircuitBreakerWindowZero` on the typed `:politicas`
5406 // duration slots) refuse zero-magnitude authoring at the typed-
5407 // validate layer above, so the single-byte `"0"` stays in the
5408 // accepted set at this codec layer and the diagnostic
5409 // partitioning between canonical-form drift (this arm) and
5410 // semantic-zero (the downstream gates) remains stable.
5411 // Peer with the future leading-zero arms on the two remaining
5412 // typed-magnitude codecs the trajectory acknowledges:
5413 // `limits::parse_duration` backing `:limits :wall-clock`,
5414 // `limits::parse_byte_size` backing `:limits :memory` — each
5415 // carries the same canonical-form-drift class today; this
5416 // gate lands the discipline on the shared duration codec
5417 // first because the `rate_limit_codec` predecessor on the
5418 // same canonical-form-drift axis is the closest peer on the
5419 // trajectory.
5420 //
5421 // Routed through the lifted
5422 // [`crate::render::is_leading_zero_padded_magnitude`]
5423 // predicate — the same source of truth the four peer
5424 // typed-magnitude codec sites share.
5425 if crate::render::is_leading_zero_padded_magnitude(num_trim) {
5426 return Err(format!(
5427 "duration: magnitude {num_trim:?} has a non-canonical leading zero — the \
5428 canonical authoring form for the typed duration slots routed through \
5429 this shared codec (`:supervisor :restart-window`, `:politicas :timeout`, \
5430 `:politicas :circuit-breaker :window`) is `<integer><unit>` (e.g. \
5431 `\"30s\"`, `\"500ms\"`, `\"2m\"`, `\"1h\"`) with no leading-zero padding \
5432 on the magnitude. A leading-zero magnitude (`\"030s\"`, `\"00s\"`, \
5433 `\"01h\"`, `\"0500ms\"`) round-trips through `render` to a *different* \
5434 canonical form (`\"30s\"`, `\"0s\"`, `\"1h\"`, `\"500ms\"`) on first \
5435 serialize — breaking the THEORY.md Part V render-determinism contract \
5436 every typed slot carries. Strip the leading zeros (write \
5437 `\"30s\"` instead of `\"030s\"`)"
5438 ));
5439 }
5440 // The digit-only gate guarantees every byte is `[0-9]`, and
5441 // the leading-zero arm above guarantees the magnitude is
5442 // either the single byte `"0"` or starts with `[1-9]`, so
5443 // the only way `u64::from_str` can fail here is overflow (the
5444 // magnitude exceeds `u64::MAX`). Surface that with an
5445 // overflow-shaped wording so the diagnostic names the offending
5446 // magnitude verbatim rather than collapsing onto the
5447 // non-canonical arm. The codec now operates on `u64` end-to-end
5448 // — every accepted magnitude is integer-exact; no f64 mantissa
5449 // drift between author-supplied magnitude and the consumer's
5450 // `Duration` value. Same shape `crate::limits::parse_duration`
5451 // (818dd38) carries on the peer `:limits :wall-clock` axis.
5452 let num: u64 = num_trim.parse::<u64>().map_err(|_| {
5453 format!("bad duration magnitude in {s:?} (digit-only magnitude overflows u64)")
5454 })?;
5455 // Route the `{"ms" | "s" | "" | "m" | "h"} → Duration`
5456 // unit-arm dispatch through the canonical
5457 // [`crate::render::duration_from_integer_magnitude_and_unit`]
5458 // primitive — the substrate-side single-owner unit-dispatch
5459 // table every typed-duration codec in caixa-core routes
5460 // through (peer: `crate::limits::parse_duration` backing
5461 // `:limits :wall-clock`). Every unit conversion is integer-
5462 // exact for an integer magnitude; overflow surfaces via the
5463 // typed `DurationUnitError::Overflow { multiplier }`
5464 // discriminant so this arm reconstructs the pre-lift
5465 // `"duration <num><unit> overflows u64 (magnitude × 60 …)"`
5466 // wording verbatim from `num` / `unit_trim` / the returned
5467 // `multiplier`, and the unknown-unit arm reconstructs the
5468 // pre-lift `"unknown duration unit \"<other>\""` wording from
5469 // the caller-scoped `unit_trim`. Load-bearing pinned by
5470 // `crate::render::tests::duration_from_integer_magnitude_and_unit_matches_pre_lift_unit_dispatch_table`.
5471 let unit_trim = unit.trim();
5472 let dur = crate::render::duration_from_integer_magnitude_and_unit(num, unit_trim).map_err(
5473 |e| match e {
5474 crate::render::DurationUnitError::Overflow { multiplier } => format!(
5475 "duration {num}{unit_trim} overflows u64 (magnitude × {multiplier} > 2^64-1)"
5476 ),
5477 crate::render::DurationUnitError::UnknownUnit => {
5478 format!("unknown duration unit {unit_trim:?}")
5479 }
5480 },
5481 )?;
5482 Ok(dur)
5483 }
5484
5485 /// Render a [`Duration`] in the canonical pleme-io duration string
5486 /// form (`"30s"`, `"1m"`, `"1h"`, `"500ms"`). The same form every
5487 /// caixa typed-duration slot serializes to and the same form K8s
5488 /// Gateway API HTTPRoute `timeouts` / `backendRequest` and Cilium
5489 /// EnvoyConfig per-route timeouts both expect (an integer
5490 /// followed by `s`/`m`/`h`/`ms`, no fractional values, no leading
5491 /// `+`). Lifted to `pub` so caixa-side renderers
5492 /// (`caixa-mesh::gateway_routes`'s :politicas :timeout overlay,
5493 /// the future per-:politicas `CiliumClusterwideEnvoyConfig`
5494 /// emitter, the future caixa-otel collector pipeline emitter) can
5495 /// consume the same canonical formatter without re-inlining the
5496 /// magnitude/unit decision tree (and inheriting the same drift
5497 /// footguns: a subtly different `300ms` vs `0.3s` rendering breaks
5498 /// downstream apply-time parsing in non-obvious ways).
5499 pub fn render(d: Duration) -> String {
5500 let total_ms = d.as_millis();
5501 if total_ms == 0 {
5502 return "0s".into();
5503 }
5504 if total_ms.is_multiple_of(3600 * 1000) {
5505 return format!("{}h", total_ms / (3600 * 1000));
5506 }
5507 if total_ms.is_multiple_of(60 * 1000) {
5508 return format!("{}m", total_ms / (60 * 1000));
5509 }
5510 if total_ms.is_multiple_of(1000) {
5511 return format!("{}s", total_ms / 1000);
5512 }
5513 format!("{total_ms}ms")
5514 }
5515
5516 /// True iff `d` round-trips losslessly through [`render`] + [`parse`].
5517 ///
5518 /// [`render`] truncates a `Duration` to `as_millis()` before picking the
5519 /// largest divisor unit, so any sub-millisecond residue
5520 /// (`d.subsec_nanos() % 1_000_000 != 0`) silently breaks the THEORY.md
5521 /// §V.2.7 render-determinism contract:
5522 ///
5523 /// - `Duration::from_micros(1500)` (= `1_500_000` ns) → `as_millis() == 1`
5524 /// → renders `"1ms"` → parses back to `Duration::from_millis(1)` =
5525 /// `1_000_000` ns ≠ original `1_500_000` ns;
5526 /// - `Duration::from_nanos(1)` (= 1 ns) → `as_millis() == 0` →
5527 /// renders the literal `"0s"`, which the per-axis zero-floor gate
5528 /// on every typed-`Duration` slot then rejects on re-validate.
5529 ///
5530 /// Lifted to a `pub` predicate next to the [`render`] / [`parse`] pair so
5531 /// the codec's round-trippable accepted set lives in exactly one place —
5532 /// every typed-`Duration` slot that routes through this shared codec
5533 /// (`SupervisorSpec::restart_window` via [`super::duration_codec`],
5534 /// [`crate::MeshPolicy::timeout`] / [`crate::CircuitBreaker::window`] via
5535 /// `supervisor::duration_codec` + [`super::duration_codec_required`]) and
5536 /// every typed-`Duration` slot whose own codec shares the same
5537 /// `as_millis()`-truncation shape ([`crate::LimitsSpec::wall_clock`] via
5538 /// [`crate::limits`]'s in-module `parse_duration` / `render_duration`
5539 /// pair) calls this predicate from its `validate()` to bracket the
5540 /// accepted set against the codec's accepted set, structurally. Drift
5541 /// between the codec's granularity and any typed slot's accepted set is
5542 /// then a single-source-of-truth edit at this predicate rather than a
5543 /// silent round-trip break the next consumer discovers at apply time.
5544 ///
5545 /// Peer of [`crate::aplicacao::POLICY_RETRIES_MAX`] /
5546 /// [`crate::LIMITS_MEMORY_WASM32_MAX_BYTES`] and the
5547 /// `is_dns_1123_label` / `is_canonical_rate_limit_window` predicate
5548 /// family — same "typed-slot's valid set matches its codec's accepted
5549 /// set, structurally" discipline carried at the codec layer.
5550 #[must_use]
5551 pub fn is_integer_millisecond_duration(d: Duration) -> bool {
5552 d.subsec_nanos().is_multiple_of(1_000_000)
5553 }
5554}
5555
5556/// Required-Duration variant for fields that aren't Option<Duration>.
5557pub mod duration_codec_required {
5558 use super::Duration;
5559 use serde::{Deserialize, Deserializer, Serializer};
5560
5561 pub fn serialize<S: Serializer>(v: &Duration, s: S) -> Result<S::Ok, S::Error> {
5562 s.serialize_str(&super::duration_codec::render(*v))
5563 }
5564
5565 pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Duration, D::Error> {
5566 let s = String::deserialize(d)?;
5567 super::duration_codec::parse(&s).map_err(serde::de::Error::custom)
5568 }
5569}
5570
5571#[cfg(test)]
5572mod tests {
5573 use super::*;
5574
5575 fn child(name: &str, ver: &str, restart: RestartPolicy) -> ChildSpec {
5576 ChildSpec {
5577 caixa: name.into(),
5578 versao: ver.into(),
5579 restart,
5580 }
5581 }
5582
5583 #[test]
5584 fn child_spec_string_scalar_accessor_pair_is_const_fn() {
5585 // Fail-before-pass-after pin on [`ChildSpec::nome`] +
5586 // [`ChildSpec::versao_requirement`]'s `const`-eval-surface
5587 // posture. Each accessor projects the per-`:children :caixa`
5588 // / per-`:children :versao` [`String`] storage through the
5589 // `pub const fn` [`String::as_str`] (const-stable since Rust
5590 // 1.87, well within the workspace MSRV) — any future
5591 // accidental downgrade to non-`const` fails the corresponding
5592 // `<name>_via_const_fn` wrapper at caixa-core build time with
5593 // E0015 (`cannot call non-const method`), strictly stronger
5594 // than a runtime `assert!`. Sibling of the peer
5595 // per-M2/M3/universal-axis `String → &str` scalar-accessor
5596 // family pins on the sibling `const`-eval-surface passes
5597 // ([`crate::Caixa::nome`] / [`crate::Caixa::versao`] at the
5598 // top-level manifest, [`crate::CaixaVersion::as_str`] at the
5599 // typed-newtype wrapper, [`crate::aplicacao::Membro::nome`] /
5600 // [`crate::aplicacao::Membro::versao_requirement`] at the M3
5601 // membership axis, [`crate::aplicacao::Entrada::hostname`] /
5602 // [`crate::aplicacao::Entrada::destination`] at the M3
5603 // ingress axis,
5604 // [`crate::upgrade::UpgradeFromEntry::prior_versao`] at the
5605 // M2 upgrade axis, [`crate::dep::Dep::nome`] /
5606 // [`crate::dep::Dep::versao_requirement`] at the dep-graph
5607 // axis, and the per-`:contratos`
5608 // [`crate::aplicacao::WitContract::source`] /
5609 // [`crate::aplicacao::WitContract::destination`] /
5610 // [`crate::aplicacao::WitContract::world_ref`] trio the
5611 // sibling pin at 279823b already anchors).
5612 const fn nome_via_const_fn(c: &ChildSpec) -> &str {
5613 c.nome()
5614 }
5615 const fn versao_via_const_fn(c: &ChildSpec) -> &str {
5616 c.versao_requirement()
5617 }
5618 for (caixa, versao) in [
5619 ("worker-a", "^0.1"),
5620 ("worker-b", "~0.2.3"),
5621 ("collector", "*"),
5622 ] {
5623 let c = child(caixa, versao, RestartPolicy::Permanent);
5624 assert_eq!(nome_via_const_fn(&c), c.nome());
5625 assert_eq!(versao_via_const_fn(&c), c.versao_requirement());
5626 assert_eq!(c.nome(), caixa);
5627 assert_eq!(c.versao_requirement(), versao);
5628 }
5629 }
5630
5631 #[test]
5632 fn supervisor_children_slice_return_accessor_is_const_fn() {
5633 // Fail-before-pass-after pin on [`SupervisorSpec::children`]'s
5634 // `const`-eval-surface posture. The accessor destructures the
5635 // per-`:children` `Vec<ChildSpec>` storage through the
5636 // `pub const fn` [`Vec::as_slice`] (const-stable since Rust
5637 // 1.66, well within the workspace MSRV) — any future
5638 // accidental downgrade to non-`const` fails
5639 // `children_via_const_fn` at caixa-core build time with E0015
5640 // (`cannot call non-const method`), strictly stronger than a
5641 // runtime `assert!`. Sibling of the peer per-M3-mesh-slot
5642 // `Vec → &[T]` slice-return accessor family pin
5643 // [`crate::aplicacao::tests::m3_reference_return_accessor_family_is_const_fn`]
5644 // on the M3 mesh-slot per-`:clusters` / per-`:paths` /
5645 // per-`:membros` / per-`:contratos` slice-return axes, and of
5646 // the peer M2 upgrade-appup axis pin
5647 // [`crate::upgrade::tests::upgrade_from_entry_instructions_slice_return_accessor_is_const_fn`]
5648 // on the per-`:upgrade-from :instructions` slice-return axis.
5649 const fn children_via_const_fn(s: &SupervisorSpec) -> &[ChildSpec] {
5650 s.children()
5651 }
5652 // Sweep both the empty-children (leaf-supervisor with no
5653 // static children — the `SimpleOneForOne` dynamic-child
5654 // arm's canonical shape) and the populated-children
5655 // (`OneForOne` / `OneForAll` / `RestForOne` static-child
5656 // arm's canonical shape) axes so the accessor carries a
5657 // const-dispatch pin on both arms.
5658 let s_empty = SupervisorSpec {
5659 estrategia: RestartStrategy::SimpleOneForOne,
5660 max_restarts: SUPERVISOR_MAX_RESTARTS_DEFAULT,
5661 restart_window: Some(SUPERVISOR_RESTART_WINDOW_DEFAULT),
5662 children: vec![],
5663 };
5664 assert!(children_via_const_fn(&s_empty).is_empty());
5665 assert_eq!(children_via_const_fn(&s_empty), s_empty.children());
5666 let s_full = SupervisorSpec {
5667 estrategia: RestartStrategy::OneForOne,
5668 max_restarts: SUPERVISOR_MAX_RESTARTS_DEFAULT,
5669 restart_window: Some(SUPERVISOR_RESTART_WINDOW_DEFAULT),
5670 children: vec![
5671 child("worker-a", "^0.1", RestartPolicy::Permanent),
5672 child("worker-b", "~0.2.3", RestartPolicy::Transient),
5673 child("collector", "*", RestartPolicy::Temporary),
5674 ],
5675 };
5676 assert_eq!(children_via_const_fn(&s_full).len(), 3);
5677 assert_eq!(children_via_const_fn(&s_full), s_full.children());
5678 }
5679
5680 #[test]
5681 fn default_has_one_for_one_and_5_restarts_in_60s() {
5682 let s = SupervisorSpec::default();
5683 assert_eq!(s.estrategia, RestartStrategy::OneForOne);
5684 assert_eq!(s.max_restarts, 5);
5685 assert_eq!(s.restart_window, Some(Duration::from_secs(60)));
5686 assert!(s.children.is_empty());
5687 }
5688
5689 #[test]
5690 fn validate_one_for_one_requires_children() {
5691 // Explicit-empty via struct-update rather than `let mut s = default(); s.children = vec![];`
5692 // — the peer `validate_simple_one_for_one_forbids_static_children` below already uses
5693 // struct-update to name the axis under test at construction, and this shape matches
5694 // it. Also keeps the "empty children is the axis under test" intent visible at the
5695 // binding site rather than one line down, and side-steps `clippy::field_reassign_with_default`.
5696 let mut s = SupervisorSpec {
5697 children: vec![],
5698 ..SupervisorSpec::default()
5699 };
5700 assert!(matches!(
5701 s.validate().unwrap_err(),
5702 SupervisorError::NoChildren { .. }
5703 ));
5704 s.children = vec![child("worker", "^0.1", RestartPolicy::Permanent)];
5705 s.validate().unwrap();
5706 }
5707
5708 #[test]
5709 fn validate_simple_one_for_one_forbids_static_children() {
5710 let mut s = SupervisorSpec {
5711 estrategia: RestartStrategy::SimpleOneForOne,
5712 ..SupervisorSpec::default()
5713 };
5714 s.children
5715 .push(child("w", "^0.1", RestartPolicy::Permanent));
5716 assert_eq!(
5717 s.validate().unwrap_err(),
5718 SupervisorError::SimpleOneForOneWithStaticChildren
5719 );
5720 s.children.clear();
5721 s.validate().unwrap();
5722 }
5723
5724 #[test]
5725 fn validate_rejects_zero_max_restarts() {
5726 let s = SupervisorSpec {
5727 max_restarts: 0,
5728 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5729 ..SupervisorSpec::default()
5730 };
5731 assert_eq!(s.validate().unwrap_err(), SupervisorError::ZeroMaxRestarts);
5732 }
5733
5734 // ── upper-cap: SUPERVISOR_MAX_RESTARTS_MAX brackets the typed slot ─────
5735 //
5736 // The cap arm lifts the `:politicas :circuit-breaker :max-failures` /
5737 // `POLICY_BREAKER_MAX_FAILURES_MAX` (2b51ace) discipline onto the peer
5738 // `:supervisor :max-restarts` axis — both fields are "trip the
5739 // next-higher protection layer after N events in a rolling window"
5740 // counters with identical degenerate-at-the-high-end shape, so the
5741 // typed-slot's accepted set lies in `1..=1000` on the supervisor side
5742 // exactly as it lies in `1..=1000` on the breaker side.
5743
5744 #[test]
5745 fn validate_rejects_max_restarts_above_cap() {
5746 // The fail-before-pass-after pin: `SUPERVISOR_MAX_RESTARTS_MAX +
5747 // 1` is structurally one past the cap and silently passed
5748 // validate on every pre-gate codebase because the typed slot's
5749 // only check was the zero-floor arm. The no-op-supervisor vector
5750 // only surfaced at the runtime substrate (Erlang/OTP
5751 // MaxIntensity/Period ratio, the future wasm-operator's
5752 // per-supervisor restart-intensity counter) far from the source
5753 // caixa.lisp with no field naming the offending supervisor.
5754 let s = SupervisorSpec {
5755 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
5756 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5757 ..SupervisorSpec::default()
5758 };
5759 assert_eq!(
5760 s.validate().unwrap_err(),
5761 SupervisorError::MaxRestartsExceedsCap {
5762 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
5763 }
5764 );
5765 }
5766
5767 #[test]
5768 fn validate_rejects_max_restarts_far_above_cap() {
5769 // The `u32::MAX` worst case — the four-billion-restart
5770 // threshold a typo (`:max-restarts 4294967295`) or a
5771 // struct-literal copy-paste lands in the slot. Pin the cap
5772 // arm's coverage explicitly across the full `u32` overflow so
5773 // a future relaxation that drops the upper bound surfaces
5774 // here. Same shape every other typed-cap arm on this surface
5775 // carries (POLICY_BREAKER_MAX_FAILURES_MAX,
5776 // POLICY_RETRIES_MAX, POLICY_RATE_LIMIT_MAX).
5777 let s = SupervisorSpec {
5778 max_restarts: u32::MAX,
5779 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5780 ..SupervisorSpec::default()
5781 };
5782 assert_eq!(
5783 s.validate().unwrap_err(),
5784 SupervisorError::MaxRestartsExceedsCap {
5785 max_restarts: u32::MAX,
5786 }
5787 );
5788 }
5789
5790 #[test]
5791 fn validate_accepts_max_restarts_at_cap() {
5792 // The boundary value — exactly SUPERVISOR_MAX_RESTARTS_MAX —
5793 // must validate. The cap is inclusive on the top edge,
5794 // matching the POLICY_BREAKER_MAX_FAILURES_MAX /
5795 // POLICY_RETRIES_MAX / LIMITS_MEMORY_WASM32_MAX_BYTES
5796 // discipline on the sibling capped axes. Pin the boundary
5797 // explicitly so a future off-by-one tightening
5798 // (`>= SUPERVISOR_MAX_RESTARTS_MAX` instead of `>`) surfaces
5799 // here as a test failure rather than a silent contract
5800 // narrowing.
5801 let s = SupervisorSpec {
5802 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX,
5803 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5804 ..SupervisorSpec::default()
5805 };
5806 s.validate()
5807 .expect("max_restarts == SUPERVISOR_MAX_RESTARTS_MAX must validate");
5808 }
5809
5810 #[test]
5811 fn validate_accepts_max_restarts_typical_values() {
5812 // The documented production-playbook band positive-control
5813 // sweep — every value Erlang/OTP / Elixir / Riak Core /
5814 // RabbitMQ recommend (1..=100) must pass, plus a sweep
5815 // through the hyperscale band (200, 500, 1000) the cap
5816 // accepts. Pin the inclusive validated set explicitly so a
5817 // future tightening of the ceiling surfaces here.
5818 for n in [1u32, 3, 5, 10, 20, 50, 100, 200, 500, 1000] {
5819 let s = SupervisorSpec {
5820 max_restarts: n,
5821 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5822 ..SupervisorSpec::default()
5823 };
5824 s.validate()
5825 .unwrap_or_else(|e| panic!("max_restarts={n} must validate; got {e:?}"));
5826 }
5827 }
5828
5829 #[test]
5830 fn zero_max_restarts_takes_precedence_over_cap() {
5831 // The cross-arm ordering pin: `0` is structurally outside
5832 // both `1..` (zero-floor) and `..=SUPERVISOR_MAX_RESTARTS_MAX`
5833 // (cap), but the zero-floor diagnostic is the more
5834 // self-locating one (it directly names the counter-axis
5835 // remediation), so the validate gate must fire on zero first.
5836 // Same shape every other zero-then-shape ordering on this
5837 // surface uses (PolicyRetriesZero then
5838 // PolicyRetriesExceedsCap; PolicyBreakerZeroFailures then
5839 // PolicyBreakerMaxFailuresExceedsCap).
5840 let s = SupervisorSpec {
5841 max_restarts: 0,
5842 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5843 ..SupervisorSpec::default()
5844 };
5845 assert_eq!(
5846 s.validate().unwrap_err(),
5847 SupervisorError::ZeroMaxRestarts,
5848 "max_restarts == 0 must surface the zero-floor diagnostic, not the cap diagnostic"
5849 );
5850 }
5851
5852 #[test]
5853 fn max_restarts_cap_takes_precedence_over_restart_window_gates() {
5854 // The cross-arm ordering pin between the cap and the sibling
5855 // `:restart-window` gates (zero-window, canonical-window). A
5856 // supervisor carrying both an over-cap `max_restarts` AND a
5857 // structurally invalid window (zero, sub-ms) must surface the
5858 // cap diagnostic first — the cap arm is wired immediately
5859 // after the zero-restart arm and strictly before the window
5860 // arms, so the offending value the diagnostic names matches
5861 // the order the author would discover the gates by reading
5862 // top-to-bottom through `SupervisorSpec::validate`. Pin the
5863 // order so a future refactor that reorders the arms surfaces
5864 // here as a test failure rather than a silent diagnostic
5865 // regression. Peer of
5866 // `circuit_breaker_max_failures_cap_takes_precedence_over_window_gates`
5867 // on the sibling `:politicas :circuit-breaker` slot.
5868 let s = SupervisorSpec {
5869 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
5870 restart_window: Some(Duration::ZERO),
5871 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5872 ..SupervisorSpec::default()
5873 };
5874 assert_eq!(
5875 s.validate().unwrap_err(),
5876 SupervisorError::MaxRestartsExceedsCap {
5877 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
5878 },
5879 "over-cap max_restarts must surface the cap diagnostic before any window-axis diagnostic"
5880 );
5881 }
5882
5883 #[test]
5884 fn max_restarts_cap_diagnostic_carries_offending_value() {
5885 // The diagnostic-shape pin: the offending `u32` is carried
5886 // verbatim into the `SupervisorError::MaxRestartsExceedsCap`
5887 // variant so the surfaced error message names the value the
5888 // author wrote (`":supervisor :max-restarts (50000) exceeds the
5889 // supervisor-policy ceiling …"`), not just the cap. Same
5890 // self-locating diagnostic shape every other typed-cap arm on
5891 // this surface carries
5892 // (`AplicacaoError::PolicyBreakerMaxFailuresExceedsCap` carries
5893 // the offending failure count verbatim,
5894 // `AplicacaoError::PolicyRetriesExceedsCap` carries the offending
5895 // retries count verbatim).
5896 let s = SupervisorSpec {
5897 max_restarts: 50_000,
5898 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
5899 ..SupervisorSpec::default()
5900 };
5901 let err = s.validate().unwrap_err();
5902 assert!(
5903 matches!(
5904 err,
5905 SupervisorError::MaxRestartsExceedsCap {
5906 max_restarts: 50_000
5907 }
5908 ),
5909 "got {err:?}"
5910 );
5911 let msg = err.to_string();
5912 assert!(
5913 msg.contains("50000"),
5914 ":supervisor :max-restarts cap diagnostic must carry the offending value verbatim (got: {msg})"
5915 );
5916 }
5917
5918 #[test]
5919 fn supervisor_max_restarts_default_pins_otp_canonical_value() {
5920 // Pin [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] at `5` — the
5921 // Erlang/OTP-canonical `{intensity, 5, 60}` `MaxIntensity`
5922 // half of Learn You Some Erlang's worker-supervisor default,
5923 // sibling of the `60s` `Period` half that the paired
5924 // [`Default for SupervisorSpec`] impl already pins on the
5925 // sibling `restart_window` axis. Pinning the literal here
5926 // surfaces a future rebrand (a tightening to Elixir's `3`,
5927 // a widening to a per-cluster overlay the operator pins
5928 // through a future `:max-restarts-overrides` slot) as a
5929 // deliberate test edit, not a silent contract migration.
5930 // Peer of the sibling
5931 // [`supervisor_max_restarts_cap_pins_canonical_value`]
5932 // upper-bracket pin on the same axis.
5933 assert_eq!(SUPERVISOR_MAX_RESTARTS_DEFAULT, 5);
5934 }
5935
5936 #[test]
5937 fn default_max_restarts_helper_routes_through_lifted_default() {
5938 // Composition pin: the private `default_max_restarts()`
5939 // serde-`#[serde(default = "…")]` helper on
5940 // [`SupervisorSpec::max_restarts`] must route through the
5941 // substrate-canonical [`SUPERVISOR_MAX_RESTARTS_DEFAULT`]
5942 // typed `pub const` rather than a raw `5` literal. Prior to
5943 // the lift the helper carried an inline `5` with no compile-
5944 // time link back to the shared default, so the wire-format
5945 // author-omitted arm and the caixa-core
5946 // [`crate::manifest::Caixa::supervisor_view`] fold's `unwrap_or(5)`
5947 // arm could silently split on any future default rebrand.
5948 // Byte-parity against the lifted constant closes the split.
5949 assert_eq!(default_max_restarts(), SUPERVISOR_MAX_RESTARTS_DEFAULT);
5950 }
5951
5952 #[test]
5953 fn supervisor_spec_default_max_restarts_routes_through_lifted_default() {
5954 // Composition pin: the [`Default for SupervisorSpec`] impl's
5955 // struct-literal `max_restarts` field must route through the
5956 // substrate-canonical [`SUPERVISOR_MAX_RESTARTS_DEFAULT`]
5957 // typed `pub const` (via the private helper this test's
5958 // sibling `default_max_restarts_helper_routes_through_lifted_default`
5959 // already pins onto the constant). Structurally: every
5960 // `SupervisorSpec::default()` call must yield a
5961 // `max_restarts` field byte-equal to the lifted constant
5962 // (the two paired defaults — the serde-side wire-format arm
5963 // and the struct-literal default arm — cannot silently split
5964 // on any future default rebrand). Peer of the sibling
5965 // `default_has_one_for_one_and_5_restarts_in_60s` shape pin
5966 // — this pin closes the byte-parity arm on the two paired
5967 // altitude entry points onto the shared substrate constant.
5968 assert_eq!(
5969 SupervisorSpec::default().max_restarts(),
5970 SUPERVISOR_MAX_RESTARTS_DEFAULT,
5971 );
5972 }
5973
5974 #[test]
5975 fn supervisor_restart_window_default_pins_otp_canonical_value() {
5976 // Pin [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] at `60s` — the
5977 // Erlang/OTP-canonical `{intensity, 5, 60}` `Period` half of
5978 // Learn You Some Erlang's worker-supervisor default, paired
5979 // with the sibling `SUPERVISOR_MAX_RESTARTS_DEFAULT` `5`
5980 // `MaxIntensity` half this constant is the sliding-window
5981 // denominator of on the same `MaxIntensity / Period`
5982 // restart-intensity ratio. Pinning the literal here surfaces a
5983 // future coherent rebrand of the paired default (Elixir's
5984 // `{max_restarts: 3, max_seconds: 5}`, a per-cluster overlay
5985 // the operator pins through a future
5986 // `:restart-window-overrides` slot) as a deliberate test edit,
5987 // not a silent contract migration. Peer of the sibling
5988 // [`supervisor_max_restarts_default_pins_otp_canonical_value`]
5989 // paired-half pin on the same OTP-canonical default and the
5990 // [`supervisor_restart_window_cap_pins_canonical_value`]
5991 // upper-bracket pin on the same axis.
5992 assert_eq!(SUPERVISOR_RESTART_WINDOW_DEFAULT, Duration::from_secs(60),);
5993 }
5994
5995 #[test]
5996 fn supervisor_spec_default_restart_window_routes_through_lifted_default() {
5997 // Composition pin: the [`Default for SupervisorSpec`] impl's
5998 // struct-literal `restart_window` field must route through the
5999 // substrate-canonical [`SUPERVISOR_RESTART_WINDOW_DEFAULT`]
6000 // typed `pub const` rather than a raw
6001 // `Duration::from_secs(60)` literal. Prior to this lift the
6002 // paired `{intensity, 5, 60}` OTP-canonical default was split
6003 // across two altitudes with no compile-time link between the
6004 // halves — the `MaxIntensity` half rode through the lifted
6005 // [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] constant while the
6006 // `Period` half rode as an open-coded literal at the
6007 // composition site, so a future coherent rebrand of the paired
6008 // canonical would have had to migrate one half through the
6009 // constant and the other through a raw literal in lockstep.
6010 // Byte-parity against the lifted constant on the `Period` half
6011 // closes the split — the paired OTP-canonical default now
6012 // migrates as one unit on any future axis change. Peer of the
6013 // sibling
6014 // [`supervisor_spec_default_max_restarts_routes_through_lifted_default`]
6015 // byte-parity pin on the paired `MaxIntensity` half.
6016 assert_eq!(
6017 SupervisorSpec::default().restart_window(),
6018 Some(SUPERVISOR_RESTART_WINDOW_DEFAULT),
6019 );
6020 }
6021
6022 #[test]
6023 fn supervisor_estrategia_default_pins_otp_canonical_value() {
6024 // Pin [`SUPERVISOR_ESTRATEGIA_DEFAULT`] at [`RestartStrategy::OneForOne`]
6025 // — the Erlang/OTP-canonical `one_for_one` half of Learn You Some
6026 // Erlang's `{one_for_one, intensity, 5, 60}` worker-supervisor
6027 // canonical default, paired with the sibling
6028 // `SUPERVISOR_MAX_RESTARTS_DEFAULT` `5` `MaxIntensity` half and the
6029 // sibling `SUPERVISOR_RESTART_WINDOW_DEFAULT` `60s` `Period` half
6030 // this constant is the strategy discriminator of on the same
6031 // OTP-canonical worker-supervisor default. Pinning the arm here
6032 // surfaces a future coherent rebrand of the paired triple (Elixir's
6033 // `{:one_for_one, max_restarts: 3, max_seconds: 5}` on the sibling
6034 // intensity/period axes leaving this strategy arm untouched, an OTP
6035 // `rest_for_one` widening once the substrate discovers startup-
6036 // order-coupled child cohorts as the more common worker-supervisor
6037 // shape, a per-cluster overlay the operator pins through a future
6038 // `:estrategia-overrides` slot the MESH-COMPOSITION §III.2
6039 // supervision-canary roadmap acknowledges) as a deliberate test
6040 // edit, not a silent contract migration. Peer of the sibling
6041 // [`supervisor_max_restarts_default_pins_otp_canonical_value`] +
6042 // [`supervisor_restart_window_default_pins_otp_canonical_value`]
6043 // paired-half pins on the same OTP-canonical default.
6044 assert_eq!(SUPERVISOR_ESTRATEGIA_DEFAULT, RestartStrategy::OneForOne);
6045 }
6046
6047 #[test]
6048 fn restart_strategy_default_routes_through_lifted_default() {
6049 // Composition pin: the [`Default for RestartStrategy`] impl's
6050 // return arm must route through the substrate-canonical
6051 // [`SUPERVISOR_ESTRATEGIA_DEFAULT`] typed `pub const` rather than
6052 // a raw `Self::OneForOne` arm. Prior to the lift the impl carried
6053 // an inline `Self::OneForOne` with no compile-time link back to
6054 // the shared OTP-canonical `one_for_one` strategy the paired
6055 // [`Default for SupervisorSpec`] impl's struct-literal `estrategia`
6056 // field and the [`crate::manifest::Caixa::supervisor_view`] fold's
6057 // `.unwrap_or_default()` (now
6058 // `.unwrap_or(SUPERVISOR_ESTRATEGIA_DEFAULT)`) arm both key off —
6059 // so a future rebrand of the OTP-canonical strategy default (an
6060 // OTP `rest_for_one` widening once the substrate discovers
6061 // startup-order-coupled child cohorts as the more common worker-
6062 // supervisor shape, a per-cluster overlay the operator pins
6063 // through a future `:estrategia-overrides` slot) would have had to
6064 // be threaded through the `Default` impl and the two peer routes
6065 // in lockstep or the three consumers would silently split. Byte-
6066 // parity against the lifted constant closes the split. Peer of
6067 // the sibling
6068 // [`default_max_restarts_helper_routes_through_lifted_default`] +
6069 // [`supervisor_spec_default_restart_window_routes_through_lifted_default`]
6070 // composition pins on the paired `MaxIntensity` + `Period` halves.
6071 assert_eq!(RestartStrategy::default(), SUPERVISOR_ESTRATEGIA_DEFAULT,);
6072 }
6073
6074 #[test]
6075 fn supervisor_spec_default_estrategia_routes_through_lifted_default() {
6076 // Composition pin: the [`Default for SupervisorSpec`] impl's
6077 // struct-literal `estrategia` field must route through the
6078 // substrate-canonical [`SUPERVISOR_ESTRATEGIA_DEFAULT`] typed
6079 // `pub const` (either directly, or via the
6080 // [`RestartStrategy::default`] impl that the sibling
6081 // `restart_strategy_default_routes_through_lifted_default` pin
6082 // already routes onto the constant). Structurally: every
6083 // `SupervisorSpec::default()` call must yield an `estrategia`
6084 // field byte-equal to the lifted constant (the three paired
6085 // defaults — the [`Default for RestartStrategy`] impl arm, the
6086 // struct-literal default arm here, and the
6087 // [`crate::manifest::Caixa::supervisor_view`] fold arm — cannot
6088 // silently split on any future default rebrand). Peer of the
6089 // sibling
6090 // [`supervisor_spec_default_max_restarts_routes_through_lifted_default`]
6091 // + [`supervisor_spec_default_restart_window_routes_through_lifted_default`]
6092 // byte-parity pins on the paired `MaxIntensity` + `Period` halves
6093 // of the same `SupervisorSpec::default()` composed altitude.
6094 assert_eq!(
6095 SupervisorSpec::default().estrategia(),
6096 SUPERVISOR_ESTRATEGIA_DEFAULT,
6097 );
6098 }
6099
6100 #[test]
6101 fn supervisor_spec_default_routes_through_otp_canonical_ctor() {
6102 // Composition pin: the [`Default for SupervisorSpec`] impl must
6103 // route through the substrate-canonical
6104 // [`SupervisorSpec::otp_canonical`] `pub const fn` constructor
6105 // rather than a re-hand-authored struct-literal cascade. Sharpens
6106 // the sibling per-arm
6107 // `supervisor_spec_default_*_routes_through_lifted_default` pins
6108 // from a per-field lift into a whole-struct one-source-of-truth
6109 // pin — the derived-until-now [`Default::default`] and the
6110 // [`SupervisorSpec::otp_canonical`] constructor are byte-equal by
6111 // construction, not by coincidence.
6112 //
6113 // A future extension of the OTP-canonical baseline (a fifth
6114 // `restart_intensity` field the Erlang/OTP `#supervisor` record
6115 // grows, a per-child-cohort split of the `restart_window` /
6116 // `max_restarts` pair, an M4 `mesh.pleme.io/v1alpha1/Supervisor`
6117 // CR materializer's admission-time overlay pass) reaches both
6118 // paths through exactly one edit on
6119 // [`SupervisorSpec::otp_canonical`] — the derived path could
6120 // silently disagree with the constructor's shape on any new
6121 // field whose [`Default::default`] resolves to a different arm
6122 // than the OTP-canonical baseline the constructor names, while
6123 // this delegated impl reaches the constructor directly and
6124 // picks up every future extension by construction.
6125 //
6126 // Fourth peer on the M2 / M3 typed-slot-spec
6127 // [`Default`]-through-const-ctor fold family — sibling of the
6128 // [`crate::LimitsSpec`] [`Default`]-through-[`crate::LimitsSpec::empty`]
6129 // (abd52c2), [`crate::aplicacao::MeshPolicy`]
6130 // [`Default`]-through-[`crate::aplicacao::MeshPolicy::empty`]
6131 // (91641a4), and [`crate::BehaviorSpec`]
6132 // [`Default`]-through-[`crate::BehaviorSpec::empty`] (0c1752c)
6133 // per-`Option`-only-typed-slot folds — extended here onto the
6134 // M2 supervisor-slot [`SupervisorSpec`] whose canonical baseline
6135 // is not "everything `None`" but the Erlang/OTP-canonical
6136 // `{one_for_one, 5, 60}` worker-supervisor triple.
6137 assert_eq!(SupervisorSpec::default(), SupervisorSpec::otp_canonical());
6138 }
6139
6140 #[test]
6141 fn supervisor_spec_otp_canonical_byte_equals_default() {
6142 // Value pin: [`SupervisorSpec::otp_canonical`] must byte-equal
6143 // the hand-authored `{one_for_one, 5, 60, []}` OTP-canonical
6144 // baseline the sibling `default_has_one_for_one_and_5_restarts_in_60s`
6145 // pin already asserts against the [`Default::default`] path.
6146 // Sharpens the pair-invariant into a per-constructor pin so a
6147 // future extension of [`SupervisorSpec`] with a fifth field
6148 // whose OTP-canonical shape is non-`Default::default`-equivalent
6149 // trips at caixa-core test time rather than at a downstream
6150 // consumer that composed [`SupervisorSpec::otp_canonical`] with
6151 // [`SupervisorSpec::validate`] as its "canonical baseline
6152 // seed".
6153 let canonical = SupervisorSpec::otp_canonical();
6154 assert_eq!(canonical.estrategia, RestartStrategy::OneForOne);
6155 assert_eq!(canonical.max_restarts, 5);
6156 assert_eq!(canonical.restart_window, Some(Duration::from_secs(60)));
6157 assert!(canonical.children.is_empty());
6158 }
6159
6160 #[test]
6161 fn supervisor_spec_otp_canonical_is_usable_in_const_context() {
6162 // Const-context pin: [`SupervisorSpec::otp_canonical`] must
6163 // remain callable from a `const`-bound position so downstream
6164 // `const`-context callers wanting a canonical OTP-baseline seed
6165 // can construct one at compile time without runtime dispatch on
6166 // the derived [`Default::default`]. Peer of the sibling
6167 // `pub const fn` [`crate::LimitsSpec::empty`] /
6168 // [`crate::aplicacao::MeshPolicy::empty`] /
6169 // [`crate::BehaviorSpec::empty`] constructors on the sibling
6170 // typed-slot-spec `pub const fn` axis. If a future edit breaks
6171 // the `const`-eligibility of [`SupervisorSpec::otp_canonical`]
6172 // (a non-`const` field-default helper, a non-`const`-stable
6173 // container type promotion), this evaluation fails at
6174 // build time on this file rather than at a downstream
6175 // `const`-context call site.
6176 const CANONICAL: SupervisorSpec = SupervisorSpec::otp_canonical();
6177 assert_eq!(CANONICAL.estrategia, SUPERVISOR_ESTRATEGIA_DEFAULT);
6178 assert_eq!(CANONICAL.max_restarts, SUPERVISOR_MAX_RESTARTS_DEFAULT);
6179 assert_eq!(
6180 CANONICAL.restart_window,
6181 Some(SUPERVISOR_RESTART_WINDOW_DEFAULT),
6182 );
6183 assert!(CANONICAL.children.is_empty());
6184 }
6185
6186 #[test]
6187 fn supervisor_child_restart_default_pins_otp_canonical_value() {
6188 // Pin [`SUPERVISOR_CHILD_RESTART_DEFAULT`] at
6189 // [`RestartPolicy::Permanent`] — Erlang/OTP's `permanent`
6190 // worker-child restart type (`{ChildId, StartFunc, permanent, …}`
6191 // in a `supervisor`'s `init/1` child-spec tuple), the per-child
6192 // half of the same OTP-shape supervisor-tree default set whose
6193 // per-`:supervisor` halves the sibling
6194 // [`SUPERVISOR_ESTRATEGIA_DEFAULT`] /
6195 // [`SUPERVISOR_MAX_RESTARTS_DEFAULT`] /
6196 // [`SUPERVISOR_RESTART_WINDOW_DEFAULT`] constants pin. Pinning the
6197 // arm here surfaces a future rebrand of the per-child default (an
6198 // OTP-`transient` widening once the substrate discovers clean-
6199 // completion-aware children as the more common child shape, a
6200 // per-cluster overlay the operator pins through a future
6201 // `:restart-overrides` slot the MESH-COMPOSITION §III.2
6202 // supervision-canary roadmap acknowledges) as a deliberate test
6203 // edit, not a silent contract migration. Peer of the sibling
6204 // [`supervisor_estrategia_default_pins_otp_canonical_value`] /
6205 // [`supervisor_max_restarts_default_pins_otp_canonical_value`] /
6206 // [`supervisor_restart_window_default_pins_otp_canonical_value`]
6207 // value pins on the per-`:supervisor` halves.
6208 assert_eq!(SUPERVISOR_CHILD_RESTART_DEFAULT, RestartPolicy::Permanent);
6209 }
6210
6211 #[test]
6212 fn restart_policy_default_routes_through_lifted_default() {
6213 // Composition pin: the [`Default for RestartPolicy`] impl's return
6214 // arm must route through the substrate-canonical
6215 // [`SUPERVISOR_CHILD_RESTART_DEFAULT`] typed `pub const` rather
6216 // than a raw `Self::Permanent` arm. Prior to the lift the impl
6217 // carried an inline `Self::Permanent` with no compile-time link
6218 // back to the OTP-shape supervisor-tree default set whose three
6219 // per-`:supervisor` halves already rode through lifted constants
6220 // — so a future coherent rebrand of the set would have had to
6221 // migrate three halves through typed constants and this fourth
6222 // through a raw enum arm in lockstep or the supervisor-level and
6223 // child-level defaults would silently drift apart. Byte-parity
6224 // against the lifted constant closes the split. Peer of the
6225 // sibling
6226 // [`restart_strategy_default_routes_through_lifted_default`]
6227 // composition pin on the per-`:supervisor` `:estrategia` axis.
6228 assert_eq!(RestartPolicy::default(), SUPERVISOR_CHILD_RESTART_DEFAULT);
6229 }
6230
6231 #[test]
6232 fn child_spec_serde_default_restart_routes_through_lifted_default() {
6233 // Composition pin: the serde-side `#[serde(default)]` on
6234 // [`ChildSpec::restart`] — the wire-format author-omitted
6235 // `:children :restart` arm — must resolve onto the substrate-
6236 // canonical [`SUPERVISOR_CHILD_RESTART_DEFAULT`] typed `pub const`
6237 // (via the [`Default for RestartPolicy`] impl the sibling
6238 // `restart_policy_default_routes_through_lifted_default` pin
6239 // already routes onto the constant). Structurally: a `ChildSpec`
6240 // deserialized from a payload that omits the `restart` key must
6241 // yield a `restart` field byte-equal to the lifted constant, so
6242 // the wire-format author-omitted arm and the
6243 // [`RestartPolicy::default`] impl arm cannot silently split on any
6244 // future default rebrand. Peer of the sibling
6245 // [`supervisor_spec_default_estrategia_routes_through_lifted_default`]
6246 // / [`supervisor_spec_default_max_restarts_routes_through_lifted_default`]
6247 // / [`supervisor_spec_default_restart_window_routes_through_lifted_default`]
6248 // byte-parity pins on the per-`:supervisor` halves of the same
6249 // author-omitted-slot resolution surface.
6250 let omitted: ChildSpec = serde_json::from_str(r#"{"caixa":"worker","versao":"^0.1"}"#)
6251 .expect("ChildSpec must deserialize with the restart key omitted");
6252 assert_eq!(
6253 omitted.restart(),
6254 SUPERVISOR_CHILD_RESTART_DEFAULT,
6255 "an author-omitted :children :restart slot must degrade onto \
6256 the SUPERVISOR_CHILD_RESTART_DEFAULT typed pub const (got \
6257 {:?}, expected {:?})",
6258 omitted.restart(),
6259 SUPERVISOR_CHILD_RESTART_DEFAULT,
6260 );
6261 }
6262
6263 #[test]
6264 fn supervisor_max_restarts_cap_pins_canonical_value() {
6265 // The SUPERVISOR_MAX_RESTARTS_MAX constant pins the value at
6266 // 1000 — the same ceiling the peer
6267 // POLICY_BREAKER_MAX_FAILURES_MAX cap carries on the
6268 // `:politicas :circuit-breaker :max-failures` axis (both are
6269 // "trip the next-higher protection layer after N events in a
6270 // rolling window" counters with identical
6271 // degenerate-at-the-high-end shape; uniform top edge so the
6272 // M4 CR materializers and the wasm-operator reconciler reach
6273 // for either field knowing the value is in `1..=1000`). Two
6274 // orders of magnitude above every documented Erlang/OTP /
6275 // Elixir / Riak Core / RabbitMQ production-playbook
6276 // recommendation band and below the clearly-pathological
6277 // "effectively no escalation" floor (10_000, 100_000,
6278 // u32::MAX). Pinning the literal value here surfaces a future
6279 // drift (a relaxation to 10_000, a tightening to 100) as a
6280 // deliberate test edit, not a silent contract narrowing.
6281 assert_eq!(SUPERVISOR_MAX_RESTARTS_MAX, 1000);
6282 }
6283
6284 #[test]
6285 fn validate_rejects_empty_child_name() {
6286 let s = SupervisorSpec {
6287 children: vec![child("", "^0.1", RestartPolicy::Permanent)],
6288 ..SupervisorSpec::default()
6289 };
6290 assert_eq!(s.validate().unwrap_err(), SupervisorError::EmptyChildName);
6291 }
6292
6293 #[test]
6294 fn validate_rejects_empty_child_version() {
6295 let s = SupervisorSpec {
6296 children: vec![child("w", "", RestartPolicy::Permanent)],
6297 ..SupervisorSpec::default()
6298 };
6299 assert!(matches!(
6300 s.validate().unwrap_err(),
6301 SupervisorError::EmptyChildVersion { .. }
6302 ));
6303 }
6304
6305 // ── value-shape: parse-as-VersionReq on :children :versao ─────────────
6306
6307 #[test]
6308 fn validate_rejects_invalid_child_versao_requirement() {
6309 // The fail-before-pass-after pin: a non-empty but malformed
6310 // semver requirement (`"^bad-version"`) silently passed
6311 // `validate()` on every pre-gate codebase because the prior
6312 // shape only refused the empty string. The parse failure
6313 // surfaced far downstream at lacre-resolve time with a
6314 // `semver::Error` that didn't name which `:children` entry
6315 // carried the typo. The new gate moves the check to caixa-build
6316 // time at the source caixa.lisp — the third `:versao` typed
6317 // axis (`:children`) joins `:deps` and `:membros` (9888b13) at
6318 // structural parity.
6319 let s = SupervisorSpec {
6320 children: vec![
6321 child("worker", "^0.1", RestartPolicy::Permanent),
6322 child("cache", "^bad-version", RestartPolicy::Transient),
6323 ],
6324 ..SupervisorSpec::default()
6325 };
6326 let err = s.validate().unwrap_err();
6327 assert!(
6328 matches!(
6329 err,
6330 SupervisorError::ChildVersaoInvalid { ref caixa, ref versao, .. }
6331 if caixa == "cache" && versao == "^bad-version"
6332 ),
6333 "got {err:?}"
6334 );
6335 }
6336
6337 #[test]
6338 fn validate_rejects_child_versao_with_double_caret_typo() {
6339 // `"^^0.1"` is the canonical doubled-caret typo — looks
6340 // Cargo-shaped on first glance but fails the parser because
6341 // semver doesn't accept stacked operators. Pin this
6342 // adjacent-shape footgun explicitly so a future relaxation that
6343 // accepts "looks-canonical-but-isn't" forms surfaces here.
6344 let s = SupervisorSpec {
6345 children: vec![child("worker", "^^0.1", RestartPolicy::Permanent)],
6346 ..SupervisorSpec::default()
6347 };
6348 let err = s.validate().unwrap_err();
6349 assert!(
6350 matches!(
6351 err,
6352 SupervisorError::ChildVersaoInvalid { ref caixa, ref versao, .. }
6353 if caixa == "worker" && versao == "^^0.1"
6354 ),
6355 "got {err:?}"
6356 );
6357 }
6358
6359 #[test]
6360 fn validate_rejects_child_versao_with_v_prefixed_tag() {
6361 // `"v0.1"` is the canonical "git-tag-shape leaking into the
6362 // semver requirement slot" typo — an author copies the
6363 // publish-side git-tag string verbatim into `:versao`, but
6364 // Cargo's semver parser rejects the leading `v`. Same
6365 // adjacent-shape footgun pinned for `:membros :versao`
6366 // (9888b13).
6367 let s = SupervisorSpec {
6368 children: vec![child("worker", "v0.1", RestartPolicy::Permanent)],
6369 ..SupervisorSpec::default()
6370 };
6371 let err = s.validate().unwrap_err();
6372 assert!(
6373 matches!(
6374 err,
6375 SupervisorError::ChildVersaoInvalid { ref caixa, ref versao, .. }
6376 if caixa == "worker" && versao == "v0.1"
6377 ),
6378 "got {err:?}"
6379 );
6380 }
6381
6382 #[test]
6383 fn validate_accepts_canonical_child_versao_forms() {
6384 // The Cargo-shaped requirement forms `:deps :versao` and
6385 // `:membros :versao` already accept via
6386 // `crate::parse_requirement` must pass the children gate
6387 // without re-validating at the resolver layer. Pin every leg so
6388 // a future tightening of the canonical set surfaces here as a
6389 // test failure.
6390 for form in [
6391 "^0.1", // caret — minor-range pin (the most common shape)
6392 "~0.1.2", // tilde — patch-range pin
6393 "0.1.0", // exact — single-version pin
6394 "*", // wildcard — any version (semver::VersionReq::STAR)
6395 ">=0.1, <2", // multi-range — comma-separated comparators
6396 ] {
6397 let s = SupervisorSpec {
6398 children: vec![child("worker", form, RestartPolicy::Permanent)],
6399 ..SupervisorSpec::default()
6400 };
6401 s.validate()
6402 .unwrap_or_else(|e| panic!("canonical form {form:?} must validate, got {e:?}"));
6403 }
6404 }
6405
6406 #[test]
6407 fn child_versao_empty_takes_precedence_over_invalid() {
6408 // Order pin: the existing `EmptyChildVersion` diagnostic (which
6409 // doesn't try to parse) fires before the new
6410 // `ChildVersaoInvalid` parse-side diagnostic, so an empty
6411 // `:versao` keeps its narrower error message —
6412 // `parse_requirement` would also reject `""`, but the
6413 // empty-string arm is the more self-locating diagnostic for the
6414 // author. Same ordering discipline as
6415 // `membro_versao_empty_takes_precedence_over_invalid` in
6416 // aplicacao.rs.
6417 let s = SupervisorSpec {
6418 children: vec![child("worker", "", RestartPolicy::Permanent)],
6419 ..SupervisorSpec::default()
6420 };
6421 let err = s.validate().unwrap_err();
6422 assert!(
6423 matches!(err, SupervisorError::EmptyChildVersion { ref caixa } if caixa == "worker"),
6424 "got {err:?}"
6425 );
6426 }
6427
6428 #[test]
6429 fn child_versao_invalid_fires_before_duplicate_check() {
6430 // Order pin: a malformed requirement on a non-duplicate entry
6431 // surfaces *its own* diagnostic (which names the offending
6432 // `:versao` string), even when a later entry would otherwise
6433 // collapse onto an earlier name. The per-entry shape gate runs
6434 // inline before the duplicate-key insert — parallel to
6435 // `membro_versao_invalid_fires_before_duplicate_check` in
6436 // aplicacao.rs and the b0c8389 / c4213a4 ordering discipline.
6437 let s = SupervisorSpec {
6438 children: vec![
6439 child("worker", "^bad", RestartPolicy::Permanent),
6440 child("cache", "^0.1", RestartPolicy::Transient),
6441 child("worker", "^0.2", RestartPolicy::Permanent), // would otherwise raise DuplicateChildCaixa
6442 ],
6443 ..SupervisorSpec::default()
6444 };
6445 let err = s.validate().unwrap_err();
6446 assert!(
6447 matches!(
6448 err,
6449 SupervisorError::ChildVersaoInvalid { ref caixa, .. } if caixa == "worker"
6450 ),
6451 "got {err:?}"
6452 );
6453 }
6454
6455 #[test]
6456 fn child_versao_invalid_diagnostic_carries_offending_versao() {
6457 // The diagnostic-shape pin: the error names the offending
6458 // `:versao` value verbatim so the author can grep their
6459 // caixa.lisp without re-running the build, and carries a
6460 // non-empty `reason` from `semver::VersionReq::parse` so the
6461 // parser's own wording flows through to the diagnostic.
6462 let s = SupervisorSpec {
6463 children: vec![child("worker", "not-a-req", RestartPolicy::Permanent)],
6464 ..SupervisorSpec::default()
6465 };
6466 let err = s.validate().unwrap_err();
6467 let SupervisorError::ChildVersaoInvalid {
6468 caixa,
6469 versao,
6470 reason,
6471 } = err
6472 else {
6473 panic!("expected ChildVersaoInvalid, got other variant");
6474 };
6475 assert_eq!(caixa, "worker");
6476 assert_eq!(versao, "not-a-req");
6477 assert!(
6478 !reason.is_empty(),
6479 "ChildVersaoInvalid `reason` must carry the parser's wording verbatim"
6480 );
6481 }
6482
6483 // ── value-shape: DNS-1123 label rule on :children :caixa ──────────────
6484
6485 #[test]
6486 fn validate_rejects_child_caixa_with_uppercase() {
6487 // The canonical "I copied the Servico's display name verbatim"
6488 // typo — child caixa names are lowercase per K8s DNS-1123 label
6489 // rule. The diagnostic names the offending name and suggests the
6490 // lower-cased fix in one edit, mirroring the
6491 // `rejects_membro_caixa_with_uppercase` gate's shape (3f9d7a0).
6492 let s = SupervisorSpec {
6493 children: vec![child("Worker", "^0.1", RestartPolicy::Permanent)],
6494 ..SupervisorSpec::default()
6495 };
6496 let err = s.validate().unwrap_err();
6497 let SupervisorError::ChildCaixaInvalid { caixa, reason } = err else {
6498 panic!("expected ChildCaixaInvalid, got other variant");
6499 };
6500 assert_eq!(caixa, "Worker");
6501 assert!(
6502 reason.contains("uppercase"),
6503 "diagnostic must name the violation as `uppercase` (got: {reason:?})"
6504 );
6505 assert!(
6506 reason.contains("\"worker\""),
6507 "diagnostic must suggest the lower-cased fix verbatim (got: {reason:?})"
6508 );
6509 }
6510
6511 #[test]
6512 fn validate_rejects_child_caixa_with_underscore() {
6513 // The canonical "I'm thinking of a Python module / Postgres
6514 // table" leak — `_` is forbidden by every DNS-1123 / DNS-1035
6515 // label schema. K8s rejects `metadata.name: my_worker` at
6516 // admission time with an opaque `field is invalid` (no source-
6517 // citing diagnostic). The gate moves it to caixa-build time.
6518 let s = SupervisorSpec {
6519 children: vec![child("my_worker", "^0.1", RestartPolicy::Permanent)],
6520 ..SupervisorSpec::default()
6521 };
6522 let err = s.validate().unwrap_err();
6523 assert!(
6524 matches!(
6525 err,
6526 SupervisorError::ChildCaixaInvalid { ref caixa, ref reason }
6527 if caixa == "my_worker" && reason.contains('_')
6528 ),
6529 "got {err:?}"
6530 );
6531 }
6532
6533 #[test]
6534 fn validate_rejects_child_caixa_with_dot() {
6535 // A `:children :caixa` entry is a single DNS-1123 label, not a
6536 // subdomain. The K8s Service / ComputeUnit `metadata.name` rules
6537 // forbid dots. Same shape as `rejects_membro_caixa_with_dot`
6538 // (3f9d7a0) on the peer name axis.
6539 let s = SupervisorSpec {
6540 children: vec![child("team.worker", "^0.1", RestartPolicy::Permanent)],
6541 ..SupervisorSpec::default()
6542 };
6543 let err = s.validate().unwrap_err();
6544 assert!(
6545 matches!(
6546 err,
6547 SupervisorError::ChildCaixaInvalid { ref caixa, ref reason }
6548 if caixa == "team.worker" && reason.contains('.')
6549 ),
6550 "got {err:?}"
6551 );
6552 }
6553
6554 #[test]
6555 fn validate_rejects_child_caixa_with_leading_hyphen() {
6556 // DNS-1123 / DNS-1035 boundary rule: labels must start and end
6557 // with an alphanumeric. The K8s apiserver rejects `-worker`
6558 // outright; the renderer would emit a `metadata.name: "-worker"`
6559 // that fails admission far from the source caixa.lisp.
6560 let s = SupervisorSpec {
6561 children: vec![child("-worker", "^0.1", RestartPolicy::Permanent)],
6562 ..SupervisorSpec::default()
6563 };
6564 let err = s.validate().unwrap_err();
6565 assert!(
6566 matches!(
6567 err,
6568 SupervisorError::ChildCaixaInvalid { ref caixa, ref reason }
6569 if caixa == "-worker" && reason.contains("start and end")
6570 ),
6571 "got {err:?}"
6572 );
6573 }
6574
6575 #[test]
6576 fn validate_rejects_child_caixa_with_trailing_hyphen() {
6577 // The symmetric arm of the boundary rule. Pin separately so
6578 // both ends of the label are covered against a future relaxation
6579 // that only checks one boundary.
6580 let s = SupervisorSpec {
6581 children: vec![child("worker-", "^0.1", RestartPolicy::Permanent)],
6582 ..SupervisorSpec::default()
6583 };
6584 let err = s.validate().unwrap_err();
6585 assert!(
6586 matches!(
6587 err,
6588 SupervisorError::ChildCaixaInvalid { ref caixa, .. }
6589 if caixa == "worker-"
6590 ),
6591 "got {err:?}"
6592 );
6593 }
6594
6595 #[test]
6596 fn validate_rejects_child_caixa_with_unicode() {
6597 // DNS-1123 is ASCII-only; IDN must be pre-encoded as Punycode
6598 // (`xn--…`) by the author before it reaches K8s. The byte-by-
6599 // byte ASCII validity check rejects multi-byte UTF-8 sequences
6600 // by the first byte that fails the `[a-z0-9-]` predicate.
6601 let s = SupervisorSpec {
6602 children: vec![child("café", "^0.1", RestartPolicy::Permanent)],
6603 ..SupervisorSpec::default()
6604 };
6605 let err = s.validate().unwrap_err();
6606 assert!(
6607 matches!(
6608 err,
6609 SupervisorError::ChildCaixaInvalid { ref caixa, .. }
6610 if caixa == "café"
6611 ),
6612 "got {err:?}"
6613 );
6614 }
6615
6616 #[test]
6617 fn validate_rejects_child_caixa_with_whitespace() {
6618 // Whitespace is the canonical "I pasted from a sketch / doc"
6619 // footgun. The apiserver rejects every `metadata.name` value
6620 // carrying whitespace; pin the gate fires at the right boundary.
6621 let s = SupervisorSpec {
6622 children: vec![child("my worker", "^0.1", RestartPolicy::Permanent)],
6623 ..SupervisorSpec::default()
6624 };
6625 let err = s.validate().unwrap_err();
6626 assert!(
6627 matches!(
6628 err,
6629 SupervisorError::ChildCaixaInvalid { ref caixa, .. }
6630 if caixa == "my worker"
6631 ),
6632 "got {err:?}"
6633 );
6634 }
6635
6636 #[test]
6637 fn validate_rejects_child_caixa_too_long() {
6638 // The 64-byte boundary pin. DNS-1123 / DNS-1035 cap labels at
6639 // 63 bytes; the K8s apiserver rejects every `metadata.name`
6640 // axis over the limit at admission time. The diagnostic names
6641 // both the cap and the actual length so the author can shorten
6642 // in one edit, mirroring `rejects_membro_caixa_too_long`
6643 // (3f9d7a0) and `rejects_placement_cluster_too_long` (6cbb900).
6644 let too_long = "a".repeat(64);
6645 let s = SupervisorSpec {
6646 children: vec![child(&too_long, "^0.1", RestartPolicy::Permanent)],
6647 ..SupervisorSpec::default()
6648 };
6649 let err = s.validate().unwrap_err();
6650 let SupervisorError::ChildCaixaInvalid { caixa, reason } = err else {
6651 panic!("expected ChildCaixaInvalid, got other variant");
6652 };
6653 assert_eq!(caixa, too_long);
6654 assert!(
6655 reason.contains("63"),
6656 "diagnostic must name the 63-byte cap (got: {reason:?})"
6657 );
6658 assert!(
6659 reason.contains("64"),
6660 "diagnostic must name the actual length (got: {reason:?})"
6661 );
6662 }
6663
6664 #[test]
6665 fn child_caixa_max_length_validates() {
6666 // The 63-byte boundary control pin — exactly-at-the-cap is
6667 // accepted, mirroring `membro_caixa_max_length_validates`
6668 // (3f9d7a0) and `placement_cluster_max_length_validates`
6669 // (6cbb900). Pinned separately so a future off-by-one tightening
6670 // surfaces here.
6671 let max_label = "a".repeat(63);
6672 let s = SupervisorSpec {
6673 children: vec![child(&max_label, "^0.1", RestartPolicy::Permanent)],
6674 ..SupervisorSpec::default()
6675 };
6676 s.validate().unwrap();
6677 }
6678
6679 #[test]
6680 fn validate_accepts_canonical_child_caixa_forms() {
6681 // The realistic shapes a supervised child's `:caixa` carries —
6682 // single-word `worker`, version-suffixed `cache-v2`, single-char
6683 // `a`, two-char `db`, digit-start `2-pool`, longer hyphen-joined
6684 // `payment-retry`, all-digit `0`. Pin every leg so a future
6685 // tightening (e.g. requiring a leading lowercase letter) surfaces
6686 // here as a test failure. Mirrors `accepts_canonical_membro_caixa_forms`
6687 // (3f9d7a0) and `accepts_canonical_placement_cluster_forms`
6688 // (6cbb900).
6689 for form in [
6690 "worker",
6691 "cache-v2",
6692 "a",
6693 "db",
6694 "2-pool",
6695 "payment-retry",
6696 "0",
6697 ] {
6698 let s = SupervisorSpec {
6699 children: vec![child(form, "^0.1", RestartPolicy::Permanent)],
6700 ..SupervisorSpec::default()
6701 };
6702 s.validate()
6703 .unwrap_or_else(|e| panic!("canonical form {form:?} must validate, got {e:?}"));
6704 }
6705 }
6706
6707 #[test]
6708 fn child_caixa_empty_takes_precedence_over_invalid() {
6709 // Order pin: the existing `EmptyChildName` diagnostic (which
6710 // doesn't try to parse the DNS-1123 shape) fires before the new
6711 // `ChildCaixaInvalid` per-axis gate, so an empty `:caixa` keeps
6712 // its narrower error message — `is_dns_1123_label` would reject
6713 // the empty string too (boundary check on the first byte), but
6714 // the empty-string arm is the more self-locating diagnostic for
6715 // the author. Same ordering discipline as
6716 // `membro_caixa_empty_takes_precedence_over_invalid` in
6717 // aplicacao.rs.
6718 let s = SupervisorSpec {
6719 children: vec![child("", "^0.1", RestartPolicy::Permanent)],
6720 ..SupervisorSpec::default()
6721 };
6722 let err = s.validate().unwrap_err();
6723 assert_eq!(err, SupervisorError::EmptyChildName);
6724 }
6725
6726 #[test]
6727 fn child_caixa_invalid_fires_before_versao_check() {
6728 // Order pin: the per-axis shape gate runs inline before the
6729 // per-entry versao check, so a malformed `:caixa` on an entry
6730 // whose `:versao` would also fail surfaces the more self-
6731 // locating name-axis diagnostic first. Parallel to
6732 // `membro_versao_invalid_fires_before_duplicate_check` (9888b13)
6733 // and `placement_cluster_invalid_fires_before_duplicate_check`
6734 // (6cbb900).
6735 let s = SupervisorSpec {
6736 children: vec![child("My_Worker", "", RestartPolicy::Permanent)],
6737 ..SupervisorSpec::default()
6738 };
6739 let err = s.validate().unwrap_err();
6740 assert!(
6741 matches!(
6742 err,
6743 SupervisorError::ChildCaixaInvalid { ref caixa, .. } if caixa == "My_Worker"
6744 ),
6745 "got {err:?}"
6746 );
6747 }
6748
6749 #[test]
6750 fn child_caixa_invalid_fires_before_duplicate_check() {
6751 // Order pin: a malformed name on a non-duplicate entry surfaces
6752 // its own diagnostic, even when a later entry would otherwise
6753 // collapse onto an earlier name. The per-entry shape gate runs
6754 // inline before the duplicate-key HashSet insert, mirroring
6755 // `placement_cluster_invalid_fires_before_duplicate_check`
6756 // (6cbb900).
6757 let s = SupervisorSpec {
6758 children: vec![
6759 child("Worker", "^0.1", RestartPolicy::Permanent),
6760 child("cache", "^0.1", RestartPolicy::Transient),
6761 child("worker", "^0.2", RestartPolicy::Permanent), // would otherwise raise DuplicateChildCaixa
6762 ],
6763 ..SupervisorSpec::default()
6764 };
6765 let err = s.validate().unwrap_err();
6766 assert!(
6767 matches!(
6768 err,
6769 SupervisorError::ChildCaixaInvalid { ref caixa, .. } if caixa == "Worker"
6770 ),
6771 "got {err:?}"
6772 );
6773 }
6774
6775 #[test]
6776 fn child_caixa_invalid_diagnostic_carries_offending_caixa() {
6777 // The diagnostic-shape pin: the error names the offending
6778 // `:caixa` verbatim plus a non-empty parser-shaped `reason` so
6779 // the author can grep their caixa.lisp without re-running the
6780 // build. Mirrors the diagnostic-shape sweep on every prior
6781 // value-shape gate (3f9d7a0, 6cbb900, c7d05ec).
6782 let s = SupervisorSpec {
6783 children: vec![child("My_Worker", "^0.1", RestartPolicy::Permanent)],
6784 ..SupervisorSpec::default()
6785 };
6786 let err = s.validate().unwrap_err();
6787 let SupervisorError::ChildCaixaInvalid { caixa, reason } = err else {
6788 panic!("expected ChildCaixaInvalid, got other variant");
6789 };
6790 assert_eq!(caixa, "My_Worker");
6791 assert!(
6792 !reason.is_empty(),
6793 "ChildCaixaInvalid `reason` must carry the parser's wording verbatim"
6794 );
6795 }
6796
6797 // ── value-shape: zero restart_window + duplicate child names ──────────
6798
6799 #[test]
6800 fn validate_accepts_none_restart_window() {
6801 // Omitted `:restart-window` is the "never reset" sentinel —
6802 // valid by design. Mirrors :limits axes where None = unbounded.
6803 let s = SupervisorSpec {
6804 restart_window: None,
6805 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6806 ..SupervisorSpec::default()
6807 };
6808 s.validate().unwrap();
6809 }
6810
6811 #[test]
6812 fn validate_rejects_zero_restart_window() {
6813 // Same "0 means the opposite of what you think" footgun closed
6814 // for :politicas :timeout (Envoy treats 0s as infinite) and
6815 // :limits :wall-clock (wasmtime traps before the call starts).
6816 // Erlang/OTP's MaxIntensity/Period requires Period > 0.
6817 let s = SupervisorSpec {
6818 restart_window: Some(Duration::ZERO),
6819 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6820 ..SupervisorSpec::default()
6821 };
6822 assert_eq!(
6823 s.validate().unwrap_err(),
6824 SupervisorError::RestartWindowZero
6825 );
6826 }
6827
6828 // ── value-shape: integer-ms canonical-form on :restart-window ─────────
6829 //
6830 // The fourth (and last) typed-`Duration` axis in caixa-core to get
6831 // the integer-millisecond canonical-form gate — peer with
6832 // `:limits :wall-clock` (82fc3ef), `:politicas :timeout` (a4ae535),
6833 // and `:politicas :circuit-breaker :window` (a4ae535). The serde
6834 // path is already gated at the shared codec layer (see
6835 // `restart_window_serde_rejects_fractional_seconds`); this arm
6836 // closes the programmatic-struct-literal path the codec gate can't
6837 // see.
6838
6839 #[test]
6840 fn validate_rejects_sub_millisecond_restart_window() {
6841 // The fail-before-pass-after pin: a programmatic
6842 // `Duration::from_micros(1500)` (= 1_500_000 ns) silently passed
6843 // `validate` on every pre-gate codebase, then truncated to
6844 // `as_millis() == 1` on first serialize — the shared codec
6845 // emits `"1ms"`, parses it back to `Duration::from_millis(1)` =
6846 // 1_000_000 ns, the typed `restart_window` no longer matches
6847 // its rendered form.
6848 let s = SupervisorSpec {
6849 restart_window: Some(Duration::from_micros(1500)),
6850 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6851 ..SupervisorSpec::default()
6852 };
6853 match s.validate().unwrap_err() {
6854 SupervisorError::RestartWindowNotCanonical { window } => {
6855 assert_eq!(window, Duration::from_micros(1500));
6856 }
6857 other => panic!("expected RestartWindowNotCanonical, got {other:?}"),
6858 }
6859 }
6860
6861 #[test]
6862 fn validate_rejects_one_nanosecond_restart_window() {
6863 // The far-sub-ms case: `Duration::from_nanos(1)` is non-zero
6864 // (so `RestartWindowZero` doesn't fire) but `as_millis() == 0`,
6865 // so the shared codec emits the literal `"0s"` — the next
6866 // serde round-trip would parse back to `Duration::ZERO`, which
6867 // the `RestartWindowZero` arm then rejects on re-validate. The
6868 // canonical-form gate at this layer surfaces a self-locating
6869 // diagnostic naming the offending Duration verbatim rather
6870 // than a downstream `RestartWindowZero` whose remediation
6871 // points at omitting the slot.
6872 let s = SupervisorSpec {
6873 restart_window: Some(Duration::from_nanos(1)),
6874 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6875 ..SupervisorSpec::default()
6876 };
6877 match s.validate().unwrap_err() {
6878 SupervisorError::RestartWindowNotCanonical { window } => {
6879 assert_eq!(window, Duration::from_nanos(1));
6880 }
6881 other => panic!("expected RestartWindowNotCanonical, got {other:?}"),
6882 }
6883 }
6884
6885 #[test]
6886 fn validate_rejects_nanosecond_past_canonical_boundary_restart_window() {
6887 // The 1-ns-past-1ms boundary case: a `Duration` carrying
6888 // 1_000_001 ns is structurally past the integer-ms granularity
6889 // floor — `subsec_nanos() % 1_000_000 == 1`. The codec round-
6890 // trip would truncate to `1ms` and the consumer would observe
6891 // a 1-ns drift on every emit. Same boundary the peer
6892 // `validate_rejects_nanosecond_past_canonical_boundary` test
6893 // in limits.rs pins for the `:limits :wall-clock` axis.
6894 let w = Duration::from_nanos(1_000_001);
6895 let s = SupervisorSpec {
6896 restart_window: Some(w),
6897 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6898 ..SupervisorSpec::default()
6899 };
6900 assert_eq!(
6901 s.validate().unwrap_err(),
6902 SupervisorError::RestartWindowNotCanonical { window: w }
6903 );
6904 }
6905
6906 #[test]
6907 fn validate_accepts_integer_millisecond_restart_window_values() {
6908 // The positive-control sweep: every `Duration` the shared
6909 // codec can round-trip losslessly — the canonical
6910 // `<integer>{ms,s,m,h}` set the codec's `render` / `parse`
6911 // pair emits and accepts — passes `validate` without
6912 // surfacing the new canonical-form arm. Mirrors
6913 // `validate_accepts_integer_millisecond_wall_clock_values` on
6914 // the sibling `:limits :wall-clock` axis.
6915 for w in [
6916 Duration::from_millis(1),
6917 Duration::from_millis(500),
6918 Duration::from_millis(1500),
6919 Duration::from_secs(1),
6920 Duration::from_secs(30),
6921 Duration::from_secs(60),
6922 Duration::from_secs(120),
6923 Duration::from_secs(3600),
6924 ] {
6925 let s = SupervisorSpec {
6926 restart_window: Some(w),
6927 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6928 ..SupervisorSpec::default()
6929 };
6930 s.validate()
6931 .unwrap_or_else(|e| panic!("integer-ms {w:?} must validate, got {e:?}"));
6932 }
6933 }
6934
6935 #[test]
6936 fn validate_restart_window_zero_takes_precedence_over_canonical_gate() {
6937 // Cross-arm ordering pin: `Duration::ZERO` has
6938 // `subsec_nanos() == 0` and would otherwise pass the
6939 // canonical-form arm — the zero-floor arm must fire first so
6940 // the more self-locating `RestartWindowZero` diagnostic (with
6941 // its omit-axis remediation directly named) leads. Same
6942 // posture every peer zero-then-shape gate uses
6943 // (`WallClockZero` → `WallClockNotCanonical`,
6944 // `PolicyTimeoutZero` → `PolicyTimeoutNotCanonical`,
6945 // `PolicyBreakerZeroWindow` → `PolicyBreakerWindowNotCanonical`).
6946 let s = SupervisorSpec {
6947 restart_window: Some(Duration::ZERO),
6948 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6949 ..SupervisorSpec::default()
6950 };
6951 assert_eq!(
6952 s.validate().unwrap_err(),
6953 SupervisorError::RestartWindowZero
6954 );
6955 }
6956
6957 #[test]
6958 fn restart_window_canonical_diagnostic_carries_offending_duration() {
6959 // Diagnostic-shape pin: the canonical-form arm names the
6960 // offending `Duration` verbatim so the author's grep lands on
6961 // the field's value, not a generic "duration not canonical"
6962 // message. Same shape every other typed-canonical-form arm
6963 // on this surface carries (`WallClockNotCanonical` carries
6964 // the offending `Duration` verbatim,
6965 // `PolicyTimeoutNotCanonical` carries the offending
6966 // `Duration` verbatim).
6967 let w = Duration::from_micros(500);
6968 let s = SupervisorSpec {
6969 restart_window: Some(w),
6970 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
6971 ..SupervisorSpec::default()
6972 };
6973 let err = s.validate().unwrap_err();
6974 let msg = err.to_string();
6975 assert!(
6976 msg.contains("500"),
6977 "diagnostic must carry the offending magnitude verbatim (got {msg:?})"
6978 );
6979 assert!(
6980 msg.contains("sub-millisecond"),
6981 "diagnostic must name the sub-millisecond residue class (got {msg:?})"
6982 );
6983 }
6984
6985 #[test]
6986 fn restart_window_validated_value_round_trips_through_codec() {
6987 // The structural property the canonical-ms gate enforces:
6988 // every `SupervisorSpec::restart_window` past
6989 // `SupervisorSpec::validate` round-trips losslessly through
6990 // the shared duration codec (serialize → string →
6991 // deserialize → equal value). Pin this end-to-end so a future
6992 // change to either side (the validate gate's accepted
6993 // granularity, the codec's parse/render unit set) that breaks
6994 // the alignment surfaces here. Peer of
6995 // `wall_clock_validated_value_round_trips_through_codec` on
6996 // the sibling `:limits :wall-clock` axis.
6997 for w in [
6998 Duration::from_millis(1),
6999 Duration::from_millis(1500),
7000 Duration::from_secs(30),
7001 Duration::from_secs(3600),
7002 ] {
7003 let s = SupervisorSpec {
7004 restart_window: Some(w),
7005 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7006 ..SupervisorSpec::default()
7007 };
7008 s.validate().unwrap();
7009 let json = serde_json::to_string(&s).unwrap();
7010 let back: SupervisorSpec = serde_json::from_str(&json).unwrap();
7011 assert_eq!(back.restart_window, Some(w));
7012 }
7013 }
7014
7015 // ── value-shape: upper cap on :restart-window ─────────────────────────
7016 //
7017 // The fourth (and last) typed-`Duration` axis in caixa-core to get
7018 // the 1h upper cap — peer with `:limits :wall-clock` (51e0dbd),
7019 // `:politicas :timeout` (2e8ee7e), and `:politicas
7020 // :circuit-breaker :window` (379a814). Brackets the typed
7021 // `:restart-window` axis structurally: every validated value lies
7022 // in `1ms..=SUPERVISOR_RESTART_WINDOW_MAX`, integer-millisecond
7023 // granularity, closing the
7024 // rolling-window-degenerates-to-lifetime-counter footgun the prior
7025 // zero-floor-and-canonical-form-only checks left open.
7026
7027 #[test]
7028 fn validate_rejects_restart_window_above_cap() {
7029 // The fail-before-pass-after pin: 3601s = 1h + 1s is
7030 // structurally one canonical-tick past the
7031 // [`SUPERVISOR_RESTART_WINDOW_MAX`] ceiling (1h = 3600s) — an
7032 // integer-millisecond magnitude the canonical-form arm above
7033 // accepts cleanly, that the shared duration codec round-trips
7034 // losslessly as `"3601s"`, and that silently passed validate on
7035 // every pre-gate codebase because the typed slot's only checks
7036 // were the zero-floor and canonical-form arms. The runtime
7037 // substrate consuming the value (Erlang/OTP's MaxIntensity/
7038 // Period reconciler, the future wasm-operator's per-supervisor
7039 // restart-intensity counter) reaches for a `Duration` so long
7040 // no realistic restart-recovery pattern resets the counter,
7041 // far from the source caixa.lisp.
7042 let w = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_secs(1);
7043 let s = SupervisorSpec {
7044 restart_window: Some(w),
7045 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7046 ..SupervisorSpec::default()
7047 };
7048 assert_eq!(
7049 s.validate().unwrap_err(),
7050 SupervisorError::RestartWindowExceedsCap { window: w }
7051 );
7052 }
7053
7054 #[test]
7055 fn validate_rejects_restart_window_one_millisecond_above_cap() {
7056 // Boundary case: exactly 1ms past the cap (the granularity the
7057 // canonical-form gate enforces). Catches a future "strictly
7058 // less than" half-measure and pins the diagnostic to name the
7059 // offending `Duration` verbatim. Peer of
7060 // `validate_rejects_wall_clock_one_millisecond_above_cap` /
7061 // `rejects_policy_timeout_one_millisecond_above_cap` /
7062 // `rejects_circuit_breaker_window_one_millisecond_above_cap`
7063 // on the sibling typed-`Duration` axes' top edges.
7064 let w = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_millis(1);
7065 let s = SupervisorSpec {
7066 restart_window: Some(w),
7067 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7068 ..SupervisorSpec::default()
7069 };
7070 assert_eq!(
7071 s.validate().unwrap_err(),
7072 SupervisorError::RestartWindowExceedsCap { window: w }
7073 );
7074 }
7075
7076 #[test]
7077 fn validate_rejects_restart_window_far_above_cap() {
7078 // The "obvious authoring footgun" case: a `(:restart-window "24h")`,
7079 // `(:restart-window "7d")`, or any "I want a lifetime counter
7080 // but wrote a `<integer>h` magnitude anyway" typo — values the
7081 // canonical-form arm accepts as integer-millisecond magnitudes,
7082 // the codec round-trips losslessly through serde, but the
7083 // operator's `MaxIntensity / Period` reconciler cannot honor
7084 // as a meaningful rolling window. Until this gate landed
7085 // validate accepted them. Pin the common above-cap values (24h,
7086 // 7d, ~11.5d) so a future relaxation that drops the upper bound
7087 // surfaces here.
7088 for w in [
7089 Duration::from_secs(86_400), // 24h
7090 Duration::from_secs(604_800), // 7d
7091 Duration::from_secs(1_000_000), // ~11.5 days
7092 ] {
7093 let s = SupervisorSpec {
7094 restart_window: Some(w),
7095 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7096 ..SupervisorSpec::default()
7097 };
7098 assert_eq!(
7099 s.validate().unwrap_err(),
7100 SupervisorError::RestartWindowExceedsCap { window: w }
7101 );
7102 }
7103 }
7104
7105 #[test]
7106 fn validate_accepts_restart_window_at_cap() {
7107 // The boundary value — exactly [`SUPERVISOR_RESTART_WINDOW_MAX`]
7108 // (1h) — must validate. The cap is inclusive on the top edge,
7109 // matching the [`crate::LIMITS_WALL_CLOCK_MAX`] /
7110 // [`crate::POLICY_TIMEOUT_MAX`] /
7111 // [`crate::POLICY_BREAKER_WINDOW_MAX`] discipline on the sibling
7112 // capped axes. Pin the boundary explicitly so a future
7113 // off-by-one tightening (`>= SUPERVISOR_RESTART_WINDOW_MAX`
7114 // instead of `>`) surfaces here as a test failure rather than a
7115 // silent contract narrowing.
7116 let s = SupervisorSpec {
7117 restart_window: Some(SUPERVISOR_RESTART_WINDOW_MAX),
7118 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7119 ..SupervisorSpec::default()
7120 };
7121 s.validate()
7122 .expect("restart_window == SUPERVISOR_RESTART_WINDOW_MAX must validate");
7123 }
7124
7125 #[test]
7126 fn validate_accepts_restart_window_typical_values() {
7127 // The documented Erlang/OTP / Elixir / Riak Core / RabbitMQ
7128 // per-supervisor production-playbook band positive-control
7129 // sweep — every value Learn You Some Erlang's `{intensity, 5,
7130 // 60}` worker-supervisor `Period = 60s` default, Elixir's
7131 // `Supervisor` `max_seconds: 5` default, OTP's `supervisor`
7132 // callback module `MaxT = 5..=60` typical, Riak Core's `MaxT ∈
7133 // 10s..=300s`, and RabbitMQ broker-supervisor `MaxT = 5s`
7134 // default recommend (5s..=300s) must pass, plus a sweep
7135 // through the long-tail-flaky-pool band (5m, 15m, 30m, 1h) the
7136 // cap accepts. Mirrors `validate_accepts_wall_clock_typical_values`
7137 // on the sibling `:limits :wall-clock` axis.
7138 for w in [
7139 Duration::from_millis(1),
7140 Duration::from_millis(500),
7141 Duration::from_secs(1),
7142 Duration::from_secs(5), // RabbitMQ broker-supervisor default
7143 Duration::from_secs(10), // Riak Core lower
7144 Duration::from_secs(30),
7145 Duration::from_secs(60), // Learn You Some Erlang default
7146 Duration::from_secs(120), // OTP supervisor MaxT typical
7147 Duration::from_secs(300), // Riak Core upper
7148 Duration::from_secs(900), // 15m
7149 Duration::from_secs(1800),
7150 Duration::from_secs(3600), // exactly 1h, the cap
7151 ] {
7152 let s = SupervisorSpec {
7153 restart_window: Some(w),
7154 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7155 ..SupervisorSpec::default()
7156 };
7157 s.validate()
7158 .unwrap_or_else(|e| panic!("restart_window={w:?} must validate; got {e:?}"));
7159 }
7160 }
7161
7162 #[test]
7163 fn restart_window_zero_takes_precedence_over_cap() {
7164 // The cross-arm ordering pin: `Duration::ZERO` is structurally
7165 // outside both `>= 1ms` (zero-floor) and `<=
7166 // SUPERVISOR_RESTART_WINDOW_MAX` (cap), but the zero-floor
7167 // diagnostic is the more self-locating one (it directly names
7168 // the omit-axis remediation), so the validate gate must fire
7169 // on zero first. Same shape every other zero-then-cap ordering
7170 // on this surface uses (`WallClockZero` then
7171 // `WallClockExceedsCap`, `PolicyTimeoutZero` then
7172 // `PolicyTimeoutExceedsCap`, `PolicyBreakerZeroWindow` then
7173 // `PolicyBreakerWindowExceedsCap`).
7174 let s = SupervisorSpec {
7175 restart_window: Some(Duration::ZERO),
7176 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7177 ..SupervisorSpec::default()
7178 };
7179 assert_eq!(
7180 s.validate().unwrap_err(),
7181 SupervisorError::RestartWindowZero,
7182 "Duration::ZERO must surface the zero-floor diagnostic, not the cap diagnostic"
7183 );
7184 }
7185
7186 #[test]
7187 fn restart_window_canonical_takes_precedence_over_cap() {
7188 // The cross-arm ordering pin: a `Duration` that is *both*
7189 // sub-millisecond (non-canonical-form) and structurally above
7190 // the cap surfaces the canonical-form diagnostic first,
7191 // because the round-trip-shape break is the more fundamental
7192 // issue (the value can't even round-trip through the codec,
7193 // so the cap diagnostic naming `1ms..=1h` would be misleading
7194 // — there's no integer-ms form of the offending value). Pin
7195 // the order so a future refactor that reorders the arms
7196 // surfaces here as a test failure rather than a silent
7197 // diagnostic regression. Peer of
7198 // `wall_clock_canonical_takes_precedence_over_cap` /
7199 // `policy_timeout_canonical_takes_precedence_over_cap`.
7200 let w = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_nanos(1);
7201 let s = SupervisorSpec {
7202 restart_window: Some(w),
7203 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7204 ..SupervisorSpec::default()
7205 };
7206 assert_eq!(
7207 s.validate().unwrap_err(),
7208 SupervisorError::RestartWindowNotCanonical { window: w },
7209 "sub-ms above-cap value must surface the canonical-form diagnostic, not the cap diagnostic"
7210 );
7211 }
7212
7213 #[test]
7214 fn max_restarts_cap_takes_precedence_over_restart_window_cap() {
7215 // The cross-arm ordering pin between the `:max-restarts` cap
7216 // and the sibling `:restart-window` cap. A supervisor carrying
7217 // both an over-cap `max_restarts` AND an over-cap window must
7218 // surface the `MaxRestartsExceedsCap` diagnostic first — the
7219 // cap arm is wired immediately after the zero-restart arm and
7220 // strictly before every window-axis arm (zero / canonical /
7221 // cap), so the offending value the diagnostic names matches
7222 // the order the author would discover the gates by reading
7223 // top-to-bottom through `SupervisorSpec::validate`. Pin the
7224 // order so a future refactor that reorders the arms surfaces
7225 // here as a test failure rather than a silent diagnostic
7226 // regression. Peer of
7227 // `max_restarts_cap_takes_precedence_over_restart_window_gates`
7228 // on the sibling zero / canonical window arms.
7229 let w = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_secs(1);
7230 let s = SupervisorSpec {
7231 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
7232 restart_window: Some(w),
7233 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7234 ..SupervisorSpec::default()
7235 };
7236 assert_eq!(
7237 s.validate().unwrap_err(),
7238 SupervisorError::MaxRestartsExceedsCap {
7239 max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
7240 },
7241 "over-cap max_restarts must surface the cap diagnostic before any window-axis diagnostic"
7242 );
7243 }
7244
7245 #[test]
7246 fn restart_window_cap_diagnostic_carries_offending_value() {
7247 // The diagnostic-shape pin: the offending `Duration` is
7248 // carried verbatim into the
7249 // [`SupervisorError::RestartWindowExceedsCap`] variant so the
7250 // surfaced error message names the value the author wrote,
7251 // not just the cap. Same self-locating diagnostic shape every
7252 // other typed-cap arm on this surface carries
7253 // (`WallClockExceedsCap` carries the offending `Duration`
7254 // verbatim, `PolicyTimeoutExceedsCap` carries the offending
7255 // `Duration` verbatim, `PolicyBreakerWindowExceedsCap` carries
7256 // the offending `Duration` verbatim).
7257 let w = Duration::from_secs(7200); // 2h
7258 let s = SupervisorSpec {
7259 restart_window: Some(w),
7260 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7261 ..SupervisorSpec::default()
7262 };
7263 let err = s.validate().unwrap_err();
7264 assert!(
7265 matches!(err, SupervisorError::RestartWindowExceedsCap { window } if window == w),
7266 "got {err:?}"
7267 );
7268 let msg = err.to_string();
7269 assert!(
7270 msg.contains("7200"),
7271 ":supervisor :restart-window cap diagnostic must carry the offending value verbatim (got: {msg})"
7272 );
7273 }
7274
7275 #[test]
7276 fn supervisor_restart_window_cap_pins_canonical_value() {
7277 // The SUPERVISOR_RESTART_WINDOW_MAX constant pins the value at
7278 // exactly 1 hour (3600s = 3_600_000ms) — the largest unit the
7279 // shared duration codec emits as a clean canonical string
7280 // (`"<n>h"`). Pinning the literal value here surfaces a future
7281 // drift (a relaxation to 24h, a tightening to 5m) as a
7282 // deliberate test edit, not a silent contract narrowing.
7283 //
7284 // The four typed-`Duration` caps on the validation surface
7285 // (`LIMITS_WALL_CLOCK_MAX` per-process, `POLICY_TIMEOUT_MAX`
7286 // per-edge, `POLICY_BREAKER_WINDOW_MAX` per-breaker,
7287 // `SUPERVISOR_RESTART_WINDOW_MAX` per-supervisor) share a
7288 // single uniform top edge at the codec's largest emitted unit
7289 // — a structural-property invariant the equality assertions
7290 // here enshrine, so a future drift on any of the four
7291 // surfaces as a deliberate test edit. Same shape every other
7292 // typed-cap value pin uses
7293 // (`wall_clock_cap_pins_canonical_value`,
7294 // `policy_timeout_cap_pins_canonical_value`,
7295 // `circuit_breaker_window_cap_pins_canonical_value`).
7296 assert_eq!(SUPERVISOR_RESTART_WINDOW_MAX, Duration::from_secs(3600));
7297 assert_eq!(SUPERVISOR_RESTART_WINDOW_MAX.as_millis(), 3_600_000);
7298 assert_eq!(SUPERVISOR_RESTART_WINDOW_MAX, crate::LIMITS_WALL_CLOCK_MAX);
7299 assert_eq!(SUPERVISOR_RESTART_WINDOW_MAX, crate::POLICY_TIMEOUT_MAX);
7300 assert_eq!(
7301 SUPERVISOR_RESTART_WINDOW_MAX,
7302 crate::POLICY_BREAKER_WINDOW_MAX
7303 );
7304 }
7305
7306 #[test]
7307 fn restart_window_cap_value_round_trips_through_codec() {
7308 // The codec round-trip property the cap arm preserves: the
7309 // [`SUPERVISOR_RESTART_WINDOW_MAX`] constant itself round-trips
7310 // through the shared duration codec — every value at the cap
7311 // serializes to the canonical `"1h"` form and parses back
7312 // identically. Pin the round-trip so a future change to the
7313 // codec's unit set or to the cap's magnitude that breaks the
7314 // round-trip property surfaces here. Peer of
7315 // `wall_clock_cap_value_round_trips_through_codec` on the
7316 // sibling `:limits :wall-clock` axis.
7317 let s = SupervisorSpec {
7318 restart_window: Some(SUPERVISOR_RESTART_WINDOW_MAX),
7319 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7320 ..SupervisorSpec::default()
7321 };
7322 s.validate().unwrap();
7323 let json = serde_json::to_string(&s).unwrap();
7324 assert!(
7325 json.contains("\"1h\""),
7326 "SUPERVISOR_RESTART_WINDOW_MAX must serialize to the canonical `\"1h\"` form (got {json})"
7327 );
7328 let back: SupervisorSpec = serde_json::from_str(&json).unwrap();
7329 assert_eq!(back.restart_window, Some(SUPERVISOR_RESTART_WINDOW_MAX));
7330 }
7331
7332 #[test]
7333 fn validate_rejects_duplicate_child_caixa() {
7334 // Two children with the same :caixa render to two ComputeUnits
7335 // with the same name in the cluster's HelmRelease values —
7336 // one silently overwrites the other. Erlang/OTP's child_spec.id
7337 // is required-unique per supervisor; same set-not-multiset
7338 // discipline applied here as for :membros / :placement
7339 // :clusters / :entrada :paths.
7340 let s = SupervisorSpec {
7341 children: vec![
7342 child("worker", "^0.1", RestartPolicy::Permanent),
7343 child("cache", "^0.1", RestartPolicy::Transient),
7344 child("worker", "^0.2", RestartPolicy::Permanent),
7345 ],
7346 ..SupervisorSpec::default()
7347 };
7348 let err = s.validate().unwrap_err();
7349 assert!(
7350 matches!(err, SupervisorError::DuplicateChildCaixa { ref caixa } if caixa == "worker"),
7351 "got {err:?}"
7352 );
7353 }
7354
7355 #[test]
7356 fn validate_duplicate_child_diagnostic_names_first_collision() {
7357 // Iteration walks the :children list in declaration order —
7358 // the diagnostic names the first repeat, deterministically,
7359 // even when multiple names duplicate.
7360 let s = SupervisorSpec {
7361 children: vec![
7362 child("a", "^0.1", RestartPolicy::Permanent),
7363 child("b", "^0.1", RestartPolicy::Permanent),
7364 child("a", "^0.1", RestartPolicy::Permanent),
7365 child("b", "^0.1", RestartPolicy::Permanent),
7366 ],
7367 ..SupervisorSpec::default()
7368 };
7369 let err = s.validate().unwrap_err();
7370 assert!(
7371 matches!(err, SupervisorError::DuplicateChildCaixa { ref caixa } if caixa == "a"),
7372 "got {err:?}"
7373 );
7374 }
7375
7376 // ── self-supervision cross-slot gate ──────────────────────────
7377
7378 #[test]
7379 fn validate_no_self_supervision_rejects_self_referential_child() {
7380 // A supervisor whose `:children` lists its own `:nome` is a
7381 // one-node reconciliation cycle — rejected, naming the parent.
7382 let children = vec![
7383 child("worker", "^0.1", RestartPolicy::Permanent),
7384 child("orquestra", "^0.1", RestartPolicy::Permanent),
7385 ];
7386 let err = validate_no_self_supervision(&children, "orquestra").unwrap_err();
7387 assert!(
7388 matches!(err, SupervisorError::ChildSupervisesSelf { ref caixa } if caixa == "orquestra"),
7389 "got {err:?}"
7390 );
7391 }
7392
7393 #[test]
7394 fn validate_no_self_supervision_accepts_distinct_children() {
7395 // Positive control: distinct child names (including a child that
7396 // is itself a supervisor — nested trees are valid OTP) pass.
7397 let children = vec![
7398 child("worker", "^0.1", RestartPolicy::Permanent),
7399 child("sub-tree", "^0.1", RestartPolicy::Permanent),
7400 ];
7401 validate_no_self_supervision(&children, "orquestra").unwrap();
7402 }
7403
7404 #[test]
7405 fn validate_no_self_supervision_empty_children_is_ok() {
7406 // SimpleOneForOne / no-static-children supervisors have nothing
7407 // to self-reference — the gate is vacuously satisfied.
7408 validate_no_self_supervision(&[], "orquestra").unwrap();
7409 }
7410
7411 #[test]
7412 fn validate_simple_one_for_one_skips_uniqueness_check() {
7413 // SimpleOneForOne supervisors carry no static children — the
7414 // duplicate-child loop never runs. A zero-window declaration
7415 // on a SimpleOneForOne supervisor still trips the window check
7416 // (window applies to dynamic children too).
7417 let s = SupervisorSpec {
7418 estrategia: RestartStrategy::SimpleOneForOne,
7419 restart_window: None,
7420 children: vec![],
7421 ..SupervisorSpec::default()
7422 };
7423 s.validate().unwrap();
7424 let s_zero = SupervisorSpec {
7425 estrategia: RestartStrategy::SimpleOneForOne,
7426 restart_window: Some(Duration::ZERO),
7427 children: vec![],
7428 ..SupervisorSpec::default()
7429 };
7430 assert_eq!(
7431 s_zero.validate().unwrap_err(),
7432 SupervisorError::RestartWindowZero
7433 );
7434 }
7435
7436 #[test]
7437 fn validate_zero_window_runs_after_max_restarts_check() {
7438 // Pin the order: max_restarts == 0 fires before
7439 // restart_window == 0s, so an author with both wrong sees the
7440 // counter-axis diagnostic first (matches the order in the
7441 // struct and in the doc comment).
7442 let s = SupervisorSpec {
7443 max_restarts: 0,
7444 restart_window: Some(Duration::ZERO),
7445 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7446 ..SupervisorSpec::default()
7447 };
7448 assert_eq!(s.validate().unwrap_err(), SupervisorError::ZeroMaxRestarts);
7449 }
7450
7451 #[test]
7452 fn round_trip_all_strategies() {
7453 for &strat in RestartStrategy::ALL {
7454 // Route the `SimpleOneForOne ↔ non-SimpleOneForOne` fixture-
7455 // shape partition through the [`gen_platform::IsVariant`]
7456 // derive-generated [`RestartStrategy::is_simple_one_for_one`]
7457 // predicate rather than the raw
7458 // `matches!(strat, RestartStrategy::SimpleOneForOne)`
7459 // open-coded pattern-match — same closed-set-typed-enum
7460 // arm-discriminator dispatch discipline the sibling
7461 // [`crate::upgrade::UpgradeInstruction::is_restart`] convergence
7462 // (915a934) extended onto its two paired positive / negated
7463 // `matches!` filter sites, and the sibling
7464 // [`crate::aplicacao::PlacementStrategy`] `IsVariant`-derived
7465 // predicate convergence (766ec63) extended onto the M3 mesh-
7466 // slot per-`:placement` distribution-strategy `matches!`
7467 // discriminator axis. See the sibling
7468 // `supervisor_spec_estrategia_returns_estrategia_verbatim_across_permutations`
7469 // fixture and the peer `manifest::tests::
7470 // caixa_estrategia_and_supervisor_view_reads_through_lifted_estrategia_accessor`
7471 // fixture — all three sites (the last unlifted
7472 // `matches!`-based arm-discriminator axis on the OTP-shape
7473 // supervisor sibling-restart-strategy closed-set typed enum,
7474 // acknowledged in 915a934's Prior-commits footnote as the
7475 // outstanding follow-up) now consult one typed dispatch on
7476 // the substrate primitive.
7477 let s = SupervisorSpec {
7478 estrategia: strat,
7479 children: if strat.is_simple_one_for_one() {
7480 vec![]
7481 } else {
7482 vec![child("w", "^0.1", RestartPolicy::Permanent)]
7483 },
7484 ..SupervisorSpec::default()
7485 };
7486 let json = serde_json::to_string(&s).unwrap();
7487 let back: SupervisorSpec = serde_json::from_str(&json).unwrap();
7488 assert_eq!(s, back);
7489 }
7490 }
7491
7492 #[test]
7493 fn round_trip_all_restart_policies() {
7494 for policy in [
7495 RestartPolicy::Permanent,
7496 RestartPolicy::Temporary,
7497 RestartPolicy::Transient,
7498 ] {
7499 let c = child("w", "^0.1", policy);
7500 let json = serde_json::to_string(&c).unwrap();
7501 let back: ChildSpec = serde_json::from_str(&json).unwrap();
7502 assert_eq!(c, back);
7503 }
7504 }
7505
7506 #[test]
7507 fn restart_strategy_is_simple_one_for_one_predicate_partitions_the_arm_set() {
7508 // The fail-before-pass-after pin on the `gen_platform::IsVariant`
7509 // derive's [`RestartStrategy::is_simple_one_for_one`] arm-
7510 // discriminator predicate: [`RestartStrategy::SimpleOneForOne`]
7511 // is the only variant that satisfies `.is_simple_one_for_one()`;
7512 // every static-children-bearing arm (`OneForOne` / `OneForAll`
7513 // / `RestForOne`) returns `false`. This pin makes the partition
7514 // invariant load-bearing at caixa-core test time so a future
7515 // derive regression (a hole that returns `false` for
7516 // `SimpleOneForOne` too, or a byte-collision that flips a second
7517 // variant to `true`) trips here rather than laundering the arm
7518 // at the three test-fixture builder sites (a hole flips the
7519 // `SimpleOneForOne` fixture to carry a non-empty children list
7520 // and the subsequent `SupervisorSpec::validate` would refuse the
7521 // fixture with [`SupervisorError::SimpleOneForOneWithStaticChildren`];
7522 // a collision flips a peer strategy's fixture to carry an empty
7523 // children list and the subsequent `validate` would refuse with
7524 // [`SupervisorError::NoChildren`] — either way, the pin fires
7525 // here, at the derive site, rather than at the fixture-refusal
7526 // site far away). Peer of the sibling
7527 // [`crate::upgrade::tests::upgrade_instruction_is_restart_predicate_partitions_the_arm_set`]
7528 // (915a934) pin on the M2 OTP-appup axis and the sibling
7529 // [`crate::kind::tests::caixa_kind_is_variant_predicates_partition_the_arm_set`]
7530 // pin on the M0 `:kind` axis.
7531 let cases: &[(RestartStrategy, bool)] = &[
7532 (RestartStrategy::OneForOne, false),
7533 (RestartStrategy::OneForAll, false),
7534 (RestartStrategy::RestForOne, false),
7535 (RestartStrategy::SimpleOneForOne, true),
7536 ];
7537 for (variant, expected) in cases {
7538 assert_eq!(
7539 variant.is_simple_one_for_one(),
7540 *expected,
7541 "RestartStrategy::{variant:?}.is_simple_one_for_one() must \
7542 return {expected} (partition invariant on the \
7543 IsVariant-derived arm-discriminator predicate — every \
7544 test-fixture site that partitions the `:children` slot \
7545 shape on `SimpleOneForOne ↔ non-SimpleOneForOne` keys \
7546 off this typed dispatch, so a derive regression must \
7547 surface here rather than at the fixture-refusal site)"
7548 );
7549 }
7550 }
7551
7552 #[test]
7553 fn restart_strategy_fixture_partition_routes_through_is_simple_one_for_one_predicate() {
7554 // Byte-identity pin on the `SimpleOneForOne ↔ non-SimpleOneForOne`
7555 // fixture-shape partition against the pre-lift
7556 // `matches!(strat, RestartStrategy::SimpleOneForOne)` open-coded
7557 // pattern-match every test-fixture builder site previously
7558 // coupled to inline. Asserts the two projections agree byte-for-
7559 // byte on every arm of the enum, so a future derive regression
7560 // that flipped either predicate's arm-set would surface here at
7561 // caixa-core test time rather than at the three fixture-builder
7562 // sites (`supervisor::tests::round_trip_all_strategies`,
7563 // `supervisor::tests::supervisor_spec_estrategia_returns_estrategia_verbatim_across_permutations`,
7564 // `manifest::tests::caixa_estrategia_and_supervisor_view_reads_through_lifted_estrategia_accessor`)
7565 // far from the derive site. Same peer-shape byte-identity pin
7566 // every sibling `IsVariant`-derive-routed convergence carries on
7567 // the substrate's closed-set typed-enum surface (peer of
7568 // [`crate::upgrade::tests::validate_restart_exclusive_routes_through_is_restart_predicate`]
7569 // on the M2 OTP-appup axis).
7570 for &strat in RestartStrategy::ALL {
7571 let via_predicate = strat.is_simple_one_for_one();
7572 let via_matches = matches!(strat, RestartStrategy::SimpleOneForOne);
7573 assert_eq!(
7574 via_predicate, via_matches,
7575 "RestartStrategy::{strat:?}: is_simple_one_for_one() must \
7576 byte-equal matches!(_, RestartStrategy::SimpleOneForOne) — \
7577 the pre-lift open-coded pattern and the \
7578 IsVariant-derived predicate are the same axis, \
7579 one typed dispatch"
7580 );
7581 }
7582 }
7583
7584 #[test]
7585 fn duration_codec_round_trip_canonical_units() {
7586 // Note the canonical-form rule: durations serialize to the
7587 // *largest* unit that divides cleanly, so 60s ↔ "1m" and not
7588 // "60s" — but the round-trip preserves the underlying Duration.
7589 let cases = [
7590 ("30s", Duration::from_secs(30)),
7591 ("5m", Duration::from_secs(300)),
7592 ("1h", Duration::from_secs(3600)),
7593 ("500ms", Duration::from_millis(500)),
7594 ];
7595 for (lit, dur) in cases {
7596 let s = SupervisorSpec {
7597 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7598 restart_window: Some(dur),
7599 ..SupervisorSpec::default()
7600 };
7601 let json = serde_json::to_string(&s).unwrap();
7602 assert!(
7603 json.contains(&format!("\"{lit}\"")),
7604 "expected \"{lit}\" in {json}"
7605 );
7606 let back: SupervisorSpec = serde_json::from_str(&json).unwrap();
7607 assert_eq!(back.restart_window, Some(dur));
7608 }
7609 }
7610
7611 #[test]
7612 fn duration_canonicalizes_to_largest_unit() {
7613 // 60 seconds → "1m" (largest cleanly-divisible unit), but the
7614 // typed Duration still equals 60s on the way back.
7615 let s = SupervisorSpec {
7616 children: vec![child("w", "^0.1", RestartPolicy::Permanent)],
7617 restart_window: Some(Duration::from_secs(60)),
7618 ..SupervisorSpec::default()
7619 };
7620 let json = serde_json::to_string(&s).unwrap();
7621 assert!(json.contains("\"1m\""), "{json}");
7622 let back: SupervisorSpec = serde_json::from_str(&json).unwrap();
7623 assert_eq!(back.restart_window, Some(Duration::from_secs(60)));
7624 }
7625
7626 #[test]
7627 fn three_child_one_for_one_validates() {
7628 let s = SupervisorSpec {
7629 estrategia: RestartStrategy::OneForOne,
7630 max_restarts: 5,
7631 restart_window: Some(Duration::from_secs(60)),
7632 children: vec![
7633 child("worker", "^0.1", RestartPolicy::Permanent),
7634 child("cache", "^0.1", RestartPolicy::Transient),
7635 child("scratch", "^0.1", RestartPolicy::Temporary),
7636 ],
7637 };
7638 s.validate().unwrap();
7639 }
7640
7641 #[test]
7642 fn json_uses_pascal_case_for_strategy_and_policy() {
7643 // Variant names are PascalCase by default in serde, matching
7644 // tatara-lisp's enum convention (`:estrategia OneForOne`).
7645 let c = child("w", "^0.1", RestartPolicy::Permanent);
7646 let json = serde_json::to_string(&c).unwrap();
7647 assert!(json.contains("\"Permanent\""));
7648 assert!(!json.contains("\"permanent\""));
7649
7650 let s = SupervisorSpec {
7651 estrategia: RestartStrategy::OneForOne,
7652 children: vec![c],
7653 ..SupervisorSpec::default()
7654 };
7655 let json = serde_json::to_string(&s).unwrap();
7656 assert!(json.contains("\"estrategia\":\"OneForOne\""));
7657 }
7658
7659 // ── shared duration codec: integer-magnitude canonical-form gate ──
7660 //
7661 // The gate lifts the discipline `crate::limits::parse_duration`
7662 // (818dd38) carries on the peer `:limits :wall-clock` codec onto
7663 // the shared codec backing the remaining three typed-duration
7664 // slots: `:supervisor :restart-window`, `:politicas :timeout`, and
7665 // `:politicas :circuit-breaker :window`. Every magnitude `render`
7666 // emits is a non-negative integer with no decimal point and no
7667 // leading sign, so the codec's accepted set must match for
7668 // serialize/deserialize to round-trip without canonical-form
7669 // drift.
7670
7671 #[test]
7672 fn parse_accepts_integer_canonical_units() {
7673 // Pin the happy-path: every canonical author shape `render`
7674 // ever emits parses to the same `Duration` value, so the
7675 // codec's accepted set is at least a superset of its emitted
7676 // set on the canonical-unit axis.
7677 for (lit, dur) in [
7678 ("30s", Duration::from_secs(30)),
7679 ("500ms", Duration::from_millis(500)),
7680 ("2m", Duration::from_secs(120)),
7681 ("1h", Duration::from_secs(3600)),
7682 ("0s", Duration::ZERO),
7683 ] {
7684 assert_eq!(
7685 duration_codec::parse(lit).unwrap(),
7686 dur,
7687 "parse({lit:?}) should be {dur:?}"
7688 );
7689 }
7690 }
7691
7692 #[test]
7693 fn parse_accepts_bare_integer_as_seconds() {
7694 // The `"s" | ""` arm: a bare integer with no unit is read as
7695 // seconds. Pin this so the unit-empty form keeps parsing (it
7696 // renders to `"<n>s"` on serialize — that's a unit-choice
7697 // drift the integer-magnitude gate does NOT close, matching
7698 // the `parse_byte_size` `"1024"` → `"1KiB"` scope decision in
7699 // the peer `:limits :memory` codec).
7700 assert_eq!(
7701 duration_codec::parse("30").unwrap(),
7702 Duration::from_secs(30)
7703 );
7704 }
7705
7706 #[test]
7707 fn parse_rejects_fractional_seconds_with_canonical_form_diagnostic() {
7708 // `"1.5s"` parses as f64 to 1.5 → renders back as `"1500ms"`
7709 // on first serialize — DRIFT. The integer-magnitude gate names
7710 // the offending `"1.5"` verbatim and points at the canonical
7711 // remediation `"1500ms"`.
7712 let err = duration_codec::parse("1.5s").unwrap_err();
7713 assert!(err.contains("\"1.5\""), "missing magnitude in {err:?}");
7714 assert!(
7715 err.contains("not a non-negative integer"),
7716 "missing canonical-form reason in {err:?}"
7717 );
7718 assert!(
7719 err.contains("\"1500ms\""),
7720 "missing canonical-form remediation in {err:?}"
7721 );
7722 }
7723
7724 #[test]
7725 fn parse_rejects_decimal_shaped_integer_seconds() {
7726 // `"1.0s"` is the trickiest drift class: numerically `1.0s` is
7727 // `1s` exactly, so the round-trip looks correct — but the
7728 // emitted canonical form is `"1s"`, not `"1.0s"`. Gate the
7729 // decimal-shape-with-integer-value form so author intent is
7730 // never silently rewritten.
7731 let err = duration_codec::parse("1.0s").unwrap_err();
7732 assert!(err.contains("\"1.0\""), "missing magnitude in {err:?}");
7733 assert!(
7734 err.contains("not a non-negative integer"),
7735 "missing canonical-form reason in {err:?}"
7736 );
7737 }
7738
7739 #[test]
7740 fn parse_rejects_half_unit_minute() {
7741 // `"0.5m"` is the unit-fraction footgun — author writes a
7742 // human-readable half-minute, serde silently rewrites to
7743 // `"30s"` on next emit. The gate names the offending
7744 // magnitude `"0.5"` and points at the integer-in-smaller-unit
7745 // form.
7746 let err = duration_codec::parse("0.5m").unwrap_err();
7747 assert!(err.contains("\"0.5\""), "missing magnitude in {err:?}");
7748 assert!(
7749 err.contains("\"30s\""),
7750 "missing canonical-form remediation in {err:?}"
7751 );
7752 }
7753
7754 #[test]
7755 fn parse_rejects_leading_plus_sign() {
7756 // `u64::from_str` rejects `"+30"` but `f64::from_str` accepts
7757 // it as `30.0` — the prior parser used f64 so `"+30s"` parsed
7758 // cleanly to 30s and round-tripped to `"30s"` on next emit
7759 // (DRIFT). The digit-only gate closes the leading-sign class
7760 // first; the diagnostic names `"+30"` verbatim.
7761 let err = duration_codec::parse("+30s").unwrap_err();
7762 assert!(err.contains("\"+30\""), "missing magnitude in {err:?}");
7763 assert!(
7764 err.contains("not a non-negative integer"),
7765 "missing canonical-form reason in {err:?}"
7766 );
7767 }
7768
7769 #[test]
7770 fn parse_rejects_leading_minus_sign() {
7771 // The former `num < 0.0` arm: `"-30s"` parsed as f64 to -30,
7772 // rejected with `"negative duration in \"-30s\""`. Under the
7773 // integer-magnitude gate the diagnostic is unified — `-30` is
7774 // non-digit-only, f64-numeric, and surfaces with the canonical-
7775 // form reason (no leading `+` / `-` sign) naming the offending
7776 // `"-30"` verbatim. Same diagnostic shape as every other
7777 // rejected non-integer magnitude.
7778 let err = duration_codec::parse("-30s").unwrap_err();
7779 assert!(err.contains("\"-30\""), "missing magnitude in {err:?}");
7780 assert!(
7781 err.contains("not a non-negative integer"),
7782 "missing canonical-form reason in {err:?}"
7783 );
7784 }
7785
7786 #[test]
7787 fn parse_garbage_still_falls_through_to_bad_magnitude() {
7788 // Non-digit-only AND non-numeric (`"--1s"`, `"abc"`) falls
7789 // through to the narrower "bad duration magnitude" arm — the
7790 // canonical-form diagnostic is reserved for the parser-shape
7791 // footgun case, not the "not a number at all" case. Same
7792 // shape `parse_byte_size`'s `BadByteMagnitude` arm carries on
7793 // the peer `:limits :memory` codec.
7794 let err = duration_codec::parse("--1s").unwrap_err();
7795 assert!(
7796 err.contains("bad duration magnitude"),
7797 "expected bad-magnitude wording in {err:?}"
7798 );
7799 }
7800
7801 #[test]
7802 fn parse_digit_only_magnitude_carries_zero_f64_drift() {
7803 // The accepted set is now closed under `u64`-exact integer
7804 // arithmetic: `"500ms"` → `Duration::from_millis(500)` exactly,
7805 // `"3600s"` → `Duration::from_secs(3600)` exactly, `"1h"` →
7806 // `Duration::from_secs(3600)` exactly, no f64 mantissa drift
7807 // possible. Pin the integer-exact arms across the four unit
7808 // suffixes so a future refactor that reaches back for f64
7809 // (`from_secs_f64`, `mul_f64`) surfaces here.
7810 assert_eq!(
7811 duration_codec::parse("3600s").unwrap(),
7812 Duration::from_secs(3600)
7813 );
7814 assert_eq!(
7815 duration_codec::parse("60m").unwrap(),
7816 Duration::from_secs(3600)
7817 );
7818 assert_eq!(
7819 duration_codec::parse("1h").unwrap(),
7820 Duration::from_secs(3600)
7821 );
7822 assert_eq!(
7823 duration_codec::parse("999ms").unwrap(),
7824 Duration::from_millis(999)
7825 );
7826 }
7827
7828 #[test]
7829 fn restart_window_serde_rejects_fractional_seconds() {
7830 // The shared codec backs `SupervisorSpec::restart_window`
7831 // (`with = "duration_codec"`) — so the gate applies on serde
7832 // deserialize for the typed Supervisor slot. A
7833 // `{"restartWindow":"1.5s"}` payload that previously round-
7834 // tripped to a different canonical string on next serialize
7835 // is now refused at deserialize with the integer-magnitude
7836 // diagnostic.
7837 let payload = r#"{"estrategia":"OneForOne","maxRestarts":5,
7838 "restartWindow":"1.5s",
7839 "children":[{"caixa":"w","versao":"^0.1","restart":"Permanent"}]}"#;
7840 let err = serde_json::from_str::<SupervisorSpec>(payload).unwrap_err();
7841 let msg = err.to_string();
7842 assert!(
7843 msg.contains("not a non-negative integer"),
7844 "expected integer-magnitude diagnostic in {msg:?}"
7845 );
7846 assert!(msg.contains("\"1.5\""), "missing magnitude in {msg:?}");
7847 }
7848
7849 #[test]
7850 fn restart_window_serde_rejects_leading_plus() {
7851 // The `u64::from_str` leading-`+` permissiveness gap that
7852 // motivated the digit-only gate (the `f64`-side accepted
7853 // `"+30"`, the prior parser silently round-tripped to `"30s"`)
7854 // is now closed on the shared codec — surfaces as a structured
7855 // diagnostic at the serde layer for every typed-duration slot.
7856 let payload = r#"{"estrategia":"OneForOne","maxRestarts":5,
7857 "restartWindow":"+30s",
7858 "children":[{"caixa":"w","versao":"^0.1","restart":"Permanent"}]}"#;
7859 let err = serde_json::from_str::<SupervisorSpec>(payload).unwrap_err();
7860 let msg = err.to_string();
7861 assert!(msg.contains("\"+30\""), "missing magnitude in {msg:?}");
7862 assert!(
7863 msg.contains("not a non-negative integer"),
7864 "missing canonical-form reason in {msg:?}"
7865 );
7866 }
7867
7868 #[test]
7869 fn parse_rejects_leading_zero_magnitude() {
7870 // `"030s"` is digit-only, so the existing non-digit-only / sign
7871 // / fractional arm doesn't catch it — `u64::from_str("030")`
7872 // returns `Ok(30)`, so before this gate `"030s"` parsed to
7873 // `Duration::from_secs(30)` and round-tripped through `render`
7874 // to `"30s"` — a *different* canonical string on the next emit,
7875 // breaking the THEORY.md Part V render-determinism contract
7876 // exactly the way `"+30s"` did before the leading-`+` arm
7877 // landed. Peer with the `rate_limit_codec` leading-zero arm
7878 // (4f46830) on the same canonical-form-drift axis.
7879 let err = duration_codec::parse("030s").unwrap_err();
7880 assert!(
7881 err.contains("non-canonical leading zero"),
7882 "expected leading-zero diagnostic in {err:?}"
7883 );
7884 assert!(err.contains("\"030\""), "missing magnitude in {err:?}");
7885 assert!(
7886 err.contains("\"30s\""),
7887 "missing canonical-form remediation in {err:?}"
7888 );
7889 assert!(
7890 err.contains("THEORY.md"),
7891 "missing render-determinism citation in {err:?}"
7892 );
7893 }
7894
7895 #[test]
7896 fn parse_rejects_multi_digit_zero_magnitude() {
7897 // `"00s"` and `"00ms"` are the all-zero leading-zero footgun —
7898 // digit-only, parse losslessly to `Duration::ZERO`, but render
7899 // back to `"0s"` (the single-byte canonical form) on the next
7900 // emit. The leading-zero arm refuses the drift class at the
7901 // codec layer; the semantic-zero gate downstream
7902 // (`SupervisorError::ZeroRestartWindow`, etc.) would refuse
7903 // the single-byte canonical form `"0s"` separately on the
7904 // typed-validate layer.
7905 let err = duration_codec::parse("00s").unwrap_err();
7906 assert!(
7907 err.contains("non-canonical leading zero"),
7908 "expected leading-zero diagnostic in {err:?}"
7909 );
7910 assert!(err.contains("\"00\""), "missing magnitude in {err:?}");
7911 }
7912
7913 #[test]
7914 fn parse_rejects_leading_zero_per_hour_window() {
7915 // `"01h"` is the per-hour-window footgun — multi-byte magnitude
7916 // starting with `0`, parses losslessly to `Duration::from_secs(3600)`,
7917 // renders to `"1h"` (DRIFT). The arm is unit-agnostic: every
7918 // canonical unit suffix the codec accepts (`ms` / `s` / `m` /
7919 // `h` / bare-integer-as-seconds) inherits the same gate.
7920 let err = duration_codec::parse("01h").unwrap_err();
7921 assert!(
7922 err.contains("non-canonical leading zero"),
7923 "expected leading-zero diagnostic in {err:?}"
7924 );
7925 assert!(err.contains("\"01\""), "missing magnitude in {err:?}");
7926 }
7927
7928 #[test]
7929 fn parse_rejects_leading_zero_bare_integer_as_seconds() {
7930 // The `parse_accepts_bare_integer_as_seconds` happy-path
7931 // (`"30"` → 30s) inherits the leading-zero arm: `"030"` is
7932 // multi-byte starts-with-`0`, parses losslessly to
7933 // `Duration::from_secs(30)`, renders to `"30s"` (DRIFT). The
7934 // bare-integer surface accepts permissive unit-empty
7935 // shorthand but still must reject leading-zero padding.
7936 let err = duration_codec::parse("030").unwrap_err();
7937 assert!(
7938 err.contains("non-canonical leading zero"),
7939 "expected leading-zero diagnostic in {err:?}"
7940 );
7941 assert!(err.contains("\"030\""), "missing magnitude in {err:?}");
7942 }
7943
7944 #[test]
7945 fn parse_accepts_single_zero_magnitude_at_codec_layer() {
7946 // The codec-layer / typed-validate-layer boundary: `"0s"` /
7947 // `"0ms"` / `"0"` are the single-byte canonical-zero forms —
7948 // each round-trips losslessly through `render`
7949 // (`render(Duration::ZERO)` → `"0s"`), so the codec layer
7950 // accepts them. The downstream semantic-zero gates
7951 // (`SupervisorError::ZeroRestartWindow`,
7952 // `AplicacaoError::PolicyTimeoutZero`,
7953 // `AplicacaoError::PolicyCircuitBreakerWindowZero`) refuse
7954 // zero-magnitude authoring at the typed-validate layer above,
7955 // peer with the `rate_limit_codec` codec-layer / typed-
7956 // validate-layer partition for `"0/s"`.
7957 assert_eq!(duration_codec::parse("0s").unwrap(), Duration::ZERO);
7958 assert_eq!(duration_codec::parse("0ms").unwrap(), Duration::ZERO);
7959 assert_eq!(duration_codec::parse("0").unwrap(), Duration::ZERO);
7960 }
7961
7962 #[test]
7963 fn parse_accepts_canonical_magnitude_with_leading_one() {
7964 // The complementary boundary: a future tightening cannot
7965 // drift into rejecting valid canonical magnitudes that
7966 // happen to start with `1` (or any digit `[1-9]`). Pin
7967 // every canonical-unit suffix so the leading-zero arm
7968 // remains strictly narrower than the digit-only arm.
7969 assert_eq!(
7970 duration_codec::parse("100ms").unwrap(),
7971 Duration::from_millis(100)
7972 );
7973 assert_eq!(
7974 duration_codec::parse("100s").unwrap(),
7975 Duration::from_secs(100)
7976 );
7977 assert_eq!(
7978 duration_codec::parse("10m").unwrap(),
7979 Duration::from_secs(600)
7980 );
7981 assert_eq!(
7982 duration_codec::parse("10h").unwrap(),
7983 Duration::from_secs(36_000)
7984 );
7985 }
7986
7987 #[test]
7988 fn restart_window_serde_rejects_leading_zero() {
7989 // The shared codec backs `SupervisorSpec::restart_window`
7990 // (`with = "duration_codec"`) — so the leading-zero arm
7991 // applies on serde deserialize for the typed Supervisor slot.
7992 // A `{"restartWindow":"030s"}` payload that previously round-
7993 // tripped to a different canonical string on next serialize
7994 // is now refused at deserialize with the leading-zero
7995 // diagnostic. Peer with `restart_window_serde_rejects_leading_plus`
7996 // / `restart_window_serde_rejects_fractional_seconds` on the
7997 // same canonical-form-drift axis.
7998 let payload = r#"{"estrategia":"OneForOne","maxRestarts":5,
7999 "restartWindow":"030s",
8000 "children":[{"caixa":"w","versao":"^0.1","restart":"Permanent"}]}"#;
8001 let err = serde_json::from_str::<SupervisorSpec>(payload).unwrap_err();
8002 let msg = err.to_string();
8003 assert!(
8004 msg.contains("non-canonical leading zero"),
8005 "expected leading-zero diagnostic in {msg:?}"
8006 );
8007 assert!(msg.contains("\"030\""), "missing magnitude in {msg:?}");
8008 }
8009
8010 #[test]
8011 fn parse_rejects_leading_whitespace() {
8012 // `" 30s"` — the canonical paste-from-aligned-doc /
8013 // paste-from-YAML-quoted-plain-scalar footgun. Before this
8014 // gate the top-level `s.trim()` at parse entry silently ate
8015 // the leading space and parsed the value to
8016 // `Duration::from_secs(30)`, which then round-tripped through
8017 // `render` to `"30s"` (a *different* canonical string on the
8018 // next emit) — the exact canonical-form-drift class the
8019 // leading-`+` / leading-zero arms already close, extended
8020 // to the whitespace-byte class. Peer with the sibling
8021 // `rate_limit_codec` whitespace-rejection arm (1ad7755) on
8022 // the M3 `:politicas` axis.
8023 let err = duration_codec::parse(" 30s").unwrap_err();
8024 assert!(
8025 err.contains("contains whitespace byte"),
8026 "expected whitespace diagnostic in {err:?}"
8027 );
8028 assert!(err.contains("0x20"), "missing offending byte in {err:?}");
8029 assert!(
8030 err.contains("THEORY.md"),
8031 "missing render-determinism contract citation in {err:?}"
8032 );
8033 }
8034
8035 #[test]
8036 fn parse_rejects_trailing_whitespace() {
8037 // `"30s "` — the canonical shell-history / trailing-space
8038 // paste footgun. Before this gate the top-level `s.trim()`
8039 // silently ate the trailing space and parsed to
8040 // `Duration::from_secs(30)`, round-tripping to `"30s"` on the
8041 // next emit — same canonical-form drift as the leading-space
8042 // sibling, closed on the same whitespace-byte arm.
8043 let err = duration_codec::parse("30s ").unwrap_err();
8044 assert!(
8045 err.contains("contains whitespace byte"),
8046 "expected whitespace diagnostic in {err:?}"
8047 );
8048 assert!(err.contains("0x20"), "missing offending byte in {err:?}");
8049 }
8050
8051 #[test]
8052 fn parse_rejects_internal_whitespace_between_magnitude_and_unit() {
8053 // `"30 s"` — the canonical typographically-spaced author
8054 // shape (the same idiom every prose reference to a duration
8055 // renders as, mistakenly retained when the value is pasted
8056 // into a codec-shaped slot). Before this gate the per-part
8057 // `num_part.trim()` / `unit.trim()` calls silently ate the
8058 // whitespace between the magnitude and the unit and parsed
8059 // the value to `Duration::from_secs(30)`, round-tripping to
8060 // `"30s"` — the codec's *internal* whitespace-tolerance
8061 // vector, orthogonal to the leading / trailing surface but
8062 // the same canonical-form-drift class. Pins the arm as
8063 // strictly stronger than the pre-existing top-level
8064 // `s.trim()` behavior: it fires on whitespace anywhere in
8065 // the value, not just at the string boundary.
8066 let err = duration_codec::parse("30 s").unwrap_err();
8067 assert!(
8068 err.contains("contains whitespace byte"),
8069 "expected whitespace diagnostic in {err:?}"
8070 );
8071 assert!(err.contains("0x20"), "missing offending byte in {err:?}");
8072 }
8073
8074 #[test]
8075 fn parse_rejects_tab_byte() {
8076 // `"\t30s"` — the canonical paste-from-indented-doc /
8077 // paste-from-YAML-block-scalar footgun where a tab byte leads
8078 // the magnitude. Pins that the gate covers tab (`0x09`) as
8079 // well as space (`0x20`) — both are `u8::is_ascii_whitespace`
8080 // members and both would be silently swallowed by `s.trim()`
8081 // pre-gate. The `is_ascii_whitespace` coverage extends beyond
8082 // space alone to the full ASCII-whitespace set (space `0x20`,
8083 // tab `0x09`, LF `0x0A`, FF `0x0C`, CR `0x0D`); this test pins
8084 // the tab arm as a representative of the non-space members.
8085 let err = duration_codec::parse("\t30s").unwrap_err();
8086 assert!(
8087 err.contains("contains whitespace byte"),
8088 "expected whitespace diagnostic in {err:?}"
8089 );
8090 assert!(
8091 err.contains("0x09"),
8092 "missing offending tab byte in {err:?}"
8093 );
8094 }
8095
8096 #[test]
8097 fn restart_window_serde_rejects_whitespace() {
8098 // The shared codec backs `SupervisorSpec::restart_window`
8099 // (`with = "duration_codec"`) — so the whitespace arm
8100 // applies on serde deserialize for the typed Supervisor slot.
8101 // A `{"restartWindow":" 30s"}` payload that previously round-
8102 // tripped to a different canonical string on next serialize
8103 // is now refused at deserialize with the whitespace-byte
8104 // diagnostic. Peer with `restart_window_serde_rejects_leading_zero`
8105 // / `restart_window_serde_rejects_leading_plus` /
8106 // `restart_window_serde_rejects_fractional_seconds` on the
8107 // same canonical-form-drift axis.
8108 let payload = r#"{"estrategia":"OneForOne","maxRestarts":5,
8109 "restartWindow":" 30s",
8110 "children":[{"caixa":"w","versao":"^0.1","restart":"Permanent"}]}"#;
8111 let err = serde_json::from_str::<SupervisorSpec>(payload).unwrap_err();
8112 let msg = err.to_string();
8113 assert!(
8114 msg.contains("contains whitespace byte"),
8115 "expected whitespace diagnostic in {msg:?}"
8116 );
8117 assert!(msg.contains("0x20"), "missing offending byte in {msg:?}");
8118 }
8119
8120 // ── canonical-form: non-ASCII Unicode `White_Space` duration gate ─────
8121 //
8122 // Successor to the ASCII-whitespace arm (a7ae622) on the shared
8123 // duration codec — closes the strictly-complementary class the
8124 // byte-scan cannot see, through the lifted
8125 // [`crate::render::find_non_ascii_whitespace_char`] predicate.
8126 // Applies to `:supervisor :restart-window`, `:politicas :timeout`,
8127 // and `:politicas :circuit-breaker :window` simultaneously via
8128 // this shared codec.
8129
8130 #[test]
8131 fn duration_codec_parse_rejects_leading_nbsp() {
8132 // NBSP prefix — the strictly-complementary drift class the
8133 // ASCII byte-scan cannot see. `str::trim` strips it silently
8134 // and the value drifts to `"30s"` on next serialize.
8135 let err = duration_codec::parse("\u{00A0}30s").unwrap_err();
8136 assert!(
8137 err.contains("non-ASCII Unicode whitespace character"),
8138 "expected non-ASCII whitespace diagnostic in {err:?}"
8139 );
8140 assert!(err.contains("U+00A0"), "missing codepoint in {err:?}");
8141 }
8142
8143 #[test]
8144 fn duration_codec_parse_rejects_trailing_line_separator() {
8145 // LINE SEPARATOR (`\u{2028}`) trailing — paste-from-web-doc
8146 // footgun.
8147 let err = duration_codec::parse("30s\u{2028}").unwrap_err();
8148 assert!(
8149 err.contains("non-ASCII Unicode whitespace character"),
8150 "expected non-ASCII whitespace diagnostic in {err:?}"
8151 );
8152 assert!(err.contains("U+2028"), "missing codepoint in {err:?}");
8153 }
8154
8155 #[test]
8156 fn duration_codec_parse_accepts_ascii_only_forms_after_unicode_arm() {
8157 // Positive-control pin: every ASCII-only canonical form the
8158 // renderer emits stays accepted through the new arm.
8159 assert_eq!(
8160 duration_codec::parse("30s").unwrap(),
8161 Duration::from_secs(30)
8162 );
8163 assert_eq!(
8164 duration_codec::parse("500ms").unwrap(),
8165 Duration::from_millis(500)
8166 );
8167 assert_eq!(
8168 duration_codec::parse("1h").unwrap(),
8169 Duration::from_secs(3600)
8170 );
8171 }
8172
8173 #[test]
8174 fn restart_window_serde_rejects_non_ascii_whitespace() {
8175 // The shared codec backs `SupervisorSpec::restart_window` — so
8176 // the new non-ASCII Unicode whitespace arm applies on serde
8177 // deserialize for the typed Supervisor slot. A
8178 // `{"restartWindow":" 30s"}` payload that previously
8179 // survived the ASCII byte-scan (only ASCII whitespace was
8180 // refused) is now refused at deserialize with the
8181 // non-ASCII-whitespace-and-codepoint diagnostic.
8182 let payload = "{\"estrategia\":\"OneForOne\",\"maxRestarts\":5,\
8183 \"restartWindow\":\"\u{00A0}30s\",\
8184 \"children\":[{\"caixa\":\"w\",\"versao\":\"^0.1\",\"restart\":\"Permanent\"}]}";
8185 let err = serde_json::from_str::<SupervisorSpec>(payload).unwrap_err();
8186 let msg = err.to_string();
8187 assert!(
8188 msg.contains("non-ASCII Unicode whitespace character"),
8189 "expected non-ASCII whitespace diagnostic in {msg:?}"
8190 );
8191 assert!(msg.contains("U+00A0"), "missing codepoint in {msg:?}");
8192 }
8193
8194 // ── drift-detection: serde-derive-to-SUPERVISOR_KEY_* identity ────────
8195
8196 #[test]
8197 fn supervisor_spec_serde_keys_match_lifted_supervisor_key_consts() {
8198 // Load-bearing invariant: the four `SUPERVISOR_KEY_*` consts
8199 // (`SUPERVISOR_KEY_ESTRATEGIA` / `SUPERVISOR_KEY_MAX_RESTARTS` /
8200 // `SUPERVISOR_KEY_RESTART_WINDOW` / `SUPERVISOR_KEY_CHILDREN`)
8201 // name the exact camelCase JSON keys the
8202 // `#[serde(rename_all = "camelCase")]` attribute on
8203 // `SupervisorSpec` emits. Serialize a fully-populated spec (each
8204 // field carries `Some(_)` / non-empty) and pin that each canonical
8205 // byte-sequence appears verbatim in the JSON — a future accidental
8206 // `rename_all = "snake_case"` / `"kebab-case"` / verbatim-field-
8207 // name flip at the derive attribute (any of which would silently
8208 // break every downstream JSON consumer that reaches for one of the
8209 // four consts via `Value::get(...)`) surfaces here as a build-time
8210 // test failure at `supervisor.rs`, not as an apply-time
8211 // `.get(<stale-canonical-const>)` returning `None` far from the
8212 // derive-attr drift's commit. Peer with the sibling
8213 // `limits_spec_serde_keys_match_lifted_m2_limits_key_consts`
8214 // (d8b8b4f) pin on the M2 `:limits` axis — same discipline the
8215 // M2 typed-slot family established, extended here to close the
8216 // top-level Supervisor axis.
8217 let spec = SupervisorSpec {
8218 estrategia: RestartStrategy::OneForOne,
8219 max_restarts: 5,
8220 restart_window: Some(Duration::from_secs(60)),
8221 children: vec![ChildSpec {
8222 caixa: "w".into(),
8223 versao: "^0.1".into(),
8224 restart: RestartPolicy::Permanent,
8225 }],
8226 };
8227 let json = serde_json::to_string(&spec).unwrap();
8228 for key in [
8229 crate::render::SUPERVISOR_KEY_ESTRATEGIA,
8230 crate::render::SUPERVISOR_KEY_MAX_RESTARTS,
8231 crate::render::SUPERVISOR_KEY_RESTART_WINDOW,
8232 crate::render::SUPERVISOR_KEY_CHILDREN,
8233 ] {
8234 let quoted = format!("\"{key}\"");
8235 assert!(
8236 json.contains("ed),
8237 "serialized SupervisorSpec must carry the lifted \
8238 SUPERVISOR_KEY_* byte-sequence {quoted} verbatim in \
8239 the JSON emission (got: {json})",
8240 );
8241 }
8242 }
8243
8244 #[test]
8245 fn supervisor_key_consts_are_pairwise_distinct() {
8246 // Cross-axis drift-detection pin: a future collapse of two
8247 // canonical top-level byte-strings onto the same value (e.g. an
8248 // accidental copy-paste flip of `SUPERVISOR_KEY_CHILDREN` to
8249 // also read `"estrategia"`) would silently reroute every
8250 // downstream probe on one axis onto the sibling axis's overlay
8251 // entry and pass every propagation-probe test that expected only
8252 // the stale axis's value. Peer of the sibling four-way distinct
8253 // pin on the `M2_LIMITS_KEY_*` tetrad (d8b8b4f).
8254 let all = [
8255 crate::render::SUPERVISOR_KEY_ESTRATEGIA,
8256 crate::render::SUPERVISOR_KEY_MAX_RESTARTS,
8257 crate::render::SUPERVISOR_KEY_RESTART_WINDOW,
8258 crate::render::SUPERVISOR_KEY_CHILDREN,
8259 ];
8260 for (i, a) in all.iter().enumerate() {
8261 for b in all.iter().skip(i + 1) {
8262 assert_ne!(
8263 a, b,
8264 "SUPERVISOR_KEY_* consts must be pairwise-distinct \
8265 canonical byte-sequences — got `{a}` == `{b}`",
8266 );
8267 }
8268 }
8269 }
8270
8271 #[test]
8272 fn supervisor_key_consts_are_lower_camel_case_shape() {
8273 // Shape-pin: every `SUPERVISOR_KEY_*` const must be a
8274 // lowerCamelCase byte-sequence (no `snake_case` underscores, no
8275 // `kebab-case` hyphens, no leading colon, no `PascalCase` leading
8276 // capital, no whitespace / dots) — the canonical shape the
8277 // `#[serde(rename_all = "camelCase")]` derive produces on
8278 // `SupervisorSpec`. A future flip to a non-camelCase attribute
8279 // at the derive surfaces both here (this test fails on the
8280 // stale-constant shape) and at
8281 // `supervisor_spec_serde_keys_match_lifted_supervisor_key_consts`
8282 // (that test fails on the mismatch between const and derive).
8283 // Peer with `m2_limits_key_consts_are_lower_camel_case_shape`
8284 // (d8b8b4f) on the sibling M2 `:limits` axis.
8285 for key in [
8286 crate::render::SUPERVISOR_KEY_ESTRATEGIA,
8287 crate::render::SUPERVISOR_KEY_MAX_RESTARTS,
8288 crate::render::SUPERVISOR_KEY_RESTART_WINDOW,
8289 crate::render::SUPERVISOR_KEY_CHILDREN,
8290 ] {
8291 assert!(
8292 !key.is_empty(),
8293 "SUPERVISOR_KEY_* must be non-empty (got {key:?})"
8294 );
8295 let first = key.chars().next().unwrap();
8296 assert!(
8297 first.is_ascii_lowercase(),
8298 "SUPERVISOR_KEY_* must lead with an ASCII-lowercase byte \
8299 (got {key:?}, leads with {first:?})",
8300 );
8301 assert!(
8302 key.chars().all(|c| c.is_ascii_alphanumeric()),
8303 "SUPERVISOR_KEY_* must be ASCII-alphanumeric only \
8304 — no `_` / `-` / `:` / `.` / whitespace (got {key:?})",
8305 );
8306 }
8307 }
8308
8309 #[test]
8310 fn supervisor_key_consts_are_byte_distinct_from_supervisor_author_key_peers() {
8311 // Cross-axis drift pin: the four `SUPERVISOR_KEY_*` consts
8312 // (camelCase JSON keys, no leading colon) must never collide
8313 // byte-for-byte with the four peer `SUPERVISOR_AUTHOR_KEY_*`
8314 // consts (kebab-case author-facing labels with leading colon)
8315 // that sit next to them at `caixa_core::render`. Both families
8316 // cover the same four typed Supervisor slots on two distinct
8317 // axes (author-side kebab vs renderer-side camelCase);
8318 // collapsing either family onto the other's byte-shape would
8319 // silently reroute the render-side probe onto the author-facing
8320 // surface, or vice versa. Peer of the byte-distinctness
8321 // discipline the `M3_PLACEMENT_KEY_ESTRATEGIA` docstring names
8322 // against the peer `M3_AUTHOR_KEY_PLACEMENT`.
8323 let pairs = [
8324 (
8325 crate::render::SUPERVISOR_KEY_ESTRATEGIA,
8326 crate::render::SUPERVISOR_AUTHOR_KEY_ESTRATEGIA,
8327 ),
8328 (
8329 crate::render::SUPERVISOR_KEY_MAX_RESTARTS,
8330 crate::render::SUPERVISOR_AUTHOR_KEY_MAX_RESTARTS,
8331 ),
8332 (
8333 crate::render::SUPERVISOR_KEY_RESTART_WINDOW,
8334 crate::render::SUPERVISOR_AUTHOR_KEY_RESTART_WINDOW,
8335 ),
8336 (
8337 crate::render::SUPERVISOR_KEY_CHILDREN,
8338 crate::render::SUPERVISOR_AUTHOR_KEY_CHILDREN,
8339 ),
8340 ];
8341 for (json_key, author_key) in pairs {
8342 assert_ne!(
8343 json_key, author_key,
8344 "SUPERVISOR_KEY_* (JSON side) must differ byte-for-byte \
8345 from the peer SUPERVISOR_AUTHOR_KEY_* (author side); \
8346 got JSON `{json_key}` == author `{author_key}`",
8347 );
8348 }
8349 }
8350
8351 // ── drift-detection: serde-derive-to-SUPERVISOR_CHILD_KEY_* identity ──
8352
8353 #[test]
8354 fn child_spec_serde_keys_match_lifted_supervisor_child_key_consts() {
8355 // Load-bearing invariant: the three `SUPERVISOR_CHILD_KEY_*` consts
8356 // (`SUPERVISOR_CHILD_KEY_CAIXA` / `SUPERVISOR_CHILD_KEY_VERSAO` /
8357 // `SUPERVISOR_CHILD_KEY_RESTART`) name the exact camelCase JSON
8358 // keys the `#[serde(rename_all = "camelCase")]` attribute on
8359 // `ChildSpec` emits. Serialize a fully-populated `ChildSpec` and
8360 // pin that each canonical byte-sequence appears verbatim in the
8361 // JSON — a future accidental `rename_all = "snake_case"` /
8362 // `"kebab-case"` / verbatim-field-name flip at the derive
8363 // attribute (any of which would silently break every downstream
8364 // JSON consumer that reaches for one of the three consts via
8365 // `Value::get(...)`) surfaces here as a build-time test failure at
8366 // `supervisor.rs`, not as an apply-time
8367 // `.get(<stale-canonical-const>)` returning `None` far from the
8368 // derive-attr drift's commit. Peer with the enclosing
8369 // `supervisor_spec_serde_keys_match_lifted_supervisor_key_consts`
8370 // (40cc4e5) pin on the M2 supervision-tree top-level axis — same
8371 // discipline the SupervisorSpec top-level lift established,
8372 // extended here to the sibling per-`:children` entry `ChildSpec`
8373 // derive so the last M2 typed-struct sub-block
8374 // `#[serde(rename_all = "camelCase")]` axis on the Supervisor
8375 // surface without a lifted serde-key peer joins the substrate's
8376 // "one canonical byte-string per typed serialized-key axis"
8377 // discipline.
8378 let c = ChildSpec {
8379 caixa: "worker".into(),
8380 versao: "^0.1".into(),
8381 restart: RestartPolicy::Permanent,
8382 };
8383 let json = serde_json::to_string(&c).unwrap();
8384 for key in [
8385 crate::render::SUPERVISOR_CHILD_KEY_CAIXA,
8386 crate::render::SUPERVISOR_CHILD_KEY_VERSAO,
8387 crate::render::SUPERVISOR_CHILD_KEY_RESTART,
8388 ] {
8389 let quoted = format!("\"{key}\"");
8390 assert!(
8391 json.contains("ed),
8392 "serialized ChildSpec must carry the lifted \
8393 SUPERVISOR_CHILD_KEY_* byte-sequence {quoted} verbatim \
8394 in the JSON emission (got: {json})",
8395 );
8396 }
8397 }
8398
8399 #[test]
8400 fn supervisor_child_key_consts_are_pairwise_distinct() {
8401 // Cross-axis drift-detection pin: a future collapse of two
8402 // canonical `ChildSpec` per-entry byte-strings onto the same
8403 // value (e.g. an accidental copy-paste flip of
8404 // `SUPERVISOR_CHILD_KEY_RESTART` to also read `"caixa"`) would
8405 // silently reroute every downstream probe on one axis onto the
8406 // sibling axis's overlay entry and pass every propagation-probe
8407 // test that expected only the stale axis's value. Peer of the
8408 // sibling three-way distinct pin on the `CONTRATO_KEY_*` triad
8409 // (ca463a4) and the two-way distinct pin on the `MEMBRO_KEY_*`
8410 // pair (ce80ca0).
8411 let all = [
8412 crate::render::SUPERVISOR_CHILD_KEY_CAIXA,
8413 crate::render::SUPERVISOR_CHILD_KEY_VERSAO,
8414 crate::render::SUPERVISOR_CHILD_KEY_RESTART,
8415 ];
8416 for (i, a) in all.iter().enumerate() {
8417 for b in all.iter().skip(i + 1) {
8418 assert_ne!(
8419 a, b,
8420 "SUPERVISOR_CHILD_KEY_* consts must be pairwise-\
8421 distinct canonical byte-sequences — got `{a}` == `{b}`",
8422 );
8423 }
8424 }
8425 }
8426
8427 #[test]
8428 fn supervisor_child_key_consts_are_lower_camel_case_shape() {
8429 // Shape-pin: every `SUPERVISOR_CHILD_KEY_*` const must be a
8430 // lowerCamelCase byte-sequence (no `snake_case` underscores, no
8431 // `kebab-case` hyphens, no leading colon, no `PascalCase` leading
8432 // capital, no whitespace / dots) — the canonical shape the
8433 // `#[serde(rename_all = "camelCase")]` derive produces on
8434 // `ChildSpec`. A future flip to a non-camelCase attribute at the
8435 // derive surfaces both here (this test fails on the
8436 // stale-constant shape) and at
8437 // `child_spec_serde_keys_match_lifted_supervisor_child_key_consts`
8438 // (that test fails on the mismatch between const and derive).
8439 // Peer with `supervisor_key_consts_are_lower_camel_case_shape`
8440 // (40cc4e5) on the sibling `SupervisorSpec` top-level axis.
8441 for key in [
8442 crate::render::SUPERVISOR_CHILD_KEY_CAIXA,
8443 crate::render::SUPERVISOR_CHILD_KEY_VERSAO,
8444 crate::render::SUPERVISOR_CHILD_KEY_RESTART,
8445 ] {
8446 assert!(
8447 !key.is_empty(),
8448 "SUPERVISOR_CHILD_KEY_* must be non-empty (got {key:?})"
8449 );
8450 let first = key.chars().next().unwrap();
8451 assert!(
8452 first.is_ascii_lowercase(),
8453 "SUPERVISOR_CHILD_KEY_* must lead with an ASCII-lowercase \
8454 byte (got {key:?}, leads with {first:?})",
8455 );
8456 assert!(
8457 key.chars().all(|c| c.is_ascii_alphanumeric()),
8458 "SUPERVISOR_CHILD_KEY_* must be ASCII-alphanumeric only \
8459 — no `_` / `-` / `:` / `.` / whitespace (got {key:?})",
8460 );
8461 }
8462 }
8463
8464 // ── drift-detection: serde-derive-to-SUPERVISOR_ESTRATEGIA_* identity ────
8465
8466 #[test]
8467 fn restart_strategy_variants_serialize_to_lifted_scalar_values() {
8468 // The fail-before-pass-after pin: pre-lift there was no
8469 // single-source binding between the [`RestartStrategy`] variant
8470 // name the un-`rename`d `Serialize` derive emits under
8471 // [`crate::render::SUPERVISOR_KEY_ESTRATEGIA`] and the byte-string
8472 // every downstream cluster-side dispatcher (the future
8473 // wasm-operator's per-supervisor sibling-restart branch, the
8474 // future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
8475 // admission-time enum-arm bind, the `caixa-operator`'s
8476 // hierarchical reconciliation scheduler's per-strategy fan-out)
8477 // probes verbatim. A future `#[serde(rename_all = "kebab-case")]`
8478 // attribute on the enum — or a per-variant `#[serde(rename = "…")]`
8479 // override, or a variant rename in the source — would silently
8480 // rebrand the emitted scalar under one spelling while every
8481 // downstream dispatcher still probed the other, with the failure
8482 // surfacing at the operator's reconcile posture (subtrees coming
8483 // up under the `default()` `OneForOne` arm rather than the typed
8484 // slot's declared strategy — a bad child would then only take
8485 // itself down instead of the sibling set the author intended, so
8486 // shared-state children fall out of sync) far from the source
8487 // rebrand commit and with no field naming the drift. Pinning the
8488 // two paths (the `Serialize` derive's serialized string AND the
8489 // [`RestartStrategy::as_str`] helper) to the same four lifted
8490 // [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE`] /
8491 // [`crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL`] /
8492 // [`crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`] /
8493 // [`crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE`]
8494 // byte-strings makes any future drift on either endpoint fail
8495 // here at caixa-core build time. Peer of the M3
8496 // `placement_strategy_variants_serialize_to_lifted_scalar_values`
8497 // (3f0e21c) on the sibling `PlacementStrategy` axis — same
8498 // three-path-convergence discipline, extended to close the
8499 // OTP-shaped per-supervisor sibling-restart axis.
8500 for (variant, expected) in [
8501 (
8502 RestartStrategy::OneForOne,
8503 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
8504 ),
8505 (
8506 RestartStrategy::OneForAll,
8507 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
8508 ),
8509 (
8510 RestartStrategy::RestForOne,
8511 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
8512 ),
8513 (
8514 RestartStrategy::SimpleOneForOne,
8515 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
8516 ),
8517 ] {
8518 let json = serde_json::to_string(&variant).unwrap();
8519 assert_eq!(
8520 json,
8521 format!("\"{expected}\""),
8522 "RestartStrategy::{variant:?} must serialize to {expected:?}"
8523 );
8524 assert_eq!(
8525 variant.as_str(),
8526 expected,
8527 "RestartStrategy::{variant:?}.as_str() must return the lifted \
8528 SUPERVISOR_ESTRATEGIA_* constant"
8529 );
8530 }
8531 }
8532
8533 #[test]
8534 fn supervisor_estrategia_consts_are_pairwise_distinct() {
8535 // Cross-arm drift-detection pin: a future collapse of two
8536 // canonical variant byte-strings onto the same value (e.g. an
8537 // accidental copy-paste flip of `SUPERVISOR_ESTRATEGIA_REST_FOR_ONE`
8538 // to also read `"OneForOne"`) would silently reroute every
8539 // downstream operator's per-strategy dispatch onto the sibling
8540 // arm's reconcile branch and pass every propagation-probe test
8541 // that expected only the stale arm's value — the mis-strategied
8542 // subtree would come up with the wrong sibling-restart posture
8543 // on every subsequent failure. Peer of the sibling four-way
8544 // distinct pin `supervisor_key_consts_are_pairwise_distinct`
8545 // (40cc4e5) on the top-level `SUPERVISOR_KEY_*` axis.
8546 let all = [
8547 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
8548 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
8549 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
8550 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
8551 ];
8552 for (i, a) in all.iter().enumerate() {
8553 for (j, b) in all.iter().enumerate() {
8554 if i != j {
8555 assert_ne!(
8556 a, b,
8557 "SUPERVISOR_ESTRATEGIA_* consts must be pairwise distinct \
8558 — got duplicate {a:?} at indices {i} and {j}",
8559 );
8560 }
8561 }
8562 }
8563 }
8564
8565 #[test]
8566 fn restart_strategy_display_routes_through_as_str_helper() {
8567 // The fail-before-pass-after pin on the first half of the
8568 // three-path convergence: pre-convergence the sibling
8569 // OTP-shape typed enum [`RestartStrategy`] carried a
8570 // [`std::fmt::Display`] surface via its
8571 // `#[discriminant(also_display)]` gen-platform derive route,
8572 // which arrived kebab-case as `"one-for-one"` /
8573 // `"one-for-all"` / `"rest-for-one"` /
8574 // `"simple-one-for-one"` while the wire format ran as
8575 // PascalCase `"OneForOne"` / `"OneForAll"` / `"RestForOne"` /
8576 // `"SimpleOneForOne"` through the un-`rename`d serde derive.
8577 // Every consumer reaching for a strategy byte-string past the
8578 // wire format had to pick between three paths
8579 // ([`RestartStrategy::as_str`], the `Serialize` derive's
8580 // serialized string, or `format!("{v}")` on the
8581 // discriminant-Display route), any two of which a future
8582 // variant rename or `#[serde(rename_all = "kebab-case")]`
8583 // attribute would silently desynchronize. Wiring
8584 // [`std::fmt::Display`] through [`RestartStrategy::as_str`]
8585 // closes the third path: every `format!("{v}")` call reaches
8586 // the same lifted [`crate::render::SUPERVISOR_ESTRATEGIA_*`]
8587 // const the wire format and the [`RestartStrategy::as_str`]
8588 // helper already route through, so a future variant rename
8589 // lands at exactly one place. Pin the routing here so a future
8590 // `impl std::fmt::Display for RestartStrategy`
8591 // reimplementation that hand-rolls the arms instead of
8592 // delegating to [`RestartStrategy::as_str`] fails at
8593 // caixa-core build time. Peer of the M3
8594 // `placement_strategy_display_routes_through_as_str_helper`
8595 // (cc8f749) which the M3 axis converged first.
8596 for &variant in RestartStrategy::ALL {
8597 assert_eq!(
8598 variant.to_string(),
8599 variant.as_str(),
8600 "RestartStrategy::{variant:?} Display must route through \
8601 RestartStrategy::as_str (single source of truth: the lifted \
8602 SUPERVISOR_ESTRATEGIA_* const the wire format also emits)"
8603 );
8604 }
8605 }
8606
8607 #[test]
8608 fn restart_strategy_display_matches_serialized_wire_byte_string() {
8609 // The fail-before-pass-after pin on the second half of the
8610 // three-path convergence: `Display` (user-facing text) agrees
8611 // byte-for-byte with the `Serialize` derive's wire format
8612 // (canonical camelCase-schema `SUPERVISOR_KEY_ESTRATEGIA`
8613 // scalar) on every variant. Pre-convergence the two paths
8614 // were structurally independent — a future
8615 // `#[serde(rename_all = "kebab-case")]` attribute on the
8616 // enum would silently rebrand the emitted wire scalar
8617 // (`one-for-one`, `one-for-all`, `rest-for-one`,
8618 // `simple-one-for-one`) while every consumer that
8619 // pretty-prints the strategy (the future wasm-operator's
8620 // per-supervisor sibling-restart-strategy diagnostic line,
8621 // the future `feira app graph` per-supervisor strategy line,
8622 // the future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
8623 // materializer's admission-webhook rejection body) would
8624 // still emit the PascalCase form the `as_str` / `Display`
8625 // route returns, with the mismatch surfacing at consumer
8626 // parse time / operator dispatch time far from the source
8627 // rebrand commit. Pin the two paths byte-for-byte here so any
8628 // future serde-attribute or variant-rename drift is a
8629 // caixa-core-build-time test failure at this call, not a
8630 // silent per-consumer dispatch miss. Peer of the M3
8631 // `placement_strategy_display_matches_serialized_wire_byte_string`
8632 // (cc8f749) which the M3 axis converged first.
8633 for &variant in RestartStrategy::ALL {
8634 let wire = serde_json::to_string(&variant).unwrap();
8635 let unquoted = wire
8636 .strip_prefix('"')
8637 .and_then(|s| s.strip_suffix('"'))
8638 .expect("serialized RestartStrategy is a JSON string");
8639 assert_eq!(
8640 variant.to_string(),
8641 unquoted,
8642 "RestartStrategy::{variant:?} Display byte-string must match the \
8643 Serialize derive's wire byte-string (three-path convergence: \
8644 Display + as_str + Serialize all resolve to the same \
8645 SUPERVISOR_ESTRATEGIA_* const)"
8646 );
8647 }
8648 }
8649
8650 #[test]
8651 fn restart_strategy_as_ref_str_routes_through_as_str_accessor() {
8652 // Fail-before-pass-after byte-parity pin on the lifted
8653 // `impl AsRef<str> for RestartStrategy` — asserts the
8654 // standard-library trait impl and the substrate-primitive
8655 // [`RestartStrategy::as_str`] `pub const fn` accessor resolve
8656 // to the same `&str` per instance across the four-arm
8657 // closed set, so any future silent detour that routes the
8658 // impl through a divergent projection (a per-arm inline
8659 // `match self { RestartStrategy::OneForOne => "OneForOne", … }`
8660 // re-inlining that opens a compile-time link to the un-lifted
8661 // arm-literal, a swap onto the kebab-case
8662 // [`gen_platform::Discriminant`] catalog identity that would
8663 // collide the wire axis with the dispatcher-catalog axis) trips
8664 // at caixa-core test time under `PartialEq` rather than at a
8665 // downstream `impl AsRef<str>`-bound consumer's silent split.
8666 // Sweeps every one of the four arms
8667 // [`RestartStrategy::ALL`] carries so no arm's projection is
8668 // covered only by the sibling wire-format `Serialize` derive
8669 // path. Peer of the sibling
8670 // [`crate::version::tests::caixa_version_as_ref_str_routes_through_as_str_accessor`]
8671 // (16d5c7e) `AsRef<str>`-byte-parity pin on the paired
8672 // top-level `:versao` typed newtype — the two pins together
8673 // cover the substrate primitive's `AsRef<str>` projection axis
8674 // on the paired newtype + closed-set-typed-enum surface.
8675 for &variant in RestartStrategy::ALL {
8676 assert_eq!(
8677 <RestartStrategy as AsRef<str>>::as_ref(&variant),
8678 variant.as_str(),
8679 "AsRef<str> impl on RestartStrategy::{variant:?} must \
8680 byte-equal RestartStrategy::as_str on the same instance \
8681 — divergence signals a silent detour off the substrate-\
8682 primitive accessor"
8683 );
8684 }
8685 }
8686
8687 #[test]
8688 fn restart_strategy_as_ref_str_routes_through_display_via_shared_accessor() {
8689 // Fail-before-pass-after byte-parity pin on the three-path
8690 // convergence discipline the M2 sibling-restart primitive now
8691 // carries on the `&str`-projection axis:
8692 // `<RestartStrategy as AsRef<str>>::as_ref(&s)` (the newly
8693 // lifted impl), `format!("{s}")` (the pre-existing
8694 // [`fmt::Display`] impl), and `s.as_str()` (the substrate-
8695 // primitive `pub const fn` accessor both trait impls delegate
8696 // through) must resolve to the same byte-string on every
8697 // instance across the four-arm closed set. Refuses any future
8698 // divergence between the two trait impls (a stray
8699 // [`fmt::Display::fmt`] rewrite that hand-rolls the arms
8700 // rather than delegating through the shared accessor; a
8701 // hypothetical `AsRef<str>` rewrite that inlines a per-arm
8702 // literal cascade) that would silently split the two
8703 // projection paths of the same closed-set typed enum. Mirrors
8704 // the sibling three-path-convergence discipline the peer
8705 // [`crate::CaixaVersion`] typed newtype carries on its
8706 // `AsRef<str>` / `Display` / `as_str` triple
8707 // (version.rs pin
8708 // `caixa_version_as_ref_str_routes_through_display_via_shared_accessor`,
8709 // 16d5c7e).
8710 for &variant in RestartStrategy::ALL {
8711 let via_as_ref: &str = <RestartStrategy as AsRef<str>>::as_ref(&variant);
8712 let via_display: String = format!("{variant}");
8713 let via_accessor: &str = variant.as_str();
8714 assert_eq!(via_as_ref, via_accessor);
8715 assert_eq!(via_display, via_accessor);
8716 assert_eq!(via_as_ref, via_display.as_str());
8717 }
8718 }
8719
8720 #[test]
8721 fn restart_strategy_all_enumerates_every_variant_exactly_once() {
8722 // Fail-before-pass-after pin on the [`RestartStrategy::ALL`]
8723 // exhaustive-iteration surface: every variant appears exactly
8724 // once, and the slice length matches the arm count of the
8725 // closed set. Every consumer that walks the accepted-strategy
8726 // set (a future `feira supervisor --estrategia …` CLI-side
8727 // arg-parse's "did you mean" hint, a future M4 admission-
8728 // webhook's rejection body naming the accepted-`:estrategia`
8729 // list, the [`RestartStrategy::from_wire`] reverse-projection
8730 // consumers that iterate the accept-set for diagnostic
8731 // rendering) reads through this slice, so a future arm addition
8732 // that grows the enum but forgets to grow [`Self::ALL`]
8733 // silently truncates every downstream consumer's accept-set at
8734 // the same pre-addition boundary — this pin fails at caixa-core
8735 // build time on the pairwise-distinct + arm-count invariants.
8736 //
8737 // Peer of the sibling [`crate::CaixaKind::ALL`] (6b1f4fb) /
8738 // [`crate::aplicacao::PlacementStrategy::ALL`] (18c7342) /
8739 // [`crate::aplicacao::RateLimitUnit::ALL`] (6bce03d) /
8740 // [`crate::dep::DepList::ALL`] (45ee563) exhaustive-iteration
8741 // pins on the peer closed-set typed-enum axes.
8742 let all: &[RestartStrategy] = RestartStrategy::ALL;
8743 assert_eq!(
8744 all.len(),
8745 4,
8746 "RestartStrategy::ALL must enumerate every variant of the \
8747 four-arm closed set (OneForOne, OneForAll, RestForOne, \
8748 SimpleOneForOne); got {all:?}"
8749 );
8750 for (i, a) in all.iter().enumerate() {
8751 for (j, b) in all.iter().enumerate() {
8752 if i != j {
8753 assert_ne!(
8754 a, b,
8755 "RestartStrategy::ALL must carry every variant exactly \
8756 once — got duplicate {a:?} at indices {i} and {j}"
8757 );
8758 }
8759 }
8760 }
8761 for variant in [
8762 RestartStrategy::OneForOne,
8763 RestartStrategy::OneForAll,
8764 RestartStrategy::RestForOne,
8765 RestartStrategy::SimpleOneForOne,
8766 ] {
8767 assert!(
8768 all.contains(&variant),
8769 "RestartStrategy::ALL must contain {variant:?} — a future arm \
8770 addition that grows the enum but forgets to grow the ALL slice \
8771 silently truncates every downstream consumer's accept-set at \
8772 the pre-addition boundary"
8773 );
8774 }
8775 }
8776
8777 #[test]
8778 fn restart_strategy_wire_names_covers_every_arm() {
8779 // Load-bearing pin on the substrate-canonical
8780 // [`RestartStrategy::WIRE_NAMES`] exhaustive accept-set roster
8781 // on the `PascalCase` wire byte-string axis: every variant of
8782 // the sibling [`RestartStrategy::ALL`] exhaustive-iteration
8783 // surface must project through [`RestartStrategy::as_str`] onto
8784 // an entry the [`RestartStrategy::WIRE_NAMES`] roster carries,
8785 // and the roster's length must byte-equal
8786 // `RestartStrategy::ALL.len()` so a silent skew between the
8787 // [`RestartStrategy::as_str`] match's arm-set and the roster's
8788 // arm-set trips here at caixa-core test time rather than at a
8789 // downstream M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
8790 // admission-webhook rejection body's wire-form `:estrategia`
8791 // accepted-set enumeration miss / a `feira supervisor
8792 // --estrategia …` "did you mean" hint drift / a future
8793 // wasm-operator per-reconcile-step diagnostic log line's
8794 // accepted-wire-form enumeration miss. A future arm addition
8795 // (an OTP-`rest_for_all` arm the theory
8796 // [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
8797 // might reach for once the four canonical OTP strategies stop
8798 // covering the substrate's discovered load-shape) extends
8799 // [`RestartStrategy::ALL`] as a single edit and this pin
8800 // sweeps the new arm by iteration; the paired
8801 // [`RestartStrategy::WIRE_NAMES`] roster must grow in lockstep
8802 // or this assertion trips. Every entry is further pinned to
8803 // open with an ASCII uppercase byte so a silent collapse of
8804 // the wire-form axis with the peer kebab-case
8805 // dispatcher-catalog axis (an entry byte-identical to a
8806 // sibling [`Self::discriminant`] kebab byte-string that would
8807 // let a wire-axis consumer accept the dispatcher-catalog
8808 // vocabulary) trips here rather than at a downstream K8s-CR
8809 // round-trip miss.
8810 //
8811 // Peer of the sibling
8812 // [`crate::kind::tests::caixa_kind_wire_names_covers_every_arm`]
8813 // (bd708bd) pin on the top-level typed-kind discriminator's
8814 // `PascalCase` wire byte-string axis, and of the sibling
8815 // [`crate::upgrade::tests::upgrade_instruction_wire_forms_covers_every_arm`]
8816 // (cc42c0e) /
8817 // [`crate::upgrade::tests::upgrade_instruction_lisp_forms_covers_every_arm`]
8818 // (1898d77) pins on the OTP-appup discriminator's two-axis
8819 // roster split — the same closed-set exhaustive-roster
8820 // coverage discipline extended here onto the first M2
8821 // OTP-shape sibling-restart closed-set typed enum.
8822 //
8823 // Fail-before-pass-after locally verified by mutating one arm
8824 // of the paired [`crate::render::SUPERVISOR_ESTRATEGIA_*`]
8825 // const family (e.g. dropping the trailing `e` from
8826 // `"OneForOne"` → `"OneForOn"`) — the length pin still passes
8827 // but the `contains` check fires on the mutated arm; and by
8828 // shortening the roster to three entries — the length pin
8829 // fires first.
8830 assert_eq!(
8831 RestartStrategy::WIRE_NAMES.len(),
8832 RestartStrategy::ALL.len(),
8833 "RestartStrategy::WIRE_NAMES.len() must byte-equal \
8834 RestartStrategy::ALL.len() — a mismatch means the roster \
8835 and the enum's arm-set have drifted; downstream consumers \
8836 that fan through both will silently disagree on the \
8837 accepted arm-set"
8838 );
8839 for &variant in RestartStrategy::ALL {
8840 let wire = variant.as_str();
8841 assert!(
8842 RestartStrategy::WIRE_NAMES.contains(&wire),
8843 "RestartStrategy::{variant:?}.as_str() = {wire:?} must \
8844 be a member of RestartStrategy::WIRE_NAMES — the \
8845 emitter and the roster have drifted out of lockstep"
8846 );
8847 }
8848 for tag in RestartStrategy::WIRE_NAMES {
8849 let first = tag.chars().next().unwrap_or_else(|| {
8850 panic!(
8851 "RestartStrategy::WIRE_NAMES entry {tag:?} must be \
8852 a non-empty PascalCase byte-string"
8853 )
8854 });
8855 assert!(
8856 first.is_ascii_uppercase(),
8857 "RestartStrategy::WIRE_NAMES entry {tag:?} must open \
8858 with an ASCII uppercase byte (PascalCase wire form) — \
8859 a lowercase entry would collide the wire-form axis \
8860 with the peer kebab-case dispatcher-catalog axis \
8861 [`RestartStrategy::discriminant`] serves"
8862 );
8863 }
8864 }
8865
8866 #[test]
8867 fn restart_strategy_from_wire_accepts_every_lifted_constant() {
8868 // Fail-before-pass-after pin on the forward accept-set of the
8869 // [`RestartStrategy::from_wire`] reverse projection: every
8870 // canonical [`crate::render::SUPERVISOR_ESTRATEGIA_*`]
8871 // constant the [`RestartStrategy::as_str`] emitter walks parses
8872 // back to its paired variant. Any future arm addition that
8873 // grows the emitter's `as_str` match but forgets to grow the
8874 // parser's `from_wire` match silently splits the two halves of
8875 // the round-trip — the wire byte-string one non-serde consumer
8876 // parses from the one the emitter wrote — with the failure
8877 // surfacing at parse time far from the rebrand commit. Pinning
8878 // the four-arm accept-set here catches the drift at caixa-core
8879 // build time.
8880 //
8881 // Peer of the sibling [`crate::CaixaKind::from_wire`] (2aa6d23)
8882 // + [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342)
8883 // accept-set pins on the peer closed-set typed-enum `str → Self`
8884 // axes.
8885 for (wire, expected) in [
8886 (
8887 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
8888 RestartStrategy::OneForOne,
8889 ),
8890 (
8891 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
8892 RestartStrategy::OneForAll,
8893 ),
8894 (
8895 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
8896 RestartStrategy::RestForOne,
8897 ),
8898 (
8899 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
8900 RestartStrategy::SimpleOneForOne,
8901 ),
8902 ] {
8903 let parsed = RestartStrategy::from_wire(wire).unwrap_or_else(|| {
8904 panic!(
8905 "RestartStrategy::from_wire({wire:?}) must accept every \
8906 SUPERVISOR_ESTRATEGIA_* constant — got None for the \
8907 lifted canonical byte-string that RestartStrategy::{expected:?} \
8908 serializes as under SUPERVISOR_KEY_ESTRATEGIA"
8909 )
8910 });
8911 assert_eq!(
8912 parsed, expected,
8913 "RestartStrategy::from_wire({wire:?}) must return \
8914 RestartStrategy::{expected:?}; got RestartStrategy::{parsed:?}"
8915 );
8916 }
8917 }
8918
8919 #[test]
8920 fn restart_strategy_from_wire_round_trips_through_as_str() {
8921 // Fail-before-pass-after pin on the closed round-trip between
8922 // the forward [`RestartStrategy::as_str`] emitter and the
8923 // reverse [`RestartStrategy::from_wire`] parser: for every
8924 // variant in [`RestartStrategy::ALL`], parsing the emitter's
8925 // output must return exactly the same variant. Any per-arm
8926 // divergence — a future arm added to `as_str` but not
8927 // `from_wire`, an accidental copy-paste flip in one but not
8928 // the other — silently splits the emit and parse halves and
8929 // the failure surfaces at consumer parse time far from the
8930 // drift site. The `ALL`-iterating shape means a future arm
8931 // addition picks up the coverage by construction.
8932 //
8933 // Peer of the sibling
8934 // [`crate::aplicacao::tests::placement_strategy_from_wire_round_trips_through_as_str`]
8935 // (18c7342) round-trip pin on
8936 // [`crate::aplicacao::PlacementStrategy::from_wire`] and
8937 // [`crate::kind::tests::caixa_kind_wire_round_trips_through_from_wire`]
8938 // (6b1f4fb) round-trip pin on [`crate::CaixaKind::from_wire`].
8939 for &variant in RestartStrategy::ALL {
8940 let wire = variant.as_str();
8941 let parsed = RestartStrategy::from_wire(wire).unwrap_or_else(|| {
8942 panic!(
8943 "RestartStrategy::from_wire(RestartStrategy::{variant:?}.as_str()) \
8944 must be Some({variant:?}) — the two halves of the round-trip \
8945 dispatch on the same lifted SUPERVISOR_ESTRATEGIA_* consts; \
8946 got None on wire byte-string {wire:?}"
8947 )
8948 });
8949 assert_eq!(
8950 parsed, variant,
8951 "RestartStrategy::from_wire(RestartStrategy::{variant:?}.as_str()) \
8952 must round-trip to the same variant; got {parsed:?}"
8953 );
8954 }
8955 }
8956
8957 #[test]
8958 fn restart_strategy_from_wire_rejects_unknown_byte_strings() {
8959 // Fail-before-pass-after pin on the closed-set refusal
8960 // discipline of [`RestartStrategy::from_wire`]: every
8961 // byte-string outside the four-arm accept-set returns `None`
8962 // rather than silently collapsing onto the [`Default`]
8963 // (`OneForOne`) arm or an arbitrary neighbor. The refusal set
8964 // exercised here sweeps the load-bearing drift shapes: the
8965 // empty string (a stripped serde-attribute drift), all-
8966 // whitespace strings (the canonical text-editor accidental
8967 // padding shape), the kebab-case dispatcher-catalog identities
8968 // (`"one-for-one"` / `"one-for-all"` / `"rest-for-one"` /
8969 // `"simple-one-for-one"` — the [`gen_platform::FromStrKind`]-
8970 // derived [`std::str::FromStr`] accept-set, which parses the
8971 // *other* axis of this enum's two-axis split and must not leak
8972 // into the `from_wire` PascalCase-wire accept-set), the
8973 // lowercased single-word forms (`"oneforone"`), the padded
8974 // canonical scalar (`" OneForOne "`), the trailing-newline
8975 // shapes (`"OneForOne\n"`), and neighboring-but-unknown arms
8976 // (`"AllForOne"` — the canonical typo direction).
8977 //
8978 // Peer of the sibling
8979 // [`crate::kind::tests::caixa_kind_from_wire_rejects_unknown_byte_strings`]
8980 // (2aa6d23) +
8981 // [`crate::aplicacao::tests::placement_strategy_from_wire_rejects_unknown_byte_strings`]
8982 // (18c7342) refusal pins on the peer closed-set typed-enum
8983 // axes.
8984 for bad in [
8985 "",
8986 " ",
8987 "\n",
8988 "\t",
8989 "one-for-one",
8990 "one-for-all",
8991 "rest-for-one",
8992 "simple-one-for-one",
8993 "oneforone",
8994 "OneForOnes",
8995 "one_for_one",
8996 "one for one",
8997 "ONEFORONE",
8998 "OneForOne ",
8999 " OneForOne",
9000 " SimpleOneForOne ",
9001 "OneForOne\n",
9002 "restforone",
9003 "REST_FOR_ONE",
9004 "AllForOne",
9005 "Simple",
9006 "?",
9007 ] {
9008 assert!(
9009 RestartStrategy::from_wire(bad).is_none(),
9010 "RestartStrategy::from_wire({bad:?}) must return None — the \
9011 parser's accept-set is exactly the four RestartStrategy::as_str \
9012 outputs (OneForOne, OneForAll, RestForOne, SimpleOneForOne), \
9013 and this byte-string is outside that closed set"
9014 );
9015 }
9016 }
9017
9018 #[test]
9019 fn restart_strategy_from_wire_matches_serialize_derive_wire_byte_string() {
9020 // Fail-before-pass-after pin on the fourth path of the four-path
9021 // convergence: `from_wire` (the reverse projection) inverts the
9022 // `Serialize` derive's wire byte-string on every variant.
9023 // Together with the pre-existing three-path convergence
9024 // (`Display` + `as_str` + `Serialize` all resolve to the same
9025 // lifted [`crate::render::SUPERVISOR_ESTRATEGIA_*`] const,
9026 // pinned by
9027 // [`restart_strategy_display_matches_serialized_wire_byte_string`])
9028 // this closes the round-trip: the wire byte-string the
9029 // `Serialize` derive emits parses back to the same variant
9030 // through `from_wire`, so any future serde-attribute or variant-
9031 // rename drift on the emit half now surfaces as a matched drift
9032 // on the parse half at caixa-core build time — the two halves
9033 // migrate as a unit through the lifted consts on any future
9034 // rename, and the round-trip cannot silently split.
9035 //
9036 // Peer of the sibling
9037 // [`crate::aplicacao::tests::placement_strategy_from_wire_matches_serialize_derive_wire_byte_string`]
9038 // (18c7342) wire-format pin on
9039 // [`crate::aplicacao::PlacementStrategy::from_wire`].
9040 for &variant in RestartStrategy::ALL {
9041 let wire = serde_json::to_string(&variant).unwrap();
9042 let unquoted = wire
9043 .strip_prefix('"')
9044 .and_then(|s| s.strip_suffix('"'))
9045 .expect("serialized RestartStrategy is a JSON string");
9046 let parsed = RestartStrategy::from_wire(unquoted).unwrap_or_else(|| {
9047 panic!(
9048 "RestartStrategy::from_wire({unquoted:?}) must accept the \
9049 Serialize derive's wire byte-string for \
9050 RestartStrategy::{variant:?} — the four-path convergence \
9051 (Display + as_str + Serialize + from_wire) resolves through \
9052 the same lifted SUPERVISOR_ESTRATEGIA_* const; got None"
9053 )
9054 });
9055 assert_eq!(
9056 parsed, variant,
9057 "RestartStrategy::from_wire of the Serialize derive's wire \
9058 byte-string for RestartStrategy::{variant:?} must round-trip \
9059 to the same variant; got {parsed:?}"
9060 );
9061 }
9062 }
9063
9064 #[test]
9065 fn restart_strategy_try_from_str_routes_through_from_wire_accessor() {
9066 // Fail-before-pass-after byte-parity pin on the newly lifted
9067 // `impl TryFrom<&str> for RestartStrategy` — asserts the standard-
9068 // library trait impl and the substrate-primitive
9069 // [`RestartStrategy::from_wire`] `Option<Self>` accessor resolve to
9070 // the same four-arm accept-set across every arm the exhaustive
9071 // [`RestartStrategy::ALL`] slice enumerates. Any future silent
9072 // detour that routes the trait impl through a divergent projection
9073 // (a per-arm inline `match s { "OneForOne" => Ok(Self::OneForOne),
9074 // … }` re-inlining that opens a compile-time link to the un-
9075 // lifted arm-literal, a hypothetical `#[serde(rename_all = "…")]`
9076 // attribute drift that silently splits the wire byte-string from
9077 // every consumer that reaches for this typed dispatch, an
9078 // accidental swap onto the kebab-case dispatcher-catalog axis the
9079 // pre-existing [`std::str::FromStr`] impl parses through and which
9080 // would collide the two-axis wire/catalog split the sibling
9081 // [`RestartStrategy::from_wire`] doc block makes load-bearing)
9082 // trips at caixa-core test time under `assert_eq!` rather than at
9083 // a downstream `impl TryFrom<&str>`-bound consumer's silent split.
9084 // Sweeps every one of the four arms [`RestartStrategy::ALL`]
9085 // carries so no arm's projection is covered only by the sibling
9086 // method-named `from_wire` path. Peer of the sibling
9087 // [`crate::kind::tests::caixa_kind_try_from_str_routes_through_from_wire_accessor`]
9088 // (3c83606),
9089 // [`crate::dialeto::tests::caixa_dialeto_try_from_str_routes_through_from_wire_accessor`]
9090 // (bf33136), and the M3
9091 // [`crate::aplicacao::tests::placement_strategy_try_from_str_routes_through_from_wire_accessor`]
9092 // (6fd00cd) — extends the trait-idiomatic reverse-projection axis
9093 // onto the first M2-OTP-shape closed-set typed enum on the caixa
9094 // surface.
9095 for &variant in RestartStrategy::ALL {
9096 let wire = variant.as_str();
9097 assert_eq!(
9098 <RestartStrategy as TryFrom<&str>>::try_from(wire),
9099 Ok(variant),
9100 "TryFrom<&str> impl on RestartStrategy must round-trip \
9101 RestartStrategy::{variant:?}.as_str() = {wire:?} back to \
9102 Ok(RestartStrategy::{variant:?}) — divergence from \
9103 RestartStrategy::from_wire signals a silent detour off \
9104 the substrate-primitive accessor"
9105 );
9106 assert_eq!(
9107 <RestartStrategy as TryFrom<&str>>::try_from(wire).ok(),
9108 RestartStrategy::from_wire(wire),
9109 "TryFrom<&str> ok()-projection on {wire:?} must byte-equal \
9110 RestartStrategy::from_wire on the same input"
9111 );
9112 }
9113 }
9114
9115 #[test]
9116 fn restart_strategy_try_from_str_rejects_unknown_byte_strings() {
9117 // Rejection witness on the `impl TryFrom<&str> for
9118 // RestartStrategy` — sweeps a candidate set of byte-strings
9119 // outside the four-arm PascalCase wire accept-set the sibling
9120 // [`RestartStrategy::as_str`] emits and asserts every one lands on
9121 // `Err(())`, so a future accidental widening of the trait impl's
9122 // accept-set (a stray additional
9123 // `_ if s.eq_ignore_ascii_case("OneForOne") => Ok(…)` case-fold
9124 // path, a silent inclusion of the kebab-case dispatcher-catalog
9125 // byte-string the pre-existing [`std::str::FromStr`] impl the
9126 // [`gen_platform::FromStrKind`] derive installs parses onto the
9127 // wire axis — which would collide the two-axis
9128 // wire/dispatcher-catalog split the sibling
9129 // [`RestartStrategy::from_wire`] doc block makes load-bearing —
9130 // an English-rebrand or plural-arm silent alias that would
9131 // widen the wire accept-set past the OTP-canonical four) trips at
9132 // caixa-core test time. The candidate set includes the empty
9133 // string, whitespace-only padding, the kebab-case dispatcher-
9134 // catalog byte-strings on the sibling axis (a caller who confuses
9135 // the two axes trips here rather than at a downstream consumer's
9136 // silent reject), a lowercase / uppercase / mixed-case fold of
9137 // each PascalCase arm (a caller who assumes case-fold acceptance
9138 // trips here), leading/trailing whitespace padding, the trailing-
9139 // newline shape, quote-wrapped candidates, and a residual set of
9140 // plausible-but-wrong English rebrand candidates. Peer of the
9141 // sibling
9142 // [`crate::kind::tests::caixa_kind_try_from_str_rejects_unknown_byte_strings`]
9143 // (3c83606) and
9144 // [`crate::aplicacao::tests::placement_strategy_try_from_str_rejects_unknown_byte_strings`]
9145 // (6fd00cd) rejection witnesses.
9146 let rejected: &[&str] = &[
9147 "",
9148 " ",
9149 "\n",
9150 "\t",
9151 "one-for-one",
9152 "one-for-all",
9153 "rest-for-one",
9154 "simple-one-for-one",
9155 "oneforone",
9156 "one_for_one",
9157 "OneForOnes",
9158 "ONEFORONE",
9159 "oneforall",
9160 "restforone",
9161 "simpleoneforone",
9162 "OneForOne ",
9163 " OneForOne",
9164 " OneForAll ",
9165 "OneForOne\n",
9166 "RestForOne\t",
9167 "OneForEach",
9168 "AllForOne",
9169 "one for one",
9170 "\"OneForOne\"",
9171 "?",
9172 ];
9173 for &input in rejected {
9174 assert_eq!(
9175 <RestartStrategy as TryFrom<&str>>::try_from(input),
9176 Err(()),
9177 "TryFrom<&str> impl on RestartStrategy must reject the \
9178 non-wire byte-string {input:?} — silent acceptance signals \
9179 an accept-set widening off the paired \
9180 RestartStrategy::from_wire resolver"
9181 );
9182 }
9183 }
9184
9185 #[test]
9186 fn restart_strategy_try_from_str_and_from_wire_partition_the_accept_set() {
9187 // Cross-axis partition pin: the paired `TryFrom<&str>` and
9188 // `from_wire` reverse projections must resolve identically on
9189 // *every* input, not just the ones [`RestartStrategy::ALL`]
9190 // enumerates. Sweeps a mixed candidate set spanning accepted
9191 // (four-arm PascalCase wire byte-strings) and rejected (kebab-case
9192 // dispatcher-catalog byte-strings, empty, whitespace-padded,
9193 // quoted, English-rebrand candidates) inputs and asserts the
9194 // trait's `Result::ok()` projection byte-equals the method-named
9195 // resolver's `Option<Self>` return-shape on each, locking the two
9196 // paths together by construction so any future detour (a stray
9197 // `try_from` special-case that widens or narrows the accept-set
9198 // outside the paired `from_wire` resolver, an accidental swap
9199 // onto the kebab-case [`std::str::FromStr`] impl the
9200 // [`gen_platform::FromStrKind`] derive installs on the sibling
9201 // dispatcher-catalog axis) trips at caixa-core test time. Peer of
9202 // the sibling
9203 // [`crate::kind::tests::caixa_kind_try_from_str_and_from_wire_partition_the_accept_set`]
9204 // pin — extends the round-trip discipline onto the M2-OTP-shape
9205 // sibling-restart axis.
9206 let candidates: &[&str] = &[
9207 "OneForOne",
9208 "OneForAll",
9209 "RestForOne",
9210 "SimpleOneForOne",
9211 "",
9212 "one-for-one",
9213 "one-for-all",
9214 "rest-for-one",
9215 "simple-one-for-one",
9216 "oneforone",
9217 "unknown",
9218 "OneForOne ",
9219 " OneForOne",
9220 "\"OneForOne\"",
9221 "OneForEach",
9222 "?",
9223 ];
9224 for &input in candidates {
9225 let via_trait: Option<RestartStrategy> =
9226 <RestartStrategy as TryFrom<&str>>::try_from(input).ok();
9227 let via_method: Option<RestartStrategy> = RestartStrategy::from_wire(input);
9228 assert_eq!(
9229 via_trait, via_method,
9230 "TryFrom<&str> and from_wire must resolve identically on \
9231 input {input:?} — divergence signals the two reverse-\
9232 projection paths have drifted onto different accept-sets"
9233 );
9234 }
9235 }
9236
9237 #[test]
9238 fn restart_strategy_from_into_static_str_routes_through_as_str_accessor() {
9239 // Fail-before-pass-after byte-parity pin on the newly lifted
9240 // `impl From<RestartStrategy> for &'static str` — asserts the
9241 // standard-library trait impl and the substrate-primitive
9242 // [`RestartStrategy::as_str`] `pub const fn` accessor resolve to
9243 // the same four-arm emit-set across every arm the exhaustive
9244 // [`RestartStrategy::ALL`] slice enumerates. Any future silent
9245 // detour that routes the trait impl through a divergent
9246 // projection (a per-arm inline `match strategy { OneForOne =>
9247 // "OneForOne", … }` re-inlining that opens a compile-time link to
9248 // the un-lifted arm-literal, an accidental swap onto the sibling
9249 // kebab-case [`Self::discriminant`] dispatcher-catalog axis that
9250 // would collide the two-axis wire/catalog split the sibling
9251 // [`RestartStrategy::from_wire`] doc block makes load-bearing) trips
9252 // at caixa-core test time under `assert_eq!` rather than at a
9253 // downstream `impl Into<&'static str>`-bound consumer's silent
9254 // split. Sweeps every one of the four arms
9255 // [`RestartStrategy::ALL`] carries so no arm's projection is
9256 // covered only by the sibling method-named `as_str` /
9257 // [`std::fmt::Display`] / [`AsRef<str>`] paths. Materializes the
9258 // `<&'static str as From<RestartStrategy>>::from` output in a
9259 // `const`-shape binding to make the `'static` lifetime promise a
9260 // build-time invariant — a future accidental downgrade of any of
9261 // the four arms' [`crate::render::SUPERVISOR_ESTRATEGIA_*`]
9262 // constants to a non-`&'static str` (a `String::leak()`-produced
9263 // return, a `Box::leak`-cast) trips at caixa-core build time
9264 // rather than at a downstream `'static`-bound consumer.
9265 const ONE_FOR_ONE: &str = RestartStrategy::OneForOne.as_str();
9266 const ONE_FOR_ALL: &str = RestartStrategy::OneForAll.as_str();
9267 const REST_FOR_ONE: &str = RestartStrategy::RestForOne.as_str();
9268 const SIMPLE_ONE_FOR_ONE: &str = RestartStrategy::SimpleOneForOne.as_str();
9269 for &variant in RestartStrategy::ALL {
9270 let via_trait: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9271 let via_method: &'static str = variant.as_str();
9272 assert_eq!(
9273 via_trait, via_method,
9274 "From<RestartStrategy> for &'static str impl must round-trip \
9275 RestartStrategy::{variant:?} to the same lifted \
9276 SUPERVISOR_ESTRATEGIA_* const RestartStrategy::as_str returns — \
9277 divergence signals a silent detour off the substrate-primitive \
9278 accessor"
9279 );
9280 let via_into: &'static str = variant.into();
9281 assert_eq!(
9282 via_into, via_method,
9283 "Into<&'static str>::into on RestartStrategy::{variant:?} must \
9284 byte-equal RestartStrategy::as_str on the same input — the \
9285 blanket-derived Into shape must resolve to the same as_str \
9286 dispatch as the explicit From impl"
9287 );
9288 }
9289 assert_eq!(
9290 [ONE_FOR_ONE, ONE_FOR_ALL, REST_FOR_ONE, SIMPLE_ONE_FOR_ONE],
9291 [
9292 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
9293 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
9294 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
9295 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
9296 ],
9297 "const-context RestartStrategy::as_str must resolve to the four \
9298 lifted SUPERVISOR_ESTRATEGIA_* consts — a future accidental \
9299 downgrade of any arm to a non-const or non-static byte-string \
9300 breaks the `&'static str`-lifetime promise the paired \
9301 From<RestartStrategy> for &'static str impl carries by \
9302 construction"
9303 );
9304 }
9305
9306 #[test]
9307 fn restart_strategy_from_into_static_str_and_as_str_partition_the_emit_set() {
9308 // Cross-axis partition pin: the paired trait-idiomatic
9309 // `From<RestartStrategy> for &'static str` forward projection and
9310 // the method-named [`RestartStrategy::as_str`] forward projection
9311 // must resolve identically on *every* arm, not just the ones
9312 // named in the primary byte-parity pin above. Sweeps every
9313 // [`RestartStrategy::ALL`] arm and asserts the trait's `From::from`
9314 // output byte-equals the method-named accessor's return-value on
9315 // each, locking the two forward-projection paths together by
9316 // construction so any future detour (a stray `From` special-case
9317 // that lands on a divergent per-arm literal outside the paired
9318 // `as_str` dispatch, a hypothetical rebrand touching one axis
9319 // without the other) trips at caixa-core test time. Peer of the
9320 // sibling reverse-projection partition pin
9321 // [`restart_strategy_try_from_str_and_from_wire_partition_the_accept_set`]
9322 // — extends the round-trip discipline onto the trait-idiomatic
9323 // *forward* axis, closing the two-way `Self ↔ &'static str`
9324 // round-trip on the trait-idiomatic pair
9325 // (`From<Self> for &'static str` + `TryFrom<&str> for Self`) as
9326 // well as the pre-existing method-named pair
9327 // (`as_str` + `from_wire`).
9328 for &variant in RestartStrategy::ALL {
9329 let via_trait: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9330 let via_method: &'static str = variant.as_str();
9331 assert_eq!(
9332 via_trait, via_method,
9333 "From<RestartStrategy> for &'static str and \
9334 RestartStrategy::as_str must resolve identically on \
9335 RestartStrategy::{variant:?} — divergence signals the \
9336 two forward-projection paths have drifted onto different \
9337 emit-sets"
9338 );
9339 }
9340 // Round-trip witness: every arm's forward `From` output re-parses
9341 // through the paired trait-idiomatic reverse `TryFrom<&str>` back
9342 // to the original variant. Closes the two-way `RestartStrategy ↔
9343 // &'static str` round-trip on the trait-idiomatic axis pair,
9344 // mirroring the pre-existing method-named `as_str` + `from_wire`
9345 // round-trip on the substrate-primitive axis pair.
9346 for &variant in RestartStrategy::ALL {
9347 let emitted: &'static str = variant.into();
9348 let re_parsed: Result<RestartStrategy, ()> =
9349 <RestartStrategy as TryFrom<&str>>::try_from(emitted);
9350 assert_eq!(
9351 re_parsed,
9352 Ok(variant),
9353 "trait-idiomatic axis pair must round-trip \
9354 RestartStrategy::{variant:?} through `.into::<&'static \
9355 str>()` and back through `TryFrom<&str>` — a break signals \
9356 the forward-emit and reverse-parse axes have drifted onto \
9357 different vocabularies"
9358 );
9359 }
9360 }
9361
9362 #[test]
9363 fn restart_strategy_from_borrowed_into_static_str_routes_through_as_str_accessor() {
9364 // Fail-before-pass-after byte-parity pin on the newly lifted
9365 // `impl From<&RestartStrategy> for &'static str` — asserts the
9366 // borrowed-input standard-library trait impl and the substrate-
9367 // primitive [`RestartStrategy::as_str`] `pub const fn` accessor
9368 // resolve to the same four-arm emit-set across every arm the
9369 // exhaustive [`RestartStrategy::ALL`] slice enumerates. Rust's
9370 // `From` trait does not auto-derive the borrowed-input sibling
9371 // from a paired owned-input impl (no `impl<T, U> From<&T> for U
9372 // where T: Copy, U: From<T>` blanket in `core`), so the
9373 // borrowed-input axis is a distinct trait-idiomatic surface
9374 // that a `.iter().map(Into::into)` shape over
9375 // [`RestartStrategy::ALL`] (whose iterator yields
9376 // `&RestartStrategy`, not `RestartStrategy`) reaches through
9377 // this impl and no other — the paired owned-input
9378 // [`From<RestartStrategy>`] impl requires an explicit
9379 // `.copied()` / dereference before the trait fires.
9380 // Materializes the `<&'static str as
9381 // From<&RestartStrategy>>::from` output in a `const`-shape
9382 // binding to make the `'static` lifetime promise a build-time
9383 // invariant.
9384 const ONE_FOR_ONE: &str = RestartStrategy::OneForOne.as_str();
9385 const ONE_FOR_ALL: &str = RestartStrategy::OneForAll.as_str();
9386 const REST_FOR_ONE: &str = RestartStrategy::RestForOne.as_str();
9387 const SIMPLE_ONE_FOR_ONE: &str = RestartStrategy::SimpleOneForOne.as_str();
9388 for variant in RestartStrategy::ALL {
9389 let via_trait: &'static str = <&'static str as From<&RestartStrategy>>::from(variant);
9390 let via_method: &'static str = variant.as_str();
9391 assert_eq!(
9392 via_trait, via_method,
9393 "From<&RestartStrategy> for &'static str impl must \
9394 round-trip &RestartStrategy::{variant:?} to the same \
9395 lifted SUPERVISOR_ESTRATEGIA_* const \
9396 RestartStrategy::as_str returns — divergence signals a \
9397 silent detour off the substrate-primitive accessor"
9398 );
9399 let via_into: &'static str = variant.into();
9400 assert_eq!(
9401 via_into, via_method,
9402 "Into<&'static str>::into on &RestartStrategy::{variant:?} \
9403 must byte-equal RestartStrategy::as_str on the same input — \
9404 the blanket-derived Into shape must resolve to the same \
9405 as_str dispatch as the explicit From impl"
9406 );
9407 }
9408 assert_eq!(
9409 [ONE_FOR_ONE, ONE_FOR_ALL, REST_FOR_ONE, SIMPLE_ONE_FOR_ONE],
9410 [
9411 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ONE,
9412 crate::render::SUPERVISOR_ESTRATEGIA_ONE_FOR_ALL,
9413 crate::render::SUPERVISOR_ESTRATEGIA_REST_FOR_ONE,
9414 crate::render::SUPERVISOR_ESTRATEGIA_SIMPLE_ONE_FOR_ONE,
9415 ],
9416 "const-context RestartStrategy::as_str must resolve to the \
9417 four lifted SUPERVISOR_ESTRATEGIA_* consts — the borrowed-\
9418 input From<&RestartStrategy> for &'static str impl inherits \
9419 its `'static` lifetime promise from the same accessor the \
9420 owned-input sibling routes through"
9421 );
9422 }
9423
9424 #[test]
9425 fn restart_strategy_from_owned_and_borrowed_into_static_str_agree_on_every_arm() {
9426 // Cross-axis partition pin: the paired trait-idiomatic
9427 // owned-input `From<RestartStrategy> for &'static str` (523157d
9428 // campaign-shape) and borrowed-input `From<&RestartStrategy> for
9429 // &'static str` (this lift) forward projections must resolve
9430 // identically on every arm, locking the two input-shape paths
9431 // together so any future detour trips at caixa-core test time.
9432 // Then a witness that a `.iter().map(Into::into)` pipe over
9433 // [`RestartStrategy::ALL`] (whose iterator yields
9434 // `&RestartStrategy`) materializes the four-arm accept-set
9435 // through the borrowed-input axis alone — the exact shape a
9436 // future wasm-operator per-supervisor sibling-restart-strategy
9437 // diagnostic line, a future substrate-wide per-arm diagnostic
9438 // column, or a
9439 // `HashMap::<&'static str, RestartStrategy>::from_iter(
9440 // RestartStrategy::ALL.iter().map(|s| (s.into(), *s)))`-style
9441 // per-strategy lookup reaches through — closing the two-way
9442 // owned/borrowed input-shape symmetry on the forward-projection
9443 // trait-idiomatic axis. Peer of the sibling
9444 // [`crate::dep::tests::dep_list_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
9445 // (64aa742) /
9446 // [`crate::kind::tests::caixa_kind_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
9447 // (5ab993a) /
9448 // [`crate::dialeto::tests::caixa_dialeto_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
9449 // (807b0b5) partition pins on the sibling closed-set typed-enum
9450 // discriminator axes — extends the borrowed-input axis
9451 // discipline onto the first M2 OTP-shape sibling-restart
9452 // closed-set typed enum on the caixa surface. Also closes the
9453 // direct two-way `&Self → &'static str → Self` round-trip via
9454 // the paired [`TryFrom<&str>`] axis — unlike the peer
9455 // [`crate::CaixaKind`] axis pair (whose forward `From` emits
9456 // lowercase Portuguese diagnostic bytes while the reverse
9457 // `TryFrom` parses `PascalCase` wire bytes, forcing the round-
9458 // trip through an intermediate wire-vocab hop), the
9459 // [`RestartStrategy::as_str`] emit and
9460 // [`RestartStrategy::from_wire`] parse share the same
9461 // `PascalCase` vocabulary by construction, so the borrowed-
9462 // input forward axis and the reverse axis compose directly.
9463 for &variant in RestartStrategy::ALL {
9464 let owned: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9465 let borrowed: &'static str = <&'static str as From<&RestartStrategy>>::from(&variant);
9466 assert_eq!(
9467 owned, borrowed,
9468 "From<RestartStrategy> and From<&RestartStrategy> for \
9469 &'static str must resolve identically on \
9470 RestartStrategy::{variant:?} — divergence signals the \
9471 owned-input and borrowed-input forward-projection paths \
9472 have drifted onto different emit-sets"
9473 );
9474 }
9475 let via_iter: Vec<&'static str> = RestartStrategy::ALL.iter().map(Into::into).collect();
9476 let via_method: Vec<&'static str> =
9477 RestartStrategy::ALL.iter().map(|s| s.as_str()).collect();
9478 assert_eq!(
9479 via_iter, via_method,
9480 "`.iter().map(Into::into)` over RestartStrategy::ALL must \
9481 byte-equal `.iter().map(|s| s.as_str())` on every arm — the \
9482 borrowed-input `From<&RestartStrategy> for &'static str` \
9483 axis is what makes the `.iter().map(Into::into)` shape route \
9484 through the substrate-primitive `RestartStrategy::as_str` \
9485 accessor rather than through a per-call-site `.copied()` / \
9486 dereference detour"
9487 );
9488 for variant in RestartStrategy::ALL {
9489 let emitted: &'static str = variant.into();
9490 let re_parsed: Result<RestartStrategy, ()> =
9491 <RestartStrategy as TryFrom<&str>>::try_from(emitted);
9492 assert_eq!(
9493 re_parsed,
9494 Ok(*variant),
9495 "trait-idiomatic borrowed-input forward-projection + \
9496 reverse-projection axis pair must round-trip \
9497 &RestartStrategy::{variant:?} through `.into::<&'static \
9498 str>()` (via the borrowed-input axis) and back through \
9499 `TryFrom<&str>` — a break signals the borrowed-input \
9500 forward-emit and reverse-parse axes have drifted onto \
9501 different vocabularies"
9502 );
9503 }
9504 }
9505
9506 #[test]
9507 fn restart_strategy_from_into_owned_string_routes_through_as_str_accessor() {
9508 // Fail-before-pass-after byte-parity pin on the newly lifted
9509 // `impl From<RestartStrategy> for String` — asserts the
9510 // owned-`String`-returning standard-library trait impl and the
9511 // substrate-primitive [`RestartStrategy::as_str`] `pub const fn`
9512 // accessor resolve to the same four-arm emit-set across every
9513 // arm the exhaustive [`RestartStrategy::ALL`] slice enumerates.
9514 // Rust's standard library does not carry a blanket
9515 // `impl<T: AsRef<str>> From<T> for String` (nor an
9516 // `impl<T: fmt::Display> From<T> for String`), so the
9517 // owned-`String` forward-projection axis is a distinct
9518 // trait-idiomatic surface that a
9519 // `let key: String = strategy.into();`-shaped call site
9520 // reaches through this impl and no other — the paired sibling
9521 // `From<RestartStrategy> for &'static str` impl forces every
9522 // owned-`String` call site through an explicit
9523 // `.to_owned()` / `String::from` restatement.
9524 for &variant in RestartStrategy::ALL {
9525 let via_trait: String = <String as From<RestartStrategy>>::from(variant);
9526 let via_method: &'static str = variant.as_str();
9527 assert_eq!(
9528 via_trait.as_str(),
9529 via_method,
9530 "From<RestartStrategy> for String impl must round-trip \
9531 RestartStrategy::{variant:?} to the same lifted \
9532 SUPERVISOR_ESTRATEGIA_* const RestartStrategy::as_str \
9533 returns — divergence signals a silent detour off the \
9534 substrate-primitive accessor"
9535 );
9536 let via_into: String = variant.into();
9537 assert_eq!(
9538 via_into.as_str(),
9539 via_method,
9540 "Into<String>::into on RestartStrategy::{variant:?} must \
9541 byte-equal RestartStrategy::as_str on the same input — the \
9542 blanket-derived Into shape must resolve to the same as_str \
9543 dispatch as the explicit From impl"
9544 );
9545 }
9546 }
9547
9548 #[test]
9549 fn restart_strategy_from_into_owned_string_and_static_str_agree_on_every_arm() {
9550 // Cross-axis partition pin: the paired trait-idiomatic
9551 // owned-`String` `From<RestartStrategy> for String` (this lift)
9552 // and owned-`&'static str` `From<RestartStrategy> for &'static
9553 // str` (523157d) forward projections must resolve identically
9554 // on every arm, locking the two return-type-shape paths
9555 // together so any future detour trips at caixa-core test time.
9556 // Also byte-parity witness against the sibling
9557 // [`ToString::to_string`] surface routed through
9558 // [`std::fmt::Display`] — the three owned-heap-string paths
9559 // (`.into::<String>()`, `String::from`, `.to_string()`) must
9560 // resolve identically on every arm so a future consumer that
9561 // picks any of the three lands on the same lifted
9562 // SUPERVISOR_ESTRATEGIA_* const. Then a direct round-trip
9563 // witness through the paired trait-idiomatic reverse
9564 // [`TryFrom<&str>`] axis on the owned-`String`'s
9565 // [`String::as_str`] borrow that closes the two-way
9566 // `Self → String → Self` round-trip on the trait-idiomatic
9567 // owned-`String` forward + reverse axis pair.
9568 for &variant in RestartStrategy::ALL {
9569 let owned_string: String = <String as From<RestartStrategy>>::from(variant);
9570 let owned_static: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9571 assert_eq!(
9572 owned_string.as_str(),
9573 owned_static,
9574 "From<RestartStrategy> for String and From<RestartStrategy> \
9575 for &'static str must resolve identically on \
9576 RestartStrategy::{variant:?} — divergence signals the \
9577 owned-`String` and owned-`&'static str` forward-projection \
9578 return-type-shape paths have drifted onto different \
9579 emit-sets"
9580 );
9581 let via_to_string: String = variant.to_string();
9582 assert_eq!(
9583 owned_string, via_to_string,
9584 "From<RestartStrategy> for String must byte-equal \
9585 RestartStrategy::to_string on RestartStrategy::{variant:?} — \
9586 divergence signals the trait-idiomatic owned-`String` \
9587 forward-projection axis and the ToString-through-Display \
9588 axis have drifted onto different emit-sets"
9589 );
9590 }
9591 let via_iter: Vec<String> = RestartStrategy::ALL
9592 .iter()
9593 .copied()
9594 .map(String::from)
9595 .collect();
9596 let via_method: Vec<String> = RestartStrategy::ALL
9597 .iter()
9598 .map(|s| s.as_str().to_owned())
9599 .collect();
9600 assert_eq!(
9601 via_iter, via_method,
9602 "`.iter().copied().map(String::from)` over RestartStrategy::ALL \
9603 must byte-equal `.iter().map(|s| s.as_str().to_owned())` on \
9604 every arm — the owned-`String` `From<RestartStrategy> for \
9605 String` axis is what makes the `String::from` composition \
9606 route through the substrate-primitive `RestartStrategy::as_str` \
9607 accessor rather than through a per-call-site `.to_owned()` / \
9608 `String::from(strategy.as_str())` detour"
9609 );
9610 for &variant in RestartStrategy::ALL {
9611 let emitted: String = variant.into();
9612 let re_parsed: Result<RestartStrategy, ()> =
9613 <RestartStrategy as TryFrom<&str>>::try_from(emitted.as_str());
9614 assert_eq!(
9615 re_parsed,
9616 Ok(variant),
9617 "trait-idiomatic owned-`String` forward-projection + \
9618 reverse-projection axis pair must round-trip \
9619 RestartStrategy::{variant:?} through `.into::<String>()` \
9620 and back through `TryFrom<&str>` on the owned-`String`'s \
9621 String::as_str borrow — a break signals the owned-`String` \
9622 forward-emit and reverse-parse axes have drifted onto \
9623 different vocabularies"
9624 );
9625 }
9626 }
9627
9628 #[test]
9629 fn restart_strategy_from_into_borrowed_owned_string_routes_through_as_str_accessor() {
9630 // Fail-before-pass-after byte-parity pin on the newly lifted
9631 // `impl From<&RestartStrategy> for String` — asserts the
9632 // borrowed-input owned-`String`-returning standard-library trait
9633 // impl and the substrate-primitive [`RestartStrategy::as_str`]
9634 // `pub const fn` accessor resolve to the same four-arm emit-set
9635 // across every arm the exhaustive [`RestartStrategy::ALL`] slice
9636 // enumerates. Rust's standard library does not carry a blanket
9637 // `impl<T: AsRef<str>> From<&T> for String` (nor an
9638 // `impl<T: fmt::Display> From<&T> for String`), so the
9639 // borrowed-input owned-`String` forward-projection axis is a
9640 // distinct trait-idiomatic surface that a
9641 // `let key: String = (&strategy).into();`-shaped call site
9642 // reaches through this impl and no other — the paired sibling
9643 // `From<RestartStrategy> for String` impl forces every
9644 // borrowed-input call site through an explicit `Copy` deref
9645 // (`String::from(*strategy)`) or an `.as_str().to_owned()` /
9646 // `.to_string()` detour.
9647 for &variant in RestartStrategy::ALL {
9648 let via_trait: String = <String as From<&RestartStrategy>>::from(&variant);
9649 let via_method: &'static str = variant.as_str();
9650 assert_eq!(
9651 via_trait.as_str(),
9652 via_method,
9653 "From<&RestartStrategy> for String impl must round-trip \
9654 &RestartStrategy::{variant:?} to the same lifted \
9655 SUPERVISOR_ESTRATEGIA_* const RestartStrategy::as_str \
9656 returns — divergence signals a silent detour off the \
9657 substrate-primitive accessor"
9658 );
9659 let via_into: String = (&variant).into();
9660 assert_eq!(
9661 via_into.as_str(),
9662 via_method,
9663 "Into<String>::into on &RestartStrategy::{variant:?} must \
9664 byte-equal RestartStrategy::as_str on the same input — the \
9665 blanket-derived Into shape must resolve to the same as_str \
9666 dispatch as the explicit From impl"
9667 );
9668 }
9669 }
9670
9671 #[test]
9672 fn restart_strategy_from_into_borrowed_owned_string_agrees_with_paired_axes_on_every_arm() {
9673 // Cross-axis partition pin: the newly lifted trait-idiomatic
9674 // borrowed-input owned-`String` `From<&RestartStrategy> for
9675 // String` (this lift), the paired owned-input owned-`String`
9676 // `From<RestartStrategy> for String` (7baa18a), the paired
9677 // borrowed-input owned-`&'static str` `From<&RestartStrategy>
9678 // for &'static str` (e941836), and the paired owned-input
9679 // owned-`&'static str` `From<RestartStrategy> for &'static str`
9680 // (523157d) — every corner of the `{Self, &Self} × {&'static
9681 // str, String}` 2×2 trait-idiomatic projection family — must
9682 // resolve identically on every arm, locking the four
9683 // return-shape × input-shape paths together so any future
9684 // detour trips at caixa-core test time. Also byte-parity
9685 // witness against the sibling [`ToString::to_string`] surface
9686 // routed through [`std::fmt::Display`] and a direct round-trip
9687 // witness through the paired trait-idiomatic reverse
9688 // [`TryFrom<&str>`] axis on the owned-`String`'s
9689 // [`String::as_str`] borrow that closes the two-way
9690 // `&Self → String → Self` round-trip on the trait-idiomatic
9691 // borrowed-input owned-`String` forward + reverse axis pair.
9692 for &variant in RestartStrategy::ALL {
9693 let borrowed_string: String = <String as From<&RestartStrategy>>::from(&variant);
9694 let owned_string: String = <String as From<RestartStrategy>>::from(variant);
9695 let borrowed_static: &'static str =
9696 <&'static str as From<&RestartStrategy>>::from(&variant);
9697 let owned_static: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9698 assert_eq!(
9699 borrowed_string, owned_string,
9700 "From<&RestartStrategy> for String and From<RestartStrategy> \
9701 for String must resolve identically on \
9702 RestartStrategy::{variant:?} — divergence signals the \
9703 borrowed-input and owned-input owned-`String` \
9704 forward-projection input-shape paths have drifted onto \
9705 different emit-sets"
9706 );
9707 assert_eq!(
9708 borrowed_string.as_str(),
9709 borrowed_static,
9710 "From<&RestartStrategy> for String and From<&RestartStrategy> \
9711 for &'static str must resolve identically on \
9712 RestartStrategy::{variant:?} — divergence signals the \
9713 borrowed-input `&'static str` and owned-`String` \
9714 return-shape paths have drifted onto different emit-sets"
9715 );
9716 assert_eq!(
9717 borrowed_string.as_str(),
9718 owned_static,
9719 "From<&RestartStrategy> for String and From<RestartStrategy> \
9720 for &'static str must resolve identically on \
9721 RestartStrategy::{variant:?} — divergence signals a break \
9722 in the diagonal corner of the {{Self, &Self}} × \
9723 {{&'static str, String}} 2×2 trait-idiomatic \
9724 projection family"
9725 );
9726 let via_to_string: String = variant.to_string();
9727 assert_eq!(
9728 borrowed_string, via_to_string,
9729 "From<&RestartStrategy> for String must byte-equal \
9730 RestartStrategy::to_string on RestartStrategy::{variant:?} — \
9731 divergence signals the trait-idiomatic borrowed-input \
9732 owned-`String` forward-projection axis and the \
9733 ToString-through-Display axis have drifted onto different \
9734 emit-sets"
9735 );
9736 }
9737 let via_iter: Vec<String> = RestartStrategy::ALL.iter().map(String::from).collect();
9738 let via_method: Vec<String> = RestartStrategy::ALL
9739 .iter()
9740 .map(|s| s.as_str().to_owned())
9741 .collect();
9742 assert_eq!(
9743 via_iter, via_method,
9744 "`.iter().map(String::from)` over RestartStrategy::ALL — a \
9745 call site whose iteration axis holds `&RestartStrategy` by \
9746 construction — must byte-equal `.iter().map(|s| \
9747 s.as_str().to_owned())` on every arm — the borrowed-input \
9748 owned-`String` `From<&RestartStrategy> for String` axis is \
9749 what makes the `String::from` composition route through the \
9750 substrate-primitive `RestartStrategy::as_str` accessor \
9751 without a spurious `Copy` deref (which would only be \
9752 reachable through the owned-input `From<RestartStrategy> for \
9753 String` axis by first calling `.copied()` on the iterator)"
9754 );
9755 for &variant in RestartStrategy::ALL {
9756 let emitted: String = (&variant).into();
9757 let re_parsed: Result<RestartStrategy, ()> =
9758 <RestartStrategy as TryFrom<&str>>::try_from(emitted.as_str());
9759 assert_eq!(
9760 re_parsed,
9761 Ok(variant),
9762 "trait-idiomatic borrowed-input owned-`String` \
9763 forward-projection + reverse-projection axis pair must \
9764 round-trip &RestartStrategy::{variant:?} through \
9765 `.into::<String>()` on the borrowed-input surface and \
9766 back through `TryFrom<&str>` on the owned-`String`'s \
9767 String::as_str borrow — a break signals the \
9768 borrowed-input owned-`String` forward-emit and \
9769 reverse-parse axes have drifted onto different \
9770 vocabularies"
9771 );
9772 }
9773 }
9774
9775 #[test]
9776 fn restart_strategy_from_into_static_cow_str_routes_through_as_str_accessor() {
9777 // Fail-before-pass-after byte-parity pin on the newly lifted
9778 // `impl From<RestartStrategy> for std::borrow::Cow<'static, str>` —
9779 // asserts the standard-library trait impl and the substrate-
9780 // primitive [`super::RestartStrategy::as_str`] `pub const fn`
9781 // accessor resolve to the same four-arm emit-set across every
9782 // arm the exhaustive [`super::RestartStrategy::ALL`] slice
9783 // enumerates. Rust's standard library does not carry a blanket
9784 // `impl<T: AsRef<str>> From<T> for Cow<'static, str>` (nor an
9785 // `impl<T: fmt::Display> From<T> for Cow<'static, str>`), so
9786 // the `Cow<'static, str>` forward-projection axis is a
9787 // distinct trait-idiomatic surface that a
9788 // `let key: Cow<'static, str> = strategy.into();`-shaped call
9789 // site reaches through this impl and no other — the paired
9790 // sibling `From<RestartStrategy> for &'static str` and
9791 // `From<RestartStrategy> for String` impls force every
9792 // `Cow<'static, str>`-parameterized call site through a
9793 // `Cow::Borrowed(strategy.as_str())` /
9794 // `Cow::Owned(strategy.to_string())` composition whose type
9795 // bounds have no compile-time link back to the substrate
9796 // primitive.
9797 //
9798 // Also asserts the projection lands on the zero-alloc
9799 // [`std::borrow::Cow::Borrowed`] arm (not the
9800 // [`std::borrow::Cow::Owned`] arm) — the substrate-primitive
9801 // [`super::RestartStrategy::as_str`] accessor's `&'static str`
9802 // return lifetime by construction makes the borrowed arm the
9803 // type-correct projection with no runtime allocation. Any
9804 // future silent detour that routes the impl through the owned
9805 // arm (an accidental `Cow::Owned(strategy.to_string())` rewrite
9806 // that would allocate on every call site where the
9807 // `&'static str` return of [`super::RestartStrategy::as_str`]
9808 // makes the zero-alloc borrowed projection type-correct) trips
9809 // at caixa-core test time under the
9810 // [`std::borrow::Cow::Borrowed`] discriminator witness rather
9811 // than at a downstream `Cow<'static, str>`-bound consumer's
9812 // silent allocation.
9813 //
9814 // First peer on the substrate-wide trait-idiomatic
9815 // [`std::borrow::Cow<'static, str>`] forward-projection family
9816 // to extend the axis off the top-level [`super::CaixaKind`]
9817 // enum (99c1735 owned-input, d45c409 borrowed-input) onto the
9818 // first M2 OTP-shape closed-set fieldless typed enum on the
9819 // caixa surface.
9820 for &variant in RestartStrategy::ALL {
9821 let via_trait: std::borrow::Cow<'static, str> =
9822 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(variant);
9823 let via_method: &'static str = variant.as_str();
9824 assert_eq!(
9825 via_trait.as_ref(),
9826 via_method,
9827 "From<RestartStrategy> for Cow<'static, str> impl must \
9828 round-trip RestartStrategy::{variant:?} to the same \
9829 lifted SUPERVISOR_ESTRATEGIA_* const \
9830 RestartStrategy::as_str returns — divergence signals a \
9831 silent detour off the substrate-primitive accessor"
9832 );
9833 assert!(
9834 matches!(via_trait, std::borrow::Cow::Borrowed(_)),
9835 "From<RestartStrategy> for Cow<'static, str> impl must \
9836 land on the zero-alloc Cow::Borrowed arm on \
9837 RestartStrategy::{variant:?} — a Cow::Owned outcome \
9838 signals the projection has silently allocated where \
9839 the substrate-primitive RestartStrategy::as_str \
9840 `&'static str` return makes the borrowed arm the \
9841 type-correct projection"
9842 );
9843 let via_into: std::borrow::Cow<'static, str> = variant.into();
9844 assert_eq!(
9845 via_into.as_ref(),
9846 via_method,
9847 "Into<Cow<'static, str>>::into on \
9848 RestartStrategy::{variant:?} must byte-equal \
9849 RestartStrategy::as_str on the same input — the \
9850 blanket-derived Into shape must resolve to the same \
9851 as_str dispatch as the explicit From impl"
9852 );
9853 assert!(
9854 matches!(via_into, std::borrow::Cow::Borrowed(_)),
9855 "Into<Cow<'static, str>>::into on \
9856 RestartStrategy::{variant:?} must land on the \
9857 zero-alloc Cow::Borrowed arm — the blanket-derived \
9858 Into shape must resolve to the same Cow::Borrowed \
9859 dispatch as the explicit From impl"
9860 );
9861 }
9862 }
9863
9864 #[test]
9865 fn restart_strategy_from_into_static_cow_str_agrees_with_paired_axes_on_every_arm() {
9866 // Cross-axis partition pin: the newly lifted trait-idiomatic
9867 // `From<RestartStrategy> for std::borrow::Cow<'static, str>`
9868 // (this lift), the paired owned-input `From<RestartStrategy>
9869 // for &'static str` (523157d), and the paired owned-input
9870 // `From<RestartStrategy> for String` (7baa18a) forward
9871 // projections must resolve identically on every arm, locking
9872 // the three return-shape paths together by construction so any
9873 // future detour trips at caixa-core test time. Also byte-parity
9874 // witness against the sibling [`ToString::to_string`] surface
9875 // routed through [`std::fmt::Display`] — every owned-heap-
9876 // string path (the `Cow::Owned` promotion of this axis's
9877 // `.into_owned()`, `From<RestartStrategy> for String`, and
9878 // `.to_string()`) resolves to the same lifted
9879 // [`crate::render::SUPERVISOR_ESTRATEGIA_*`] const per arm.
9880 //
9881 // Then a `.iter().copied().map(std::borrow::Cow::from)` pipe
9882 // witness over [`super::RestartStrategy::ALL`] that
9883 // materializes the four-arm accept-set through the
9884 // [`std::borrow::Cow<'static, str>`] axis alone — the exact
9885 // shape a future `axum::response::IntoResponse` per-strategy
9886 // rejection-body composer, a future M4 admission-webhook
9887 // per-strategy rejection-reason emitter whose typing rules out
9888 // the sibling [`AsRef<str>`] borrowed return, or a future
9889 // substrate-wide per-strategy diagnostic surface that binds
9890 // through a [`Cow<'static, str>`] boundary reaches through.
9891 // The pipe witness also pins the zero-alloc discipline: every
9892 // element in the collected vector satisfies the
9893 // [`std::borrow::Cow::Borrowed`] arm predicate, so a future
9894 // accidental silent-allocation regression on the pipe's
9895 // iteration axis is a caixa-core-test-time failure.
9896 for &variant in RestartStrategy::ALL {
9897 let via_cow: std::borrow::Cow<'static, str> =
9898 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(variant);
9899 let via_static: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
9900 let via_string: String = <String as From<RestartStrategy>>::from(variant);
9901 assert_eq!(
9902 via_cow.as_ref(),
9903 via_static,
9904 "From<RestartStrategy> for Cow<'static, str> and \
9905 From<RestartStrategy> for &'static str must resolve \
9906 identically on RestartStrategy::{variant:?} — \
9907 divergence signals the Cow<'static, str> and \
9908 &'static str return-shape paths have drifted onto \
9909 different emit-sets"
9910 );
9911 assert_eq!(
9912 via_cow.as_ref(),
9913 via_string.as_str(),
9914 "From<RestartStrategy> for Cow<'static, str> and \
9915 From<RestartStrategy> for String must resolve \
9916 identically on RestartStrategy::{variant:?} — \
9917 divergence signals the Cow<'static, str> and String \
9918 return-shape paths have drifted onto different \
9919 emit-sets"
9920 );
9921 let via_to_string: String = variant.to_string();
9922 assert_eq!(
9923 via_cow.as_ref(),
9924 via_to_string.as_str(),
9925 "From<RestartStrategy> for Cow<'static, str> must \
9926 byte-equal RestartStrategy::to_string on \
9927 RestartStrategy::{variant:?} — divergence signals the \
9928 trait-idiomatic Cow<'static, str> forward-projection \
9929 axis and the ToString-through-Display axis have \
9930 drifted onto different emit-sets"
9931 );
9932 }
9933 let via_iter: Vec<std::borrow::Cow<'static, str>> = RestartStrategy::ALL
9934 .iter()
9935 .copied()
9936 .map(std::borrow::Cow::from)
9937 .collect();
9938 let via_method: Vec<std::borrow::Cow<'static, str>> = RestartStrategy::ALL
9939 .iter()
9940 .map(|s| std::borrow::Cow::Borrowed(s.as_str()))
9941 .collect();
9942 assert_eq!(
9943 via_iter, via_method,
9944 "`.iter().copied().map(Cow::from)` over \
9945 RestartStrategy::ALL must byte-equal `.iter().map(|s| \
9946 Cow::Borrowed(s.as_str()))` on every arm — the \
9947 trait-idiomatic `From<RestartStrategy> for Cow<'static, \
9948 str>` axis is what makes the `Cow::from` composition \
9949 route through the substrate-primitive \
9950 `RestartStrategy::as_str` accessor with the zero-alloc \
9951 Cow::Borrowed arm by construction, rather than a \
9952 per-call-site `Cow::Owned(strategy.to_string())` \
9953 allocation"
9954 );
9955 for cow in &via_iter {
9956 assert!(
9957 matches!(cow, std::borrow::Cow::Borrowed(_)),
9958 "every element of the \
9959 .iter().copied().map(Cow::from) pipe over \
9960 RestartStrategy::ALL must land on the zero-alloc \
9961 Cow::Borrowed arm — a Cow::Owned outcome on any arm \
9962 signals the pipe's iteration axis has silently \
9963 allocated where the substrate-primitive \
9964 RestartStrategy::as_str `&'static str` return makes \
9965 the borrowed arm the type-correct projection"
9966 );
9967 }
9968 }
9969
9970 #[test]
9971 fn restart_strategy_from_borrowed_into_static_cow_str_routes_through_as_str_accessor() {
9972 // Fail-before-pass-after byte-parity pin on the newly lifted
9973 // `impl From<&RestartStrategy> for std::borrow::Cow<'static, str>` —
9974 // asserts the borrowed-input standard-library trait impl and
9975 // the substrate-primitive [`super::RestartStrategy::as_str`]
9976 // `pub const fn` accessor resolve to the same four-arm emit-
9977 // set across every arm the exhaustive
9978 // [`super::RestartStrategy::ALL`] slice enumerates. Rust's
9979 // standard library does not carry a blanket
9980 // `impl<T: AsRef<str>> From<&T> for Cow<'static, str>` (nor a
9981 // `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`), so
9982 // the borrowed-input `Cow<'static, str>` forward-projection
9983 // axis is a distinct trait-idiomatic surface that a
9984 // `let key: Cow<'static, str> = (&strategy).into();`-shaped
9985 // call site or a
9986 // `RestartStrategy::ALL.iter().map(Cow::from)`-shaped pipe
9987 // reaches through this impl and no other — the paired owned-
9988 // input `From<RestartStrategy> for Cow<'static, str>` impl
9989 // (7dd28b3) forces every borrowed-input call site through an
9990 // explicit `Copy` deref (`Cow::from(*strategy)`) or a
9991 // `Cow::Borrowed(strategy.as_str())` open-code whose type
9992 // bounds have no compile-time link back to the substrate
9993 // primitive.
9994 //
9995 // Also asserts the projection lands on the zero-alloc
9996 // [`std::borrow::Cow::Borrowed`] arm (not the
9997 // [`std::borrow::Cow::Owned`] arm) — the substrate-primitive
9998 // [`super::RestartStrategy::as_str`] accessor's `&'static str`
9999 // return lifetime by construction makes the borrowed arm the
10000 // type-correct projection with no runtime allocation on the
10001 // borrowed-input surface just as on the paired owned-input
10002 // surface.
10003 //
10004 // Second peer on the substrate-wide trait-idiomatic
10005 // [`std::borrow::Cow<'static, str>`] forward-projection family
10006 // on this enum — closes the `{Self, &Self}` input-shape
10007 // corner of the [`Cow<'static, str>`] axis on the first M2
10008 // OTP-shape closed-set fieldless typed enum peer on the caixa
10009 // surface (`:supervisor :estrategia`), exactly as d45c409
10010 // closed it on the top-level [`super::CaixaKind`] one commit
10011 // after the owning half (99c1735) landed. Every future
10012 // closed-set fieldless typed enum peer on the substrate is a
10013 // future target of the campaign.
10014 for &variant in RestartStrategy::ALL {
10015 let via_trait: std::borrow::Cow<'static, str> =
10016 <std::borrow::Cow<'static, str> as From<&RestartStrategy>>::from(&variant);
10017 let via_method: &'static str = variant.as_str();
10018 assert_eq!(
10019 via_trait.as_ref(),
10020 via_method,
10021 "From<&RestartStrategy> for Cow<'static, str> impl must \
10022 round-trip &RestartStrategy::{variant:?} to the same \
10023 lifted SUPERVISOR_ESTRATEGIA_* const \
10024 RestartStrategy::as_str returns — divergence signals a \
10025 silent detour off the substrate-primitive accessor"
10026 );
10027 assert!(
10028 matches!(via_trait, std::borrow::Cow::Borrowed(_)),
10029 "From<&RestartStrategy> for Cow<'static, str> impl must \
10030 land on the zero-alloc Cow::Borrowed arm on \
10031 &RestartStrategy::{variant:?} — a Cow::Owned outcome \
10032 signals the projection has silently allocated where \
10033 the substrate-primitive RestartStrategy::as_str \
10034 `&'static str` return makes the borrowed arm the \
10035 type-correct projection"
10036 );
10037 let via_into: std::borrow::Cow<'static, str> = (&variant).into();
10038 assert_eq!(
10039 via_into.as_ref(),
10040 via_method,
10041 "Into<Cow<'static, str>>::into on \
10042 &RestartStrategy::{variant:?} must byte-equal \
10043 RestartStrategy::as_str on the same input — the \
10044 blanket-derived Into shape must resolve to the same \
10045 as_str dispatch as the explicit From impl"
10046 );
10047 assert!(
10048 matches!(via_into, std::borrow::Cow::Borrowed(_)),
10049 "Into<Cow<'static, str>>::into on \
10050 &RestartStrategy::{variant:?} must land on the \
10051 zero-alloc Cow::Borrowed arm — the blanket-derived \
10052 Into shape must resolve to the same Cow::Borrowed \
10053 dispatch as the explicit From impl"
10054 );
10055 }
10056 }
10057
10058 #[test]
10059 fn restart_strategy_from_borrowed_into_static_cow_str_agrees_with_paired_axes_on_every_arm() {
10060 // Cross-axis partition pin: the newly lifted trait-idiomatic
10061 // borrowed-input `From<&RestartStrategy> for
10062 // std::borrow::Cow<'static, str>` (this lift), the paired
10063 // owned-input `From<RestartStrategy> for
10064 // std::borrow::Cow<'static, str>` (7dd28b3), the paired
10065 // borrowed-input owned-`&'static str` `From<&RestartStrategy>
10066 // for &'static str`, and the paired borrowed-input owned-
10067 // `String` `From<&RestartStrategy> for String` must resolve
10068 // identically on every arm, locking the four
10069 // return-shape × input-shape paths together by construction so
10070 // any future detour trips at caixa-core test time. Also byte-
10071 // parity witness against the sibling [`ToString::to_string`]
10072 // surface routed through [`std::fmt::Display`] — every owned-
10073 // heap-string path (this axis's `.into_owned()` promotion, the
10074 // paired [`From<&RestartStrategy> for String`], and
10075 // `.to_string()`) resolves to the same lifted
10076 // [`crate::render::SUPERVISOR_ESTRATEGIA_*`] const per arm.
10077 //
10078 // Then a `.iter().map(std::borrow::Cow::from)` pipe witness
10079 // over [`super::RestartStrategy::ALL`] — whose iterator yields
10080 // `&RestartStrategy` by construction, so the borrowed-input
10081 // [`Cow<'static, str>`] axis is what routes the pipe through
10082 // the substrate-primitive [`super::RestartStrategy::as_str`]
10083 // accessor without a spurious [`Copy`] deref (which would only
10084 // be reachable through the owned-input
10085 // [`From<RestartStrategy> for Cow<'static, str>`] axis by
10086 // first calling `.copied()` on the iterator). The pipe witness
10087 // also pins the zero-alloc discipline: every element in the
10088 // collected vector satisfies the [`std::borrow::Cow::Borrowed`]
10089 // arm predicate, so a future accidental silent-allocation
10090 // regression on the pipe's iteration axis is a caixa-core-
10091 // test-time failure.
10092 for &strategy in RestartStrategy::ALL {
10093 let borrowed_cow: std::borrow::Cow<'static, str> =
10094 <std::borrow::Cow<'static, str> as From<&RestartStrategy>>::from(&strategy);
10095 let owned_cow: std::borrow::Cow<'static, str> =
10096 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(strategy);
10097 let borrowed_static: &'static str =
10098 <&'static str as From<&RestartStrategy>>::from(&strategy);
10099 let borrowed_string: String = <String as From<&RestartStrategy>>::from(&strategy);
10100 assert_eq!(
10101 borrowed_cow, owned_cow,
10102 "From<&RestartStrategy> for Cow<'static, str> and \
10103 From<RestartStrategy> for Cow<'static, str> must \
10104 resolve identically on RestartStrategy::{strategy:?} — \
10105 divergence signals the borrowed-input and owned-input \
10106 Cow<'static, str> forward-projection input-shape \
10107 paths have drifted onto different emit-sets"
10108 );
10109 assert_eq!(
10110 borrowed_cow.as_ref(),
10111 borrowed_static,
10112 "From<&RestartStrategy> for Cow<'static, str> and \
10113 From<&RestartStrategy> for &'static str must resolve \
10114 identically on RestartStrategy::{strategy:?} — \
10115 divergence signals the borrowed-input Cow<'static, \
10116 str> and &'static str return-shape paths have drifted \
10117 onto different emit-sets"
10118 );
10119 assert_eq!(
10120 borrowed_cow.as_ref(),
10121 borrowed_string.as_str(),
10122 "From<&RestartStrategy> for Cow<'static, str> and \
10123 From<&RestartStrategy> for String must resolve \
10124 identically on RestartStrategy::{strategy:?} — \
10125 divergence signals the borrowed-input Cow<'static, \
10126 str> and owned-`String` return-shape paths have \
10127 drifted onto different emit-sets"
10128 );
10129 let via_to_string: String = strategy.to_string();
10130 assert_eq!(
10131 borrowed_cow.as_ref(),
10132 via_to_string.as_str(),
10133 "From<&RestartStrategy> for Cow<'static, str> must \
10134 byte-equal RestartStrategy::to_string on \
10135 RestartStrategy::{strategy:?} — divergence signals \
10136 the trait-idiomatic borrowed-input Cow<'static, str> \
10137 forward-projection axis and the ToString-through-\
10138 Display axis have drifted onto different emit-sets"
10139 );
10140 }
10141 let via_iter: Vec<std::borrow::Cow<'static, str>> = RestartStrategy::ALL
10142 .iter()
10143 .map(std::borrow::Cow::from)
10144 .collect();
10145 let via_method: Vec<std::borrow::Cow<'static, str>> = RestartStrategy::ALL
10146 .iter()
10147 .map(|s| std::borrow::Cow::Borrowed(s.as_str()))
10148 .collect();
10149 assert_eq!(
10150 via_iter, via_method,
10151 "`.iter().map(Cow::from)` over RestartStrategy::ALL — a \
10152 call site whose iteration axis holds `&RestartStrategy` \
10153 by construction — must byte-equal `.iter().map(|s| \
10154 Cow::Borrowed(s.as_str()))` on every arm — the borrowed-\
10155 input Cow<'static, str> `From<&RestartStrategy> for \
10156 Cow<'static, str>` axis is what makes the `Cow::from` \
10157 composition route through the substrate-primitive \
10158 `RestartStrategy::as_str` accessor with the zero-alloc \
10159 Cow::Borrowed arm by construction and without a spurious \
10160 `Copy` deref (which would only be reachable through the \
10161 owned-input `From<RestartStrategy> for Cow<'static, str>` \
10162 axis by first calling `.copied()` on the iterator)"
10163 );
10164 for cow in &via_iter {
10165 assert!(
10166 matches!(cow, std::borrow::Cow::Borrowed(_)),
10167 "every element of the .iter().map(Cow::from) pipe \
10168 over RestartStrategy::ALL must land on the zero-\
10169 alloc Cow::Borrowed arm — a Cow::Owned outcome on \
10170 any arm signals the pipe's iteration axis has \
10171 silently allocated where the substrate-primitive \
10172 RestartStrategy::as_str `&'static str` return makes \
10173 the borrowed arm the type-correct projection"
10174 );
10175 }
10176 }
10177
10178 #[test]
10179 fn restart_strategy_from_into_box_str_routes_through_as_str_accessor() {
10180 // Fail-before-pass-after byte-parity pin on the newly lifted
10181 // `impl From<RestartStrategy> for Box<str>` — asserts the
10182 // owned-input standard-library trait impl and the
10183 // substrate-primitive [`super::RestartStrategy::as_str`]
10184 // `pub const fn` accessor resolve to the same four-arm emit-
10185 // set across every arm the exhaustive
10186 // [`super::RestartStrategy::ALL`] slice enumerates. Opens the
10187 // substrate-wide `Box<str>` forward-projection campaign tier
10188 // on the first M2 OTP-shape closed-set fieldless typed enum
10189 // peer on the caixa surface (`:supervisor :estrategia`),
10190 // immediately after the paired `Cow<'static, str>` axis
10191 // (7dd28b3 / ee577fd) closed the
10192 // `{Self, &Self} × {&'static str, String, Cow<'static, str>}`
10193 // 2×3 corner on this enum. Rust's standard library carries
10194 // `impl From<&str> for Box<str>` and
10195 // `impl From<String> for Box<str>` but no blanket
10196 // `impl<T: AsRef<str>> From<T> for Box<str>`, so this axis is
10197 // a distinct trait-idiomatic surface that a
10198 // `let key: Box<str> = strategy.into();`-shaped call site
10199 // reaches through this impl and no other — a paired
10200 // `Box::from(strategy.as_str())` open-code has no compile-
10201 // time link back to the substrate primitive.
10202 for &variant in RestartStrategy::ALL {
10203 let via_trait: Box<str> = <Box<str> as From<RestartStrategy>>::from(variant);
10204 let via_method: &'static str = variant.as_str();
10205 assert_eq!(
10206 via_trait.as_ref(),
10207 via_method,
10208 "From<RestartStrategy> for Box<str> impl must round-\
10209 trip RestartStrategy::{variant:?} to the same lifted \
10210 SUPERVISOR_ESTRATEGIA_* const RestartStrategy::as_str \
10211 returns — divergence signals a silent detour off the \
10212 substrate-primitive accessor"
10213 );
10214 let via_into: Box<str> = variant.into();
10215 assert_eq!(
10216 via_into.as_ref(),
10217 via_method,
10218 "Into<Box<str>>::into on RestartStrategy::{variant:?} \
10219 must byte-equal RestartStrategy::as_str on the same \
10220 input — the blanket-derived Into shape must resolve \
10221 to the same as_str dispatch as the explicit From impl"
10222 );
10223 }
10224 }
10225
10226 #[test]
10227 fn restart_strategy_from_borrowed_into_box_str_routes_through_as_str_accessor() {
10228 // Fail-before-pass-after byte-parity pin on the newly lifted
10229 // `impl From<&RestartStrategy> for Box<str>` — asserts the
10230 // borrowed-input standard-library trait impl and the
10231 // substrate-primitive [`super::RestartStrategy::as_str`]
10232 // `pub const fn` accessor resolve to the same four-arm emit-
10233 // set across every arm the exhaustive
10234 // [`super::RestartStrategy::ALL`] slice enumerates. Rust's
10235 // standard library does not carry a blanket
10236 // `impl<T: AsRef<str>> From<&T> for Box<str>` (nor a
10237 // `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`),
10238 // so the borrowed-input `Box<str>` forward-projection axis
10239 // is a distinct trait-idiomatic surface that a
10240 // `let key: Box<str> = (&strategy).into();`-shaped call site
10241 // or a `RestartStrategy::ALL.iter().map(Box::<str>::from)`-
10242 // shaped pipe reaches through this impl and no other — the
10243 // paired owned-input `From<RestartStrategy> for Box<str>`
10244 // impl (69ef45c) forces every borrowed-input call site
10245 // through an explicit `Copy` deref
10246 // (`Box::<str>::from((*strategy).as_str())`) or a
10247 // `Box::<str>::from(strategy.as_str())` open-code whose
10248 // type bounds have no compile-time link back to the
10249 // substrate primitive.
10250 //
10251 // Second peer on the substrate-wide trait-idiomatic
10252 // [`Box<str>`] forward-projection family on this enum —
10253 // closes the `{Self, &Self}` input-shape corner of the
10254 // [`Box<str>`] axis on the first M2 OTP-shape closed-set
10255 // fieldless typed enum peer on the caixa surface
10256 // (`:supervisor :estrategia`), exactly as ee577fd closed
10257 // the paired [`Cow<'static, str>`] axis one commit after
10258 // its owning half (7dd28b3) landed. Every future closed-
10259 // set fieldless typed enum peer on the substrate is a
10260 // future target of the campaign.
10261 //
10262 // Also byte-parity witness against the paired owned-input
10263 // [`From<RestartStrategy> for Box<str>`] and the sibling
10264 // borrowed-input [`From<&RestartStrategy> for &'static str`],
10265 // [`From<&RestartStrategy> for String`], and
10266 // [`From<&RestartStrategy> for Cow<'static, str>`]
10267 // return-shape axes — locking the four
10268 // return-shape × input-shape paths together by construction
10269 // so any future detour trips at caixa-core test time. Then a
10270 // `.iter().map(Box::<str>::from)` pipe witness over
10271 // [`super::RestartStrategy::ALL`] — whose iterator yields
10272 // `&RestartStrategy` by construction, so the borrowed-input
10273 // [`Box<str>`] axis is what routes the pipe through the
10274 // substrate-primitive [`super::RestartStrategy::as_str`]
10275 // accessor without a spurious [`Copy`] deref (which would
10276 // only be reachable through the owned-input
10277 // [`From<RestartStrategy> for Box<str>`] axis by first
10278 // calling `.copied()` on the iterator).
10279 for &variant in RestartStrategy::ALL {
10280 let via_trait: Box<str> = <Box<str> as From<&RestartStrategy>>::from(&variant);
10281 let via_method: &'static str = variant.as_str();
10282 assert_eq!(
10283 via_trait.as_ref(),
10284 via_method,
10285 "From<&RestartStrategy> for Box<str> impl must \
10286 round-trip &RestartStrategy::{variant:?} to the same \
10287 lifted SUPERVISOR_ESTRATEGIA_* const \
10288 RestartStrategy::as_str returns — divergence signals \
10289 a silent detour off the substrate-primitive accessor"
10290 );
10291 let via_into: Box<str> = (&variant).into();
10292 assert_eq!(
10293 via_into.as_ref(),
10294 via_method,
10295 "Into<Box<str>>::into on &RestartStrategy::{variant:?} \
10296 must byte-equal RestartStrategy::as_str on the same \
10297 input — the blanket-derived Into shape must resolve \
10298 to the same as_str dispatch as the explicit From impl"
10299 );
10300 let owned_box: Box<str> = <Box<str> as From<RestartStrategy>>::from(variant);
10301 assert_eq!(
10302 via_trait, owned_box,
10303 "From<&RestartStrategy> for Box<str> and \
10304 From<RestartStrategy> for Box<str> must resolve \
10305 identically on RestartStrategy::{variant:?} — \
10306 divergence signals the borrowed-input and owned-input \
10307 Box<str> forward-projection input-shape paths have \
10308 drifted onto different emit-sets"
10309 );
10310 let borrowed_static: &'static str =
10311 <&'static str as From<&RestartStrategy>>::from(&variant);
10312 assert_eq!(
10313 via_trait.as_ref(),
10314 borrowed_static,
10315 "From<&RestartStrategy> for Box<str> and \
10316 From<&RestartStrategy> for &'static str must resolve \
10317 identically on RestartStrategy::{variant:?} — \
10318 divergence signals the borrowed-input Box<str> and \
10319 &'static str return-shape paths have drifted onto \
10320 different emit-sets"
10321 );
10322 let borrowed_string: String = <String as From<&RestartStrategy>>::from(&variant);
10323 assert_eq!(
10324 via_trait.as_ref(),
10325 borrowed_string.as_str(),
10326 "From<&RestartStrategy> for Box<str> and \
10327 From<&RestartStrategy> for String must resolve \
10328 identically on RestartStrategy::{variant:?} — \
10329 divergence signals the borrowed-input Box<str> and \
10330 owned-`String` return-shape paths have drifted onto \
10331 different emit-sets"
10332 );
10333 let borrowed_cow: std::borrow::Cow<'static, str> =
10334 <std::borrow::Cow<'static, str> as From<&RestartStrategy>>::from(&variant);
10335 assert_eq!(
10336 via_trait.as_ref(),
10337 borrowed_cow.as_ref(),
10338 "From<&RestartStrategy> for Box<str> and \
10339 From<&RestartStrategy> for Cow<'static, str> must \
10340 resolve identically on RestartStrategy::{variant:?} — \
10341 divergence signals the borrowed-input Box<str> and \
10342 Cow<'static, str> return-shape paths have drifted \
10343 onto different emit-sets"
10344 );
10345 }
10346 let via_iter: Vec<Box<str>> = RestartStrategy::ALL.iter().map(Box::<str>::from).collect();
10347 let via_method: Vec<Box<str>> = RestartStrategy::ALL
10348 .iter()
10349 .map(|s| Box::<str>::from(s.as_str()))
10350 .collect();
10351 assert_eq!(
10352 via_iter, via_method,
10353 "`.iter().map(Box::<str>::from)` over \
10354 RestartStrategy::ALL — a call site whose iteration axis \
10355 holds `&RestartStrategy` by construction — must byte-\
10356 equal `.iter().map(|s| Box::<str>::from(s.as_str()))` \
10357 on every arm — the borrowed-input Box<str> \
10358 `From<&RestartStrategy> for Box<str>` axis is what \
10359 makes the `Box::<str>::from` composition route through \
10360 the substrate-primitive `RestartStrategy::as_str` \
10361 accessor without a spurious `Copy` deref (which would \
10362 only be reachable through the owned-input \
10363 `From<RestartStrategy> for Box<str>` axis by first \
10364 calling `.copied()` on the iterator)"
10365 );
10366 }
10367
10368 #[test]
10369 fn restart_strategy_from_into_arc_str_routes_through_as_str_accessor() {
10370 // Fail-before-pass-after byte-parity pin on the newly lifted
10371 // `impl From<RestartStrategy> for std::sync::Arc<str>` — asserts
10372 // the owned-input standard-library trait impl and the
10373 // substrate-primitive [`super::RestartStrategy::as_str`]
10374 // `pub const fn` accessor resolve to the same four-arm emit-
10375 // set across every arm the exhaustive
10376 // [`super::RestartStrategy::ALL`] slice enumerates. Opens the
10377 // substrate-wide [`std::sync::Arc<str>`] forward-projection
10378 // campaign tier on the first M2 OTP-shape closed-set fieldless
10379 // typed enum peer on the caixa surface
10380 // (`:supervisor :estrategia`), immediately after the paired
10381 // [`Box<str>`] axis (69ef45c / 59ae5dc) closed the
10382 // `{Self, &Self} × {&'static str, String, Cow<'static, str>,
10383 // Box<str>}` 2×4 corner on this enum. Rust's standard library
10384 // carries `impl From<&str> for std::sync::Arc<str>` and
10385 // `impl From<String> for std::sync::Arc<str>` but no blanket
10386 // `impl<T: AsRef<str>> From<T> for std::sync::Arc<str>` (nor
10387 // an `impl<T: fmt::Display> From<T> for std::sync::Arc<str>`),
10388 // so this axis is a distinct trait-idiomatic surface that a
10389 // `let key: std::sync::Arc<str> = strategy.into();`-shaped call
10390 // site reaches through this impl and no other — a paired
10391 // `std::sync::Arc::<str>::from(strategy.as_str())` open-code
10392 // has no compile-time link back to the substrate primitive,
10393 // and a two-step `std::sync::Arc::<str>::from(String::from(
10394 // strategy))` composition through the owned-`String` axis
10395 // allocates twice (once into the intermediate `String`, once
10396 // into the [`Arc<str>`] on the `From<String>` conversion)
10397 // where the single-step trait impl allocates once.
10398 //
10399 // Cross-axis byte-parity witness against the sibling owned-
10400 // input `{&'static str, String, Cow<'static, str>, Box<str>}`
10401 // return-shape axes — locking the five return-shape paths on
10402 // the owned-input surface together by construction so any
10403 // future detour off the substrate-primitive
10404 // [`super::RestartStrategy::as_str`] accessor trips at caixa-
10405 // core test time.
10406 for &variant in RestartStrategy::ALL {
10407 let via_trait: std::sync::Arc<str> =
10408 <std::sync::Arc<str> as From<RestartStrategy>>::from(variant);
10409 let via_method: &'static str = variant.as_str();
10410 assert_eq!(
10411 via_trait.as_ref(),
10412 via_method,
10413 "From<RestartStrategy> for std::sync::Arc<str> impl \
10414 must round-trip RestartStrategy::{variant:?} to the \
10415 same lifted SUPERVISOR_ESTRATEGIA_* const \
10416 RestartStrategy::as_str returns — divergence signals \
10417 a silent detour off the substrate-primitive accessor"
10418 );
10419 let via_into: std::sync::Arc<str> = variant.into();
10420 assert_eq!(
10421 via_into.as_ref(),
10422 via_method,
10423 "Into<std::sync::Arc<str>>::into on \
10424 RestartStrategy::{variant:?} must byte-equal \
10425 RestartStrategy::as_str on the same input — the \
10426 blanket-derived Into shape must resolve to the same \
10427 as_str dispatch as the explicit From impl"
10428 );
10429 let owned_static: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
10430 assert_eq!(
10431 via_trait.as_ref(),
10432 owned_static,
10433 "From<RestartStrategy> for std::sync::Arc<str> and \
10434 From<RestartStrategy> for &'static str must resolve \
10435 identically on RestartStrategy::{variant:?} — \
10436 divergence signals the owned-input std::sync::Arc<str> \
10437 and &'static str return-shape paths have drifted onto \
10438 different emit-sets"
10439 );
10440 let owned_string: String = <String as From<RestartStrategy>>::from(variant);
10441 assert_eq!(
10442 via_trait.as_ref(),
10443 owned_string.as_str(),
10444 "From<RestartStrategy> for std::sync::Arc<str> and \
10445 From<RestartStrategy> for String must resolve \
10446 identically on RestartStrategy::{variant:?} — \
10447 divergence signals the owned-input std::sync::Arc<str> \
10448 and owned-`String` return-shape paths have drifted \
10449 onto different emit-sets"
10450 );
10451 let owned_cow: std::borrow::Cow<'static, str> =
10452 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(variant);
10453 assert_eq!(
10454 via_trait.as_ref(),
10455 owned_cow.as_ref(),
10456 "From<RestartStrategy> for std::sync::Arc<str> and \
10457 From<RestartStrategy> for Cow<'static, str> must \
10458 resolve identically on RestartStrategy::{variant:?} — \
10459 divergence signals the owned-input std::sync::Arc<str> \
10460 and Cow<'static, str> return-shape paths have drifted \
10461 onto different emit-sets"
10462 );
10463 let owned_box: Box<str> = <Box<str> as From<RestartStrategy>>::from(variant);
10464 assert_eq!(
10465 via_trait.as_ref(),
10466 owned_box.as_ref(),
10467 "From<RestartStrategy> for std::sync::Arc<str> and \
10468 From<RestartStrategy> for Box<str> must resolve \
10469 identically on RestartStrategy::{variant:?} — \
10470 divergence signals the owned-input std::sync::Arc<str> \
10471 and Box<str> return-shape paths have drifted onto \
10472 different emit-sets"
10473 );
10474 }
10475 }
10476
10477 #[test]
10478 fn restart_strategy_from_borrowed_into_arc_str_routes_through_as_str_accessor() {
10479 // Fail-before-pass-after byte-parity pin on the newly lifted
10480 // `impl From<&RestartStrategy> for std::sync::Arc<str>` —
10481 // asserts the borrowed-input standard-library trait impl and
10482 // the substrate-primitive [`super::RestartStrategy::as_str`]
10483 // `pub const fn` accessor resolve to the same four-arm emit-
10484 // set across every arm the exhaustive
10485 // [`super::RestartStrategy::ALL`] slice enumerates. Rust's
10486 // standard library does not carry a blanket
10487 // `impl<T: AsRef<str>> From<&T> for std::sync::Arc<str>` (nor
10488 // a `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`),
10489 // so the borrowed-input [`std::sync::Arc<str>`] forward-
10490 // projection axis is a distinct trait-idiomatic surface that a
10491 // `let key: std::sync::Arc<str> = (&strategy).into();`-shaped
10492 // call site or a
10493 // `RestartStrategy::ALL.iter().map(std::sync::Arc::<str>::from)`-
10494 // shaped pipe reaches through this impl and no other — the
10495 // paired owned-input
10496 // `From<RestartStrategy> for std::sync::Arc<str>` impl
10497 // (bca2ec8) forces every borrowed-input call site through an
10498 // explicit `Copy` deref
10499 // (`std::sync::Arc::<str>::from((*strategy).as_str())`) or a
10500 // `std::sync::Arc::<str>::from(strategy.as_str())` open-code
10501 // whose type bounds have no compile-time link back to the
10502 // substrate primitive.
10503 //
10504 // Second peer on the substrate-wide trait-idiomatic
10505 // [`std::sync::Arc<str>`] forward-projection family on this
10506 // enum — closes the `{Self, &Self}` input-shape corner of
10507 // the [`std::sync::Arc<str>`] axis on the first M2 OTP-shape
10508 // closed-set fieldless typed enum peer on the caixa surface
10509 // (`:supervisor :estrategia`), exactly as 59ae5dc closed the
10510 // paired [`Box<str>`] axis one commit after its owning half
10511 // (69ef45c) landed. Every future closed-set fieldless typed
10512 // enum peer on the substrate is a future target of the
10513 // campaign.
10514 //
10515 // Also byte-parity witness against the paired owned-input
10516 // [`From<RestartStrategy> for std::sync::Arc<str>`] and the
10517 // sibling borrowed-input
10518 // [`From<&RestartStrategy> for &'static str`],
10519 // [`From<&RestartStrategy> for String`],
10520 // [`From<&RestartStrategy> for Cow<'static, str>`], and
10521 // [`From<&RestartStrategy> for Box<str>`] return-shape axes —
10522 // locking the five return-shape × input-shape paths together
10523 // by construction so any future detour trips at caixa-core
10524 // test time. Then a
10525 // `.iter().map(std::sync::Arc::<str>::from)` pipe witness over
10526 // [`super::RestartStrategy::ALL`] — whose iterator yields
10527 // `&RestartStrategy` by construction, so the borrowed-input
10528 // [`std::sync::Arc<str>`] axis is what routes the pipe
10529 // through the substrate-primitive
10530 // [`super::RestartStrategy::as_str`] accessor without a
10531 // spurious [`Copy`] deref (which would only be reachable
10532 // through the owned-input
10533 // [`From<RestartStrategy> for std::sync::Arc<str>`] axis by
10534 // first calling `.copied()` on the iterator).
10535 for &variant in RestartStrategy::ALL {
10536 let via_trait: std::sync::Arc<str> =
10537 <std::sync::Arc<str> as From<&RestartStrategy>>::from(&variant);
10538 let via_method: &'static str = variant.as_str();
10539 assert_eq!(
10540 via_trait.as_ref(),
10541 via_method,
10542 "From<&RestartStrategy> for std::sync::Arc<str> impl \
10543 must round-trip &RestartStrategy::{variant:?} to the \
10544 same lifted SUPERVISOR_ESTRATEGIA_* const \
10545 RestartStrategy::as_str returns — divergence signals \
10546 a silent detour off the substrate-primitive accessor"
10547 );
10548 let via_into: std::sync::Arc<str> = (&variant).into();
10549 assert_eq!(
10550 via_into.as_ref(),
10551 via_method,
10552 "Into<std::sync::Arc<str>>::into on \
10553 &RestartStrategy::{variant:?} must byte-equal \
10554 RestartStrategy::as_str on the same input — the \
10555 blanket-derived Into shape must resolve to the same \
10556 as_str dispatch as the explicit From impl"
10557 );
10558 let owned_arc: std::sync::Arc<str> =
10559 <std::sync::Arc<str> as From<RestartStrategy>>::from(variant);
10560 assert_eq!(
10561 via_trait, owned_arc,
10562 "From<&RestartStrategy> for std::sync::Arc<str> and \
10563 From<RestartStrategy> for std::sync::Arc<str> must \
10564 resolve identically on RestartStrategy::{variant:?} — \
10565 divergence signals the borrowed-input and owned-input \
10566 std::sync::Arc<str> forward-projection input-shape \
10567 paths have drifted onto different emit-sets"
10568 );
10569 let borrowed_static: &'static str =
10570 <&'static str as From<&RestartStrategy>>::from(&variant);
10571 assert_eq!(
10572 via_trait.as_ref(),
10573 borrowed_static,
10574 "From<&RestartStrategy> for std::sync::Arc<str> and \
10575 From<&RestartStrategy> for &'static str must resolve \
10576 identically on RestartStrategy::{variant:?} — \
10577 divergence signals the borrowed-input \
10578 std::sync::Arc<str> and &'static str return-shape \
10579 paths have drifted onto different emit-sets"
10580 );
10581 let borrowed_string: String = <String as From<&RestartStrategy>>::from(&variant);
10582 assert_eq!(
10583 via_trait.as_ref(),
10584 borrowed_string.as_str(),
10585 "From<&RestartStrategy> for std::sync::Arc<str> and \
10586 From<&RestartStrategy> for String must resolve \
10587 identically on RestartStrategy::{variant:?} — \
10588 divergence signals the borrowed-input \
10589 std::sync::Arc<str> and owned-`String` return-shape \
10590 paths have drifted onto different emit-sets"
10591 );
10592 let borrowed_cow: std::borrow::Cow<'static, str> =
10593 <std::borrow::Cow<'static, str> as From<&RestartStrategy>>::from(&variant);
10594 assert_eq!(
10595 via_trait.as_ref(),
10596 borrowed_cow.as_ref(),
10597 "From<&RestartStrategy> for std::sync::Arc<str> and \
10598 From<&RestartStrategy> for Cow<'static, str> must \
10599 resolve identically on RestartStrategy::{variant:?} — \
10600 divergence signals the borrowed-input \
10601 std::sync::Arc<str> and Cow<'static, str> return-shape \
10602 paths have drifted onto different emit-sets"
10603 );
10604 let borrowed_box: Box<str> = <Box<str> as From<&RestartStrategy>>::from(&variant);
10605 assert_eq!(
10606 via_trait.as_ref(),
10607 borrowed_box.as_ref(),
10608 "From<&RestartStrategy> for std::sync::Arc<str> and \
10609 From<&RestartStrategy> for Box<str> must resolve \
10610 identically on RestartStrategy::{variant:?} — \
10611 divergence signals the borrowed-input \
10612 std::sync::Arc<str> and Box<str> return-shape paths \
10613 have drifted onto different emit-sets"
10614 );
10615 }
10616 let via_iter: Vec<std::sync::Arc<str>> = RestartStrategy::ALL
10617 .iter()
10618 .map(std::sync::Arc::<str>::from)
10619 .collect();
10620 let via_method: Vec<std::sync::Arc<str>> = RestartStrategy::ALL
10621 .iter()
10622 .map(|s| std::sync::Arc::<str>::from(s.as_str()))
10623 .collect();
10624 assert_eq!(
10625 via_iter, via_method,
10626 "`.iter().map(std::sync::Arc::<str>::from)` over \
10627 RestartStrategy::ALL — a call site whose iteration axis \
10628 holds `&RestartStrategy` by construction — must byte-\
10629 equal `.iter().map(|s| std::sync::Arc::<str>::from(s.as_str()))` \
10630 on every arm — the borrowed-input std::sync::Arc<str> \
10631 `From<&RestartStrategy> for std::sync::Arc<str>` axis is \
10632 what makes the `std::sync::Arc::<str>::from` composition \
10633 route through the substrate-primitive \
10634 `RestartStrategy::as_str` accessor without a spurious \
10635 `Copy` deref (which would only be reachable through the \
10636 owned-input `From<RestartStrategy> for std::sync::Arc<str>` \
10637 axis by first calling `.copied()` on the iterator)"
10638 );
10639 }
10640
10641 #[test]
10642 #[allow(
10643 clippy::too_many_lines,
10644 reason = "cross-axis partition pin folds the substrate-primitive \
10645 as_str accessor's `.as_bytes()` byte-tail plus the \
10646 paired str-view (AsRef<str>, Display, as_str) and \
10647 reverse-projection ({&'static str, String, Cow<'static, \
10648 str>, Box<str>, std::sync::Arc<str>}) return-shape \
10649 axes' `.as_bytes()` byte-tails plus a <T: AsRef<[u8]>>\
10650 -bound-consumer witness plus a blake3::Hasher::update-\
10651 shape byte-input surface witness into one exhaustive \
10652 round-trip over RestartStrategy::ALL — the accepted \
10653 line-count cost of opening the byte-view axis keyed \
10654 to the substrate-primitive as_str accessor at the \
10655 same test-site"
10656 )]
10657 #[allow(
10658 clippy::needless_borrows_for_generic_args,
10659 reason = "the borrowed-input surface (&variant) is exercised \
10660 deliberately: the `<T: AsRef<[u8]>>`-bound consumer \
10661 and the `blake3::Hasher::update`-shape byte-input \
10662 surface both accept either owned or borrowed input \
10663 through the standard-library blanket \
10664 `impl<T: ?Sized + AsRef<[u8]>> AsRef<[u8]> for &T`, \
10665 and this pin round-trips both input shapes to lock \
10666 the borrowed-input path load-bearing against a \
10667 future silent regression"
10668 )]
10669 fn restart_strategy_as_ref_bytes_routes_through_as_str_accessor() {
10670 // `<T: AsRef<[u8]>>`-bound generic-consumer witness: a byte-input
10671 // function that binds its argument through the standard-library
10672 // [`AsRef<[u8]>`] trait bound accepts a [`super::RestartStrategy`]
10673 // directly, without the caller open-coding the two-hop
10674 // `estrategia.as_str().as_bytes()` composition. Lifted to the top
10675 // of the function per `clippy::items_after_statements`.
10676 fn generic_bytes_sink<T: AsRef<[u8]>>(t: T) -> Vec<u8> {
10677 t.as_ref().to_vec()
10678 }
10679 // `blake3::Hasher::update`-shape byte-input surface mock: mirrors
10680 // `blake3::Hasher::update` / `ring::digest::Context::update` /
10681 // `sha2::Sha256::update`'s `impl AsRef<[u8]>`-bound `update`
10682 // signature so a per-supervisor BLAKE3 content-address closure
10683 // that composes `hasher.update(estrategia)` on the
10684 // [`crate::Lacre`] closure builder reaches the substrate-primitive
10685 // `as_str` accessor through the [`super::RestartStrategy`]
10686 // `AsRef<[u8]>` axis and no other. Lifted to the top of the
10687 // function per `clippy::items_after_statements`.
10688 struct MockHasher(Vec<u8>);
10689 impl MockHasher {
10690 fn new() -> Self {
10691 Self(Vec::new())
10692 }
10693 fn update(&mut self, bytes: impl AsRef<[u8]>) -> &mut Self {
10694 self.0.extend_from_slice(bytes.as_ref());
10695 self
10696 }
10697 fn finalize(self) -> Vec<u8> {
10698 self.0
10699 }
10700 }
10701
10702 // Fail-before-pass-after byte-parity pin on the newly lifted
10703 // `impl AsRef<[u8]> for RestartStrategy` — asserts the trait-
10704 // idiomatic byte-view standard-library impl and the substrate-
10705 // primitive [`super::RestartStrategy::as_str`] `pub const fn`
10706 // accessor's `.as_bytes()` byte-tail resolve to the same four-arm
10707 // `PascalCase` wire byte-string emit-set across every arm the
10708 // exhaustive [`super::RestartStrategy::ALL`] slice enumerates.
10709 // Opens the trait-idiomatic byte-view axis onto the first M2
10710 // OTP-shape closed-set fieldless typed enum peer on the caixa
10711 // surface (`:supervisor :estrategia`), extending the substrate-
10712 // wide byte-view campaign the sibling
10713 // [`super::crate::CaixaKind`] first-mover (69d8d86) opened.
10714 //
10715 // Rust's standard library carries `impl AsRef<[u8]> for str` and
10716 // `impl AsRef<[u8]> for String`, so a two-hop composition
10717 // `estrategia.as_str().as_bytes()` (or the equally two-hop
10718 // `AsRef::<str>::as_ref(&estrategia).as_bytes()`) is reachable
10719 // through the pre-existing str-view axis alone. But that two-hop
10720 // shape has no compile-time link back to the byte-projection
10721 // axis, forces every downstream `<T: AsRef<[u8]>>`-bound
10722 // consumer to open-code the two-hop composition at every call
10723 // site, and admits a silent split whenever a future call site
10724 // takes a sibling reverse-projection axis whose `.as_bytes()`
10725 // byte-tail carries no compile-time byte-view surface. This
10726 // impl closes the byte-view axis at the substrate-primitive
10727 // [`super::RestartStrategy::as_str`] accessor so every future
10728 // `<T: AsRef<[u8]>>`-bound consumer reaches the same lifted
10729 // [`super::crate::render::SUPERVISOR_ESTRATEGIA_*`] const roster
10730 // the paired str-view axes already return through — through one
10731 // trait dispatch.
10732 for &variant in RestartStrategy::ALL {
10733 let via_trait: &[u8] = <RestartStrategy as AsRef<[u8]>>::as_ref(&variant);
10734 let via_method_bytes: &[u8] = variant.as_str().as_bytes();
10735 assert_eq!(
10736 via_trait, via_method_bytes,
10737 "AsRef<[u8]> for RestartStrategy impl must byte-equal \
10738 RestartStrategy::as_str().as_bytes() on \
10739 RestartStrategy::{variant:?} — divergence signals a \
10740 silent detour off the substrate-primitive accessor"
10741 );
10742 // Cross-axis witness against the paired str-view axes'
10743 // `.as_bytes()` byte-tails: [`AsRef<str>`] /
10744 // [`std::fmt::Display`] / [`super::RestartStrategy::as_str`]
10745 // all resolve to the same lifted
10746 // [`super::crate::render::SUPERVISOR_ESTRATEGIA_*`] const
10747 // roster, and the byte-view axis must byte-equal each of
10748 // their `.as_bytes()` byte-tails by construction — locking
10749 // the str-view and byte-view axes together at the
10750 // substrate-primitive accessor.
10751 let str_view_ref: &str = <RestartStrategy as AsRef<str>>::as_ref(&variant);
10752 assert_eq!(
10753 via_trait,
10754 str_view_ref.as_bytes(),
10755 "AsRef<[u8]> for RestartStrategy and AsRef<str> for \
10756 RestartStrategy must resolve to byte-equal byte-tails \
10757 on RestartStrategy::{variant:?} — divergence signals \
10758 the byte-view and str-view axes have drifted off the \
10759 same substrate-primitive as_str accessor"
10760 );
10761 let display_bytes = variant.to_string();
10762 assert_eq!(
10763 via_trait,
10764 display_bytes.as_bytes(),
10765 "AsRef<[u8]> for RestartStrategy and \
10766 <RestartStrategy as std::fmt::Display>::to_string must \
10767 resolve to byte-equal byte-tails on \
10768 RestartStrategy::{variant:?} — divergence signals the \
10769 byte-view axis and the Display formatter axis have \
10770 drifted off the same substrate-primitive as_str \
10771 accessor"
10772 );
10773 // Cross-axis witness against the paired reverse-projection
10774 // axes' `.as_bytes()` byte-tails: every one of `{&'static
10775 // str, String, Cow<'static, str>, Box<str>,
10776 // std::sync::Arc<str>}` allocates (or borrows) the same
10777 // `PascalCase` wire byte-string the substrate-primitive
10778 // accessor emits, so the byte-view axis must byte-equal
10779 // each of their `.as_bytes()` byte-tails by construction.
10780 let owned_static: &'static str = <&'static str as From<RestartStrategy>>::from(variant);
10781 assert_eq!(
10782 via_trait,
10783 owned_static.as_bytes(),
10784 "AsRef<[u8]> for RestartStrategy and From<RestartStrategy> \
10785 for &'static str must resolve to byte-equal byte-tails \
10786 on RestartStrategy::{variant:?}"
10787 );
10788 let owned_string: String = <String as From<RestartStrategy>>::from(variant);
10789 assert_eq!(
10790 via_trait,
10791 owned_string.as_bytes(),
10792 "AsRef<[u8]> for RestartStrategy and From<RestartStrategy> \
10793 for String must resolve to byte-equal byte-tails on \
10794 RestartStrategy::{variant:?}"
10795 );
10796 let owned_cow: std::borrow::Cow<'static, str> =
10797 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(variant);
10798 assert_eq!(
10799 via_trait,
10800 owned_cow.as_bytes(),
10801 "AsRef<[u8]> for RestartStrategy and From<RestartStrategy> \
10802 for Cow<'static, str> must resolve to byte-equal byte-\
10803 tails on RestartStrategy::{variant:?}"
10804 );
10805 let owned_box: Box<str> = <Box<str> as From<RestartStrategy>>::from(variant);
10806 assert_eq!(
10807 via_trait,
10808 owned_box.as_bytes(),
10809 "AsRef<[u8]> for RestartStrategy and From<RestartStrategy> \
10810 for Box<str> must resolve to byte-equal byte-tails on \
10811 RestartStrategy::{variant:?}"
10812 );
10813 let owned_arc: std::sync::Arc<str> =
10814 <std::sync::Arc<str> as From<RestartStrategy>>::from(variant);
10815 assert_eq!(
10816 via_trait,
10817 owned_arc.as_bytes(),
10818 "AsRef<[u8]> for RestartStrategy and From<RestartStrategy> \
10819 for std::sync::Arc<str> must resolve to byte-equal byte-\
10820 tails on RestartStrategy::{variant:?}"
10821 );
10822 }
10823 // `<T: AsRef<[u8]>>`-bound-consumer witness: the generic byte-
10824 // input function `generic_bytes_sink` (lifted above per
10825 // `clippy::items_after_statements`) accepts a
10826 // [`super::RestartStrategy`] directly through the trait bound,
10827 // without the caller open-coding the two-hop
10828 // `estrategia.as_str().as_bytes()` composition. This is the
10829 // shape that reaches the caixa-lacre BLAKE3 content-address
10830 // closure's `blake3::Hasher::update(impl AsRef<[u8]>)` byte-
10831 // input surface through this impl and no other.
10832 for &variant in RestartStrategy::ALL {
10833 let via_generic = generic_bytes_sink(variant);
10834 let via_borrowed_generic = generic_bytes_sink(&variant);
10835 let via_method_bytes = variant.as_str().as_bytes().to_vec();
10836 assert_eq!(
10837 via_generic, via_method_bytes,
10838 "generic `<T: AsRef<[u8]>>`-bound consumer on \
10839 RestartStrategy::{variant:?} must yield the same byte-\
10840 tail RestartStrategy::as_str().as_bytes() returns — \
10841 divergence signals the byte-view axis fails to bridge \
10842 a generic byte-input trait bound to the substrate-\
10843 primitive accessor"
10844 );
10845 assert_eq!(
10846 via_borrowed_generic, via_method_bytes,
10847 "generic `<T: AsRef<[u8]>>`-bound consumer on \
10848 &RestartStrategy::{variant:?} must yield the same byte-\
10849 tail RestartStrategy::as_str().as_bytes() returns — \
10850 the borrowed-input surface must resolve to the same \
10851 as_str dispatch"
10852 );
10853 }
10854 // `blake3::Hasher::update`-shape byte-input surface witness on
10855 // the caixa-lacre compounding target: the `MockHasher` (lifted
10856 // above per `clippy::items_after_statements`) mirrors
10857 // `blake3::Hasher::update` / `ring::digest::Context::update` /
10858 // `sha2::Sha256::update`'s `impl AsRef<[u8]>`-bound update
10859 // signature and accepts a [`super::RestartStrategy`] directly,
10860 // routing its byte-tail through the substrate-primitive
10861 // `as_str` accessor — the shape a future per-supervisor BLAKE3
10862 // content-address closure composes to fold an `:estrategia`
10863 // discriminator byte-tag into the [`crate::Lacre`] closure
10864 // body.
10865 for &variant in RestartStrategy::ALL {
10866 let mut owned_hasher = MockHasher::new();
10867 owned_hasher.update(variant);
10868 let owned_folded = owned_hasher.finalize();
10869 assert_eq!(
10870 owned_folded,
10871 variant.as_str().as_bytes(),
10872 "`hasher.update(estrategia)`-shape composition on \
10873 RestartStrategy::{variant:?} must fold the same byte-\
10874 tail RestartStrategy::as_str().as_bytes() returns — \
10875 the shape a future per-supervisor BLAKE3 content-\
10876 address closure composes to fold an `:estrategia` \
10877 discriminator byte-tag into the Lacre closure body"
10878 );
10879 let mut borrowed_hasher = MockHasher::new();
10880 borrowed_hasher.update(&variant);
10881 let borrowed_folded = borrowed_hasher.finalize();
10882 assert_eq!(
10883 borrowed_folded,
10884 variant.as_str().as_bytes(),
10885 "`hasher.update(&estrategia)`-shape composition on \
10886 &RestartStrategy::{variant:?} must fold the same byte-\
10887 tail RestartStrategy::as_str().as_bytes() returns — \
10888 the borrowed-input surface must resolve to the same \
10889 as_str dispatch"
10890 );
10891 }
10892 }
10893
10894 #[test]
10895 #[expect(
10896 clippy::too_many_lines,
10897 reason = "the byte-owned reverse-projection axis is extended \
10898 here onto the first M2-OTP-shape closed-set fieldless \
10899 typed-enum peer, so the pin binds the new impl against \
10900 every paired byte-view and str-owned axis on the same \
10901 enum plus a generic <T: Into<Vec<u8>>>-bound consumer \
10902 witness and a std::io::Write::write_all-shape owned-\
10903 byte-sink surface witness on both owned and borrowed \
10904 input shapes to lock the whole family against a future \
10905 silent regression"
10906 )]
10907 fn restart_strategy_from_into_owned_vec_bytes_routes_through_as_str_accessor() {
10908 // `<T: Into<Vec<u8>>>`-bound-consumer witness helper: a generic
10909 // owned-byte-input function accepts a [`super::RestartStrategy`]
10910 // directly through the trait bound, without the caller open-
10911 // coding the three-hop `strategy.as_str().as_bytes().to_vec()`
10912 // composition. Lifted to the top of the function per
10913 // `clippy::items_after_statements`.
10914 fn generic_owned_bytes_sink<T: Into<Vec<u8>>>(t: T) -> Vec<u8> {
10915 t.into()
10916 }
10917 // `std::io::Write::write_all`-shape owned-byte-sink surface
10918 // mock: mirrors `std::io::Write::write_all` /
10919 // `bytes::BytesMut::extend_from_slice` / any per-arm audit-log
10920 // byte-sink that consumes a `Vec<u8>` payload via
10921 // `Into<Vec<u8>>`, so a future per-supervisor per-`:estrategia`
10922 // audit-log emit reaches the substrate-primitive `as_str`
10923 // accessor through the byte-owned reverse-projection axis and
10924 // no other. Lifted to the top of the function per
10925 // `clippy::items_after_statements`.
10926 struct MockOwnedByteSink(Vec<u8>);
10927 impl MockOwnedByteSink {
10928 fn new() -> Self {
10929 Self(Vec::new())
10930 }
10931 fn write_all(&mut self, bytes: impl Into<Vec<u8>>) -> &mut Self {
10932 self.0.extend_from_slice(&bytes.into());
10933 self
10934 }
10935 fn finalize(self) -> Vec<u8> {
10936 self.0
10937 }
10938 }
10939
10940 // Fail-before-pass-after byte-parity pin on the newly lifted
10941 // `impl From<RestartStrategy> for Vec<u8>` and
10942 // `impl From<&RestartStrategy> for Vec<u8>` — asserts the trait-
10943 // idiomatic byte-owned reverse-projection standard-library
10944 // impls and the substrate-primitive
10945 // [`super::RestartStrategy::as_str`] `pub const fn` accessor's
10946 // `.as_bytes().to_vec()` byte-tail resolve to the same four-arm
10947 // PascalCase wire byte-string emit-set across every arm the
10948 // exhaustive [`super::RestartStrategy::ALL`] slice enumerates.
10949 // Extends the substrate-wide trait-idiomatic byte-owned
10950 // reverse-projection axis onto the first M2-OTP-shape closed-
10951 // set fieldless typed-enum peer on the caixa surface
10952 // (`:supervisor :estrategia`), matching the trajectory the
10953 // first-mover [`super::crate::CaixaKind`] lift (b245fd6), the
10954 // second-mover [`super::crate::dialeto::CaixaDialeto`] lift
10955 // (4cceaf5), and the third-mover
10956 // [`super::crate::dep::DepList`] lift (e974ca2) established
10957 // across the caixa-core-internal tier.
10958 for &variant in RestartStrategy::ALL {
10959 let via_owned_from: Vec<u8> = <Vec<u8> as From<RestartStrategy>>::from(variant);
10960 let via_borrowed_from: Vec<u8> = <Vec<u8> as From<&RestartStrategy>>::from(&variant);
10961 let via_method_bytes: Vec<u8> = variant.as_str().as_bytes().to_vec();
10962 assert_eq!(
10963 via_owned_from, via_method_bytes,
10964 "From<RestartStrategy> for Vec<u8> impl must byte-equal \
10965 RestartStrategy::as_str().as_bytes().to_vec() on \
10966 RestartStrategy::{variant:?} — divergence signals a \
10967 silent detour off the substrate-primitive accessor"
10968 );
10969 assert_eq!(
10970 via_borrowed_from, via_method_bytes,
10971 "From<&RestartStrategy> for Vec<u8> impl must byte-\
10972 equal RestartStrategy::as_str().as_bytes().to_vec() \
10973 on RestartStrategy::{variant:?} — divergence signals \
10974 a silent detour off the substrate-primitive accessor"
10975 );
10976 assert_eq!(
10977 via_owned_from, via_borrowed_from,
10978 "From<RestartStrategy> for Vec<u8> and \
10979 From<&RestartStrategy> for Vec<u8> must byte-equal \
10980 each other on RestartStrategy::{variant:?} — \
10981 divergence signals the owned-input and borrowed-input \
10982 paths have drifted off the same substrate-primitive \
10983 as_str accessor"
10984 );
10985 // Cross-axis witness against the paired [`AsRef<[u8]>`]
10986 // borrowed byte-view axis (cd4c4e0): the byte-owned
10987 // reverse-projection axis must byte-equal the paired
10988 // borrowed byte-view axis by construction — locking the
10989 // byte-view and byte-owned axes together at the substrate-
10990 // primitive accessor.
10991 let borrowed_bytes: &[u8] = <RestartStrategy as AsRef<[u8]>>::as_ref(&variant);
10992 assert_eq!(
10993 via_owned_from,
10994 borrowed_bytes.to_vec(),
10995 "From<RestartStrategy> for Vec<u8> and AsRef<[u8]> \
10996 for RestartStrategy must resolve to byte-equal byte-\
10997 tails on RestartStrategy::{variant:?} — divergence \
10998 signals the byte-owned and byte-view axes have \
10999 drifted off the same substrate-primitive as_str \
11000 accessor"
11001 );
11002 // Cross-axis witness against the str-owned reverse-
11003 // projection family's `.into_bytes()` / `.as_bytes().to_vec()`
11004 // byte-tails: every one of `{String, Cow<'static, str>,
11005 // Box<str>, std::sync::Arc<str>, std::rc::Rc<str>}`
11006 // allocates (or borrows) the same PascalCase wire byte-
11007 // string the substrate-primitive accessor emits, so the
11008 // byte-owned axis must byte-equal each of their owned
11009 // byte-tails by construction.
11010 let owned_string: String = <String as From<RestartStrategy>>::from(variant);
11011 assert_eq!(
11012 via_owned_from,
11013 owned_string.into_bytes(),
11014 "From<RestartStrategy> for Vec<u8> and \
11015 String::from(strategy).into_bytes() must resolve to \
11016 byte-equal byte-tails on RestartStrategy::{variant:?}"
11017 );
11018 let owned_cow: std::borrow::Cow<'static, str> =
11019 <std::borrow::Cow<'static, str> as From<RestartStrategy>>::from(variant);
11020 assert_eq!(
11021 via_owned_from,
11022 owned_cow.as_bytes().to_vec(),
11023 "From<RestartStrategy> for Vec<u8> and \
11024 From<RestartStrategy> for Cow<'static, str> must \
11025 resolve to byte-equal byte-tails on \
11026 RestartStrategy::{variant:?}"
11027 );
11028 let owned_box: Box<str> = <Box<str> as From<RestartStrategy>>::from(variant);
11029 assert_eq!(
11030 via_owned_from,
11031 owned_box.as_bytes().to_vec(),
11032 "From<RestartStrategy> for Vec<u8> and \
11033 From<RestartStrategy> for Box<str> must resolve to \
11034 byte-equal byte-tails on RestartStrategy::{variant:?}"
11035 );
11036 let owned_arc: std::sync::Arc<str> =
11037 <std::sync::Arc<str> as From<RestartStrategy>>::from(variant);
11038 assert_eq!(
11039 via_owned_from,
11040 owned_arc.as_bytes().to_vec(),
11041 "From<RestartStrategy> for Vec<u8> and \
11042 From<RestartStrategy> for std::sync::Arc<str> must \
11043 resolve to byte-equal byte-tails on \
11044 RestartStrategy::{variant:?}"
11045 );
11046 }
11047 // `<T: Into<Vec<u8>>>`-bound-consumer witness on both owned
11048 // and borrowed input shapes: the generic owned-byte-input
11049 // function `generic_owned_bytes_sink` (lifted above per
11050 // `clippy::items_after_statements`) accepts a
11051 // [`super::RestartStrategy`] and a `&RestartStrategy`
11052 // directly through the trait bound, without the caller open-
11053 // coding the three-hop `strategy.as_str().as_bytes().to_vec()`
11054 // composition.
11055 for &variant in RestartStrategy::ALL {
11056 let via_generic_owned = generic_owned_bytes_sink(variant);
11057 // Bind the borrowed-input path through an explicit
11058 // `&RestartStrategy` local so the generic-consumer witness
11059 // routes through `From<&RestartStrategy> for Vec<u8>` (T
11060 // binds to `&RestartStrategy`) rather than clippy-collapsing
11061 // the borrow onto the owned-input peer.
11062 let variant_ref: &RestartStrategy = &variant;
11063 let via_generic_borrowed = generic_owned_bytes_sink(variant_ref);
11064 let via_method_bytes = variant.as_str().as_bytes().to_vec();
11065 assert_eq!(
11066 via_generic_owned, via_method_bytes,
11067 "generic `<T: Into<Vec<u8>>>`-bound consumer on \
11068 RestartStrategy::{variant:?} must yield the same byte-\
11069 tail RestartStrategy::as_str().as_bytes() returns — \
11070 divergence signals the byte-owned axis fails to bridge \
11071 a generic owned-byte-input trait bound to the \
11072 substrate-primitive accessor"
11073 );
11074 assert_eq!(
11075 via_generic_borrowed, via_method_bytes,
11076 "generic `<T: Into<Vec<u8>>>`-bound consumer on \
11077 &RestartStrategy::{variant:?} must yield the same byte-\
11078 tail RestartStrategy::as_str().as_bytes() returns — \
11079 the borrowed-input surface must resolve to the same \
11080 as_str dispatch"
11081 );
11082 }
11083 // `std::io::Write::write_all`-shape owned-byte-sink surface
11084 // witness: the `MockOwnedByteSink` (lifted above per
11085 // `clippy::items_after_statements`) mirrors
11086 // `std::io::Write::write_all` /
11087 // `bytes::BytesMut::extend_from_slice`'s `impl Into<Vec<u8>>`-
11088 // bound owned-byte input signature and accepts a
11089 // [`super::RestartStrategy`] directly on both owned and
11090 // borrowed input shapes, routing its byte-tail through the
11091 // substrate-primitive `as_str` accessor — the shape a future
11092 // per-supervisor per-`:estrategia` audit-log emit composes to
11093 // fold an `:estrategia` discriminator byte-tag into a
11094 // downstream owned-byte-sink surface.
11095 for &variant in RestartStrategy::ALL {
11096 let mut owned_sink = MockOwnedByteSink::new();
11097 owned_sink.write_all(variant);
11098 let owned_folded = owned_sink.finalize();
11099 assert_eq!(
11100 owned_folded,
11101 variant.as_str().as_bytes(),
11102 "`sink.write_all(strategy)`-shape composition on \
11103 RestartStrategy::{variant:?} must fold the same byte-\
11104 tail RestartStrategy::as_str().as_bytes() returns"
11105 );
11106 let mut borrowed_sink = MockOwnedByteSink::new();
11107 let variant_ref: &RestartStrategy = &variant;
11108 borrowed_sink.write_all(variant_ref);
11109 let borrowed_folded = borrowed_sink.finalize();
11110 assert_eq!(
11111 borrowed_folded,
11112 variant.as_str().as_bytes(),
11113 "`sink.write_all(&strategy)`-shape composition on \
11114 &RestartStrategy::{variant:?} must fold the same byte-\
11115 tail RestartStrategy::as_str().as_bytes() returns — \
11116 the borrowed-input surface must resolve to the same \
11117 as_str dispatch"
11118 );
11119 }
11120 }
11121
11122 #[test]
11123 fn restart_policy_try_from_str_routes_through_from_wire_accessor() {
11124 // Fail-before-pass-after byte-parity pin on the newly lifted
11125 // `impl TryFrom<&str> for RestartPolicy` — asserts the standard-
11126 // library trait impl and the substrate-primitive
11127 // [`RestartPolicy::from_wire`] `Option<Self>` accessor resolve to
11128 // the same three-arm accept-set across every arm the exhaustive
11129 // [`RestartPolicy::ALL`] slice enumerates. Any future silent
11130 // detour that routes the trait impl through a divergent
11131 // projection (a per-arm inline `match s { "Permanent" =>
11132 // Ok(Self::Permanent), … }` re-inlining that opens a compile-time
11133 // link to the un-lifted arm-literal, a hypothetical
11134 // `#[serde(rename_all = "…")]` attribute drift that silently
11135 // splits the wire byte-string from every consumer that reaches
11136 // for this typed dispatch, an accidental swap onto the kebab-case
11137 // dispatcher-catalog axis the pre-existing [`std::str::FromStr`]
11138 // impl parses through and which would collide the two-axis
11139 // wire/catalog split the sibling [`RestartPolicy::from_wire`]
11140 // doc block makes load-bearing) trips at caixa-core test time
11141 // under `assert_eq!` rather than at a downstream
11142 // `impl TryFrom<&str>`-bound consumer's silent split. Sweeps
11143 // every one of the three arms [`RestartPolicy::ALL`] carries so
11144 // no arm's projection is covered only by the sibling method-
11145 // named `from_wire` path. Peer of the sibling
11146 // [`restart_strategy_try_from_str_routes_through_from_wire_accessor`]
11147 // (5b828ed) — extends the trait-idiomatic reverse-projection
11148 // axis onto the third and final M2-OTP-shape closed-set typed
11149 // enum on the caixa surface (the paired per-child restart-
11150 // decision-policy sibling on the same M2 `:supervisor` slot).
11151 for &variant in RestartPolicy::ALL {
11152 let wire = variant.as_str();
11153 assert_eq!(
11154 <RestartPolicy as TryFrom<&str>>::try_from(wire),
11155 Ok(variant),
11156 "TryFrom<&str> impl on RestartPolicy must round-trip \
11157 RestartPolicy::{variant:?}.as_str() = {wire:?} back to \
11158 Ok(RestartPolicy::{variant:?}) — divergence from \
11159 RestartPolicy::from_wire signals a silent detour off \
11160 the substrate-primitive accessor"
11161 );
11162 assert_eq!(
11163 <RestartPolicy as TryFrom<&str>>::try_from(wire).ok(),
11164 RestartPolicy::from_wire(wire),
11165 "TryFrom<&str> ok()-projection on {wire:?} must byte-\
11166 equal RestartPolicy::from_wire on the same input"
11167 );
11168 }
11169 }
11170
11171 #[test]
11172 fn restart_policy_try_from_str_rejects_unknown_byte_strings() {
11173 // Rejection witness on the `impl TryFrom<&str> for
11174 // RestartPolicy` — sweeps a candidate set of byte-strings
11175 // outside the three-arm PascalCase wire accept-set the sibling
11176 // [`RestartPolicy::as_str`] emits and asserts every one lands on
11177 // `Err(())`, so a future accidental widening of the trait impl's
11178 // accept-set (a stray additional
11179 // `_ if s.eq_ignore_ascii_case("Permanent") => Ok(…)` case-fold
11180 // path, a silent inclusion of the kebab-case dispatcher-catalog
11181 // byte-string the pre-existing [`std::str::FromStr`] impl the
11182 // [`gen_platform::FromStrKind`] derive installs parses onto the
11183 // wire axis — which would collide the two-axis
11184 // wire/dispatcher-catalog split the sibling
11185 // [`RestartPolicy::from_wire`] doc block makes load-bearing —
11186 // an English-rebrand or plural-arm silent alias that would widen
11187 // the wire accept-set past the OTP-canonical three) trips at
11188 // caixa-core test time. The candidate set includes the empty
11189 // string, whitespace-only padding, the kebab-case dispatcher-
11190 // catalog byte-strings on the sibling axis (a caller who
11191 // confuses the two axes trips here rather than at a downstream
11192 // consumer's silent reject), a lowercase / uppercase / mixed-case
11193 // fold of each PascalCase arm (a caller who assumes case-fold
11194 // acceptance trips here), leading/trailing whitespace padding,
11195 // the trailing-newline shape, quote-wrapped candidates, and a
11196 // residual set of plausible-but-wrong English rebrand
11197 // candidates. Peer of the sibling
11198 // [`restart_strategy_try_from_str_rejects_unknown_byte_strings`]
11199 // (5b828ed) rejection witness.
11200 let rejected: &[&str] = &[
11201 "",
11202 " ",
11203 "\n",
11204 "\t",
11205 "permanent",
11206 "temporary",
11207 "transient",
11208 "PERMANENT",
11209 "TEMPORARY",
11210 "TRANSIENT",
11211 "Permanents",
11212 "Permanent ",
11213 " Permanent",
11214 " Temporary ",
11215 "Permanent\n",
11216 "Transient\t",
11217 "\"Permanent\"",
11218 "Ephemeral",
11219 "Always",
11220 "Never",
11221 "OnAbnormalExit",
11222 "intrinsic",
11223 "?",
11224 ];
11225 for &input in rejected {
11226 assert_eq!(
11227 <RestartPolicy as TryFrom<&str>>::try_from(input),
11228 Err(()),
11229 "TryFrom<&str> impl on RestartPolicy must reject the \
11230 non-wire byte-string {input:?} — silent acceptance \
11231 signals an accept-set widening off the paired \
11232 RestartPolicy::from_wire resolver"
11233 );
11234 }
11235 }
11236
11237 #[test]
11238 fn restart_policy_try_from_str_and_from_wire_partition_the_accept_set() {
11239 // Cross-axis partition pin: the paired `TryFrom<&str>` and
11240 // `from_wire` reverse projections must resolve identically on
11241 // *every* input, not just the ones [`RestartPolicy::ALL`]
11242 // enumerates. Sweeps a mixed candidate set spanning accepted
11243 // (three-arm PascalCase wire byte-strings) and rejected (kebab-
11244 // case dispatcher-catalog byte-strings, empty, whitespace-
11245 // padded, quoted, English-rebrand candidates) inputs and asserts
11246 // the trait's `Result::ok()` projection byte-equals the method-
11247 // named resolver's `Option<Self>` return-shape on each, locking
11248 // the two paths together by construction so any future detour
11249 // (a stray `try_from` special-case that widens or narrows the
11250 // accept-set outside the paired `from_wire` resolver, an
11251 // accidental swap onto the kebab-case [`std::str::FromStr`]
11252 // impl the [`gen_platform::FromStrKind`] derive installs on the
11253 // sibling dispatcher-catalog axis) trips at caixa-core test
11254 // time. Peer of the sibling
11255 // [`restart_strategy_try_from_str_and_from_wire_partition_the_accept_set`]
11256 // pin — extends the round-trip discipline onto the M2-OTP-shape
11257 // per-child restart-policy axis.
11258 let candidates: &[&str] = &[
11259 "Permanent",
11260 "Temporary",
11261 "Transient",
11262 "",
11263 "permanent",
11264 "temporary",
11265 "transient",
11266 "PERMANENT",
11267 "unknown",
11268 "Permanent ",
11269 " Permanent",
11270 "\"Permanent\"",
11271 "Ephemeral",
11272 "OnAbnormalExit",
11273 "?",
11274 ];
11275 for &input in candidates {
11276 let via_trait: Option<RestartPolicy> =
11277 <RestartPolicy as TryFrom<&str>>::try_from(input).ok();
11278 let via_method: Option<RestartPolicy> = RestartPolicy::from_wire(input);
11279 assert_eq!(
11280 via_trait, via_method,
11281 "TryFrom<&str> and from_wire must resolve identically on \
11282 input {input:?} — divergence signals the two reverse-\
11283 projection paths have drifted onto different accept-sets"
11284 );
11285 }
11286 }
11287
11288 #[test]
11289 fn restart_policy_from_into_static_str_routes_through_as_str_accessor() {
11290 // Fail-before-pass-after byte-parity pin on the newly lifted
11291 // `impl From<RestartPolicy> for &'static str` — asserts the
11292 // standard-library trait impl and the substrate-primitive
11293 // [`RestartPolicy::as_str`] `pub const fn` accessor resolve to
11294 // the same three-arm emit-set across every arm the exhaustive
11295 // [`RestartPolicy::ALL`] slice enumerates. Any future silent
11296 // detour that routes the trait impl through a divergent
11297 // projection (a per-arm inline `match policy { Permanent =>
11298 // "Permanent", … }` re-inlining that opens a compile-time link
11299 // to the un-lifted arm-literal, an accidental swap onto the
11300 // sibling kebab-case [`Self::discriminant`] dispatcher-catalog
11301 // axis that would collide the two-axis wire/catalog split the
11302 // sibling [`RestartPolicy::from_wire`] doc block makes
11303 // load-bearing) trips at caixa-core test time under
11304 // `assert_eq!` rather than at a downstream
11305 // `impl Into<&'static str>`-bound consumer's silent split.
11306 // Sweeps every one of the three arms [`RestartPolicy::ALL`]
11307 // carries so no arm's projection is covered only by the sibling
11308 // method-named `as_str` / [`std::fmt::Display`] / [`AsRef<str>`]
11309 // paths. Materializes the `<&'static str as
11310 // From<RestartPolicy>>::from` output in a `const`-shape binding
11311 // to make the `'static` lifetime promise a build-time invariant
11312 // — a future accidental downgrade of any of the three arms'
11313 // [`crate::render::SUPERVISOR_CHILD_RESTART_*`] constants to a
11314 // non-`&'static str` (a `String::leak()`-produced return, a
11315 // `Box::leak`-cast) trips at caixa-core build time rather than
11316 // at a downstream `'static`-bound consumer. Peer of the sibling
11317 // [`restart_strategy_from_into_static_str_routes_through_as_str_accessor`]
11318 // (523157d) — extends the trait-idiomatic forward-projection
11319 // axis onto the second (and second-of-two-in-M2) closed-set
11320 // typed enum on the caixa surface (the paired per-child
11321 // restart-decision-policy sibling on the same M2 `:supervisor`
11322 // slot).
11323 const PERMANENT: &str = RestartPolicy::Permanent.as_str();
11324 const TEMPORARY: &str = RestartPolicy::Temporary.as_str();
11325 const TRANSIENT: &str = RestartPolicy::Transient.as_str();
11326 for &variant in RestartPolicy::ALL {
11327 let via_trait: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
11328 let via_method: &'static str = variant.as_str();
11329 assert_eq!(
11330 via_trait, via_method,
11331 "From<RestartPolicy> for &'static str impl must round-trip \
11332 RestartPolicy::{variant:?} to the same lifted \
11333 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str returns — \
11334 divergence signals a silent detour off the substrate-primitive \
11335 accessor"
11336 );
11337 let via_into: &'static str = variant.into();
11338 assert_eq!(
11339 via_into, via_method,
11340 "Into<&'static str>::into on RestartPolicy::{variant:?} must \
11341 byte-equal RestartPolicy::as_str on the same input — the \
11342 blanket-derived Into shape must resolve to the same as_str \
11343 dispatch as the explicit From impl"
11344 );
11345 }
11346 assert_eq!(
11347 [PERMANENT, TEMPORARY, TRANSIENT],
11348 [
11349 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
11350 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
11351 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
11352 ],
11353 "const-context RestartPolicy::as_str must resolve to the three \
11354 lifted SUPERVISOR_CHILD_RESTART_* consts — a future accidental \
11355 downgrade of any arm to a non-const or non-static byte-string \
11356 breaks the `&'static str`-lifetime promise the paired \
11357 From<RestartPolicy> for &'static str impl carries by \
11358 construction"
11359 );
11360 }
11361
11362 #[test]
11363 fn restart_policy_from_into_static_str_and_as_str_partition_the_emit_set() {
11364 // Cross-axis partition pin: the paired trait-idiomatic
11365 // `From<RestartPolicy> for &'static str` forward projection and
11366 // the method-named [`RestartPolicy::as_str`] forward projection
11367 // must resolve identically on *every* arm, not just the ones
11368 // named in the primary byte-parity pin above. Sweeps every
11369 // [`RestartPolicy::ALL`] arm and asserts the trait's `From::from`
11370 // output byte-equals the method-named accessor's return-value on
11371 // each, locking the two forward-projection paths together by
11372 // construction so any future detour (a stray `From` special-case
11373 // that lands on a divergent per-arm literal outside the paired
11374 // `as_str` dispatch, a hypothetical rebrand touching one axis
11375 // without the other) trips at caixa-core test time. Peer of the
11376 // sibling forward-projection partition pin
11377 // [`restart_strategy_from_into_static_str_and_as_str_partition_the_emit_set`]
11378 // (523157d) — extends the round-trip discipline onto the
11379 // second-of-two M2-OTP-shape closed-set typed enum on the caixa
11380 // surface, closing the two-way `Self ↔ &'static str` round-trip
11381 // on the trait-idiomatic pair (`From<Self> for &'static str` +
11382 // `TryFrom<&str> for Self`) as well as the pre-existing method-
11383 // named pair (`as_str` + `from_wire`).
11384 for &variant in RestartPolicy::ALL {
11385 let via_trait: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
11386 let via_method: &'static str = variant.as_str();
11387 assert_eq!(
11388 via_trait, via_method,
11389 "From<RestartPolicy> for &'static str and \
11390 RestartPolicy::as_str must resolve identically on \
11391 RestartPolicy::{variant:?} — divergence signals the \
11392 two forward-projection paths have drifted onto different \
11393 emit-sets"
11394 );
11395 }
11396 // Round-trip witness: every arm's forward `From` output re-parses
11397 // through the paired trait-idiomatic reverse `TryFrom<&str>` back
11398 // to the original variant. Closes the two-way `RestartPolicy ↔
11399 // &'static str` round-trip on the trait-idiomatic axis pair,
11400 // mirroring the pre-existing method-named `as_str` + `from_wire`
11401 // round-trip on the substrate-primitive axis pair.
11402 for &variant in RestartPolicy::ALL {
11403 let emitted: &'static str = variant.into();
11404 let re_parsed: Result<RestartPolicy, ()> =
11405 <RestartPolicy as TryFrom<&str>>::try_from(emitted);
11406 assert_eq!(
11407 re_parsed,
11408 Ok(variant),
11409 "trait-idiomatic axis pair must round-trip \
11410 RestartPolicy::{variant:?} through `.into::<&'static \
11411 str>()` and back through `TryFrom<&str>` — a break signals \
11412 the forward-emit and reverse-parse axes have drifted onto \
11413 different vocabularies"
11414 );
11415 }
11416 }
11417
11418 #[test]
11419 fn restart_policy_from_borrowed_into_static_str_routes_through_as_str_accessor() {
11420 // Fail-before-pass-after byte-parity pin on the newly lifted
11421 // `impl From<&RestartPolicy> for &'static str` — asserts the
11422 // borrowed-input standard-library trait impl and the substrate-
11423 // primitive [`RestartPolicy::as_str`] `pub const fn` accessor
11424 // resolve to the same three-arm emit-set across every arm the
11425 // exhaustive [`RestartPolicy::ALL`] slice enumerates. Rust's
11426 // `From` trait does not auto-derive the borrowed-input sibling
11427 // from a paired owned-input impl (no `impl<T, U> From<&T> for U
11428 // where T: Copy, U: From<T>` blanket in `core`), so the
11429 // borrowed-input axis is a distinct trait-idiomatic surface
11430 // that a `.iter().map(Into::into)` shape over
11431 // [`RestartPolicy::ALL`] (whose iterator yields
11432 // `&RestartPolicy`, not `RestartPolicy`) reaches through this
11433 // impl and no other — the paired owned-input
11434 // [`From<RestartPolicy>`] impl requires an explicit `.copied()`
11435 // / dereference before the trait fires. Materializes the
11436 // `<&'static str as From<&RestartPolicy>>::from` output in a
11437 // `const`-shape binding to make the `'static` lifetime promise
11438 // a build-time invariant.
11439 const PERMANENT: &str = RestartPolicy::Permanent.as_str();
11440 const TEMPORARY: &str = RestartPolicy::Temporary.as_str();
11441 const TRANSIENT: &str = RestartPolicy::Transient.as_str();
11442 for variant in RestartPolicy::ALL {
11443 let via_trait: &'static str = <&'static str as From<&RestartPolicy>>::from(variant);
11444 let via_method: &'static str = variant.as_str();
11445 assert_eq!(
11446 via_trait, via_method,
11447 "From<&RestartPolicy> for &'static str impl must round-trip \
11448 &RestartPolicy::{variant:?} to the same lifted \
11449 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str \
11450 returns — divergence signals a silent detour off the \
11451 substrate-primitive accessor"
11452 );
11453 let via_into: &'static str = variant.into();
11454 assert_eq!(
11455 via_into, via_method,
11456 "Into<&'static str>::into on &RestartPolicy::{variant:?} \
11457 must byte-equal RestartPolicy::as_str on the same input — \
11458 the blanket-derived Into shape must resolve to the same \
11459 as_str dispatch as the explicit From impl"
11460 );
11461 }
11462 assert_eq!(
11463 [PERMANENT, TEMPORARY, TRANSIENT],
11464 [
11465 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
11466 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
11467 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
11468 ],
11469 "const-context RestartPolicy::as_str must resolve to the three \
11470 lifted SUPERVISOR_CHILD_RESTART_* consts — the borrowed-input \
11471 From<&RestartPolicy> for &'static str impl inherits its \
11472 `'static` lifetime promise from the same accessor the \
11473 owned-input sibling routes through"
11474 );
11475 }
11476
11477 #[test]
11478 fn restart_policy_from_owned_and_borrowed_into_static_str_agree_on_every_arm() {
11479 // Cross-axis partition pin: the paired trait-idiomatic
11480 // owned-input `From<RestartPolicy> for &'static str` (9fb37d0
11481 // campaign-shape) and borrowed-input `From<&RestartPolicy> for
11482 // &'static str` (this lift) forward projections must resolve
11483 // identically on every arm, locking the two input-shape paths
11484 // together so any future detour trips at caixa-core test time.
11485 // Then a witness that a `.iter().map(Into::into)` pipe over
11486 // [`RestartPolicy::ALL`] (whose iterator yields
11487 // `&RestartPolicy`) materializes the three-arm accept-set
11488 // through the borrowed-input axis alone — the exact shape a
11489 // future wasm-operator per-child post-exit restart-decision
11490 // diagnostic line, a future substrate-wide per-arm diagnostic
11491 // column, or a
11492 // `HashMap::<&'static str, RestartPolicy>::from_iter(
11493 // RestartPolicy::ALL.iter().map(|p| (p.into(), *p)))`-style
11494 // per-policy lookup reaches through — closing the two-way
11495 // owned/borrowed input-shape symmetry on the forward-projection
11496 // trait-idiomatic axis. Peer of the sibling
11497 // [`crate::dep::tests::dep_list_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
11498 // (64aa742) /
11499 // [`crate::kind::tests::caixa_kind_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
11500 // (5ab993a) /
11501 // [`crate::dialeto::tests::caixa_dialeto_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
11502 // (807b0b5) /
11503 // [`restart_strategy_from_owned_and_borrowed_into_static_str_agree_on_every_arm`]
11504 // (e941836) partition pins on the sibling closed-set typed-enum
11505 // discriminator axes — extends the borrowed-input axis
11506 // discipline onto the second-of-two M2 OTP-shape closed-set
11507 // typed enum on the caixa surface (per-child restart-decision
11508 // policy). Also closes the direct two-way `&Self → &'static
11509 // str → Self` round-trip via the paired [`TryFrom<&str>`] axis
11510 // — unlike the peer [`crate::CaixaKind`] axis pair (whose
11511 // forward `From` emits lowercase Portuguese diagnostic bytes
11512 // while the reverse `TryFrom` parses `PascalCase` wire bytes,
11513 // forcing the round-trip through an intermediate wire-vocab
11514 // hop), the [`RestartPolicy::as_str`] emit and
11515 // [`RestartPolicy::from_wire`] parse share the same
11516 // `PascalCase` vocabulary by construction, so the borrowed-
11517 // input forward axis and the reverse axis compose directly.
11518 for &variant in RestartPolicy::ALL {
11519 let owned: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
11520 let borrowed: &'static str = <&'static str as From<&RestartPolicy>>::from(&variant);
11521 assert_eq!(
11522 owned, borrowed,
11523 "From<RestartPolicy> and From<&RestartPolicy> for \
11524 &'static str must resolve identically on \
11525 RestartPolicy::{variant:?} — divergence signals the \
11526 owned-input and borrowed-input forward-projection paths \
11527 have drifted onto different emit-sets"
11528 );
11529 }
11530 let via_iter: Vec<&'static str> = RestartPolicy::ALL.iter().map(Into::into).collect();
11531 let via_method: Vec<&'static str> = RestartPolicy::ALL.iter().map(|p| p.as_str()).collect();
11532 assert_eq!(
11533 via_iter, via_method,
11534 "`.iter().map(Into::into)` over RestartPolicy::ALL must \
11535 byte-equal `.iter().map(|p| p.as_str())` on every arm — the \
11536 borrowed-input `From<&RestartPolicy> for &'static str` axis \
11537 is what makes the `.iter().map(Into::into)` shape route \
11538 through the substrate-primitive `RestartPolicy::as_str` \
11539 accessor rather than through a per-call-site `.copied()` / \
11540 dereference detour"
11541 );
11542 for variant in RestartPolicy::ALL {
11543 let emitted: &'static str = variant.into();
11544 let re_parsed: Result<RestartPolicy, ()> =
11545 <RestartPolicy as TryFrom<&str>>::try_from(emitted);
11546 assert_eq!(
11547 re_parsed,
11548 Ok(*variant),
11549 "trait-idiomatic borrowed-input forward-projection + \
11550 reverse-projection axis pair must round-trip \
11551 &RestartPolicy::{variant:?} through `.into::<&'static \
11552 str>()` (via the borrowed-input axis) and back through \
11553 `TryFrom<&str>` — a break signals the borrowed-input \
11554 forward-emit and reverse-parse axes have drifted onto \
11555 different vocabularies"
11556 );
11557 }
11558 }
11559
11560 #[test]
11561 fn restart_policy_from_into_owned_string_routes_through_as_str_accessor() {
11562 // Fail-before-pass-after byte-parity pin on the newly lifted
11563 // `impl From<RestartPolicy> for String` — asserts the
11564 // owned-`String`-returning standard-library trait impl and the
11565 // substrate-primitive [`RestartPolicy::as_str`] `pub const fn`
11566 // accessor resolve to the same three-arm emit-set across every
11567 // arm the exhaustive [`RestartPolicy::ALL`] slice enumerates.
11568 // Rust's standard library does not carry a blanket
11569 // `impl<T: AsRef<str>> From<T> for String` (nor an
11570 // `impl<T: fmt::Display> From<T> for String`), so the
11571 // owned-`String` forward-projection axis is a distinct
11572 // trait-idiomatic surface that a `let key: String =
11573 // policy.into();`-shaped call site reaches through this impl
11574 // and no other — the paired sibling `From<RestartPolicy> for
11575 // &'static str` impl forces every owned-`String` call site
11576 // through an explicit `.to_owned()` / `String::from`
11577 // restatement. Peer of the first-mover
11578 // [`restart_strategy_from_into_owned_string_routes_through_as_str_accessor`]
11579 // (7baa18a) — extends the trait-idiomatic owned-`String`
11580 // forward-projection axis onto the second-of-two M2 OTP-shape
11581 // closed-set typed enums on the caixa surface (per-child
11582 // restart-decision-policy sibling on the same M2 `:supervisor`
11583 // slot).
11584 for &variant in RestartPolicy::ALL {
11585 let via_trait: String = <String as From<RestartPolicy>>::from(variant);
11586 let via_method: &'static str = variant.as_str();
11587 assert_eq!(
11588 via_trait.as_str(),
11589 via_method,
11590 "From<RestartPolicy> for String impl must round-trip \
11591 RestartPolicy::{variant:?} to the same lifted \
11592 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str \
11593 returns — divergence signals a silent detour off the \
11594 substrate-primitive accessor"
11595 );
11596 let via_into: String = variant.into();
11597 assert_eq!(
11598 via_into.as_str(),
11599 via_method,
11600 "Into<String>::into on RestartPolicy::{variant:?} must \
11601 byte-equal RestartPolicy::as_str on the same input — the \
11602 blanket-derived Into shape must resolve to the same as_str \
11603 dispatch as the explicit From impl"
11604 );
11605 }
11606 }
11607
11608 #[test]
11609 fn restart_policy_from_into_owned_string_and_static_str_agree_on_every_arm() {
11610 // Cross-axis partition pin: the paired trait-idiomatic
11611 // owned-`String` `From<RestartPolicy> for String` (this lift)
11612 // and owned-`&'static str` `From<RestartPolicy> for &'static
11613 // str` (9fb37d0) forward projections must resolve identically
11614 // on every arm, locking the two return-type-shape paths
11615 // together so any future detour trips at caixa-core test time.
11616 // Also byte-parity witness against the sibling
11617 // [`ToString::to_string`] surface routed through
11618 // [`std::fmt::Display`] — the three owned-heap-string paths
11619 // (`.into::<String>()`, `String::from`, `.to_string()`) must
11620 // resolve identically on every arm so a future consumer that
11621 // picks any of the three lands on the same lifted
11622 // SUPERVISOR_CHILD_RESTART_* const. Then a `.iter().copied()
11623 // .map(String::from)` pipe witness over [`RestartPolicy::ALL`]
11624 // that materializes the three-arm accept-set through the
11625 // owned-`String` axis alone — the exact shape a future
11626 // wasm-operator per-child post-exit restart-decision
11627 // diagnostic line composer or a
11628 // `HashMap::<String, RestartPolicy>::from_iter(
11629 // RestartPolicy::ALL.iter().copied().map(|p| (p.into(), p)))`-style
11630 // owned-key per-policy lookup reaches through — closing the
11631 // owned-`String` forward-projection axis's iterator-pipe
11632 // shape. Then a direct round-trip witness through the paired
11633 // trait-idiomatic reverse [`TryFrom<&str>`] axis on the
11634 // owned-`String`'s [`String::as_str`] borrow that closes the
11635 // two-way `Self → String → Self` round-trip on the trait-
11636 // idiomatic owned-`String` forward + reverse axis pair —
11637 // unlike the peer [`crate::CaixaKind`] axis pair (whose
11638 // forward `From` emits lowercase Portuguese diagnostic bytes
11639 // while the reverse `TryFrom` parses `PascalCase` wire bytes,
11640 // forcing the round-trip through an intermediate wire-vocab
11641 // hop), the [`RestartPolicy::as_str`] emit and
11642 // [`RestartPolicy::from_wire`] parse share the same
11643 // `PascalCase` vocabulary by construction, so the owned-
11644 // `String` forward axis and the reverse axis compose directly.
11645 for &variant in RestartPolicy::ALL {
11646 let owned_string: String = <String as From<RestartPolicy>>::from(variant);
11647 let owned_static: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
11648 assert_eq!(
11649 owned_string.as_str(),
11650 owned_static,
11651 "From<RestartPolicy> for String and From<RestartPolicy> \
11652 for &'static str must resolve identically on \
11653 RestartPolicy::{variant:?} — divergence signals the \
11654 owned-`String` and owned-`&'static str` forward-projection \
11655 return-type-shape paths have drifted onto different \
11656 emit-sets"
11657 );
11658 let via_to_string: String = variant.to_string();
11659 assert_eq!(
11660 owned_string, via_to_string,
11661 "From<RestartPolicy> for String must byte-equal \
11662 RestartPolicy::to_string on RestartPolicy::{variant:?} — \
11663 divergence signals the trait-idiomatic owned-`String` \
11664 forward-projection axis and the ToString-through-Display \
11665 axis have drifted onto different emit-sets"
11666 );
11667 }
11668 let via_iter: Vec<String> = RestartPolicy::ALL
11669 .iter()
11670 .copied()
11671 .map(String::from)
11672 .collect();
11673 let via_method: Vec<String> = RestartPolicy::ALL
11674 .iter()
11675 .map(|p| p.as_str().to_owned())
11676 .collect();
11677 assert_eq!(
11678 via_iter, via_method,
11679 "`.iter().copied().map(String::from)` over RestartPolicy::ALL \
11680 must byte-equal `.iter().map(|p| p.as_str().to_owned())` on \
11681 every arm — the owned-`String` `From<RestartPolicy> for \
11682 String` axis is what makes the `String::from` composition \
11683 route through the substrate-primitive `RestartPolicy::as_str` \
11684 accessor rather than through a per-call-site `.to_owned()` / \
11685 `String::from(policy.as_str())` detour"
11686 );
11687 for &variant in RestartPolicy::ALL {
11688 let emitted: String = variant.into();
11689 let re_parsed: Result<RestartPolicy, ()> =
11690 <RestartPolicy as TryFrom<&str>>::try_from(emitted.as_str());
11691 assert_eq!(
11692 re_parsed,
11693 Ok(variant),
11694 "trait-idiomatic owned-`String` forward-projection + \
11695 reverse-projection axis pair must round-trip \
11696 RestartPolicy::{variant:?} through `.into::<String>()` \
11697 and back through `TryFrom<&str>` on the owned-`String`'s \
11698 String::as_str borrow — a break signals the owned-`String` \
11699 forward-emit and reverse-parse axes have drifted onto \
11700 different vocabularies"
11701 );
11702 }
11703 }
11704
11705 #[test]
11706 fn restart_policy_from_into_borrowed_owned_string_routes_through_as_str_accessor() {
11707 // Fail-before-pass-after byte-parity pin on the newly lifted
11708 // `impl From<&RestartPolicy> for String` — asserts the
11709 // borrowed-input owned-`String`-returning standard-library
11710 // trait impl and the substrate-primitive
11711 // [`RestartPolicy::as_str`] `pub const fn` accessor resolve to
11712 // the same three-arm emit-set across every arm the exhaustive
11713 // [`RestartPolicy::ALL`] slice enumerates. Rust's standard
11714 // library does not carry a blanket `impl<T: AsRef<str>>
11715 // From<&T> for String` (nor an `impl<T: fmt::Display> From<&T>
11716 // for String`), so the borrowed-input owned-`String` forward-
11717 // projection axis is a distinct trait-idiomatic surface that a
11718 // `let key: String = (&policy).into();`-shaped call site
11719 // reaches through this impl and no other — the paired sibling
11720 // `From<RestartPolicy> for String` impl forces every borrowed-
11721 // input call site through an explicit `Copy` deref
11722 // (`String::from(*policy)`) or an `.as_str().to_owned()` /
11723 // `.to_string()` detour. Peer of the first-mover
11724 // [`restart_strategy_from_into_borrowed_owned_string_routes_through_as_str_accessor`]
11725 // (579385f) — extends the trait-idiomatic borrowed-input
11726 // owned-`String` forward-projection axis onto the second-of-
11727 // two M2 OTP-shape closed-set typed enums on the caixa surface
11728 // (per-child restart-decision-policy sibling on the same M2
11729 // `:supervisor` slot).
11730 for &variant in RestartPolicy::ALL {
11731 let via_trait: String = <String as From<&RestartPolicy>>::from(&variant);
11732 let via_method: &'static str = variant.as_str();
11733 assert_eq!(
11734 via_trait.as_str(),
11735 via_method,
11736 "From<&RestartPolicy> for String impl must round-trip \
11737 &RestartPolicy::{variant:?} to the same lifted \
11738 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str \
11739 returns — divergence signals a silent detour off the \
11740 substrate-primitive accessor"
11741 );
11742 let via_into: String = (&variant).into();
11743 assert_eq!(
11744 via_into.as_str(),
11745 via_method,
11746 "Into<String>::into on &RestartPolicy::{variant:?} must \
11747 byte-equal RestartPolicy::as_str on the same input — \
11748 the blanket-derived Into shape must resolve to the \
11749 same as_str dispatch as the explicit From impl"
11750 );
11751 }
11752 }
11753
11754 #[test]
11755 fn restart_policy_from_into_borrowed_owned_string_agrees_with_paired_axes_on_every_arm() {
11756 // Cross-axis partition pin: the newly lifted trait-idiomatic
11757 // borrowed-input owned-`String` `From<&RestartPolicy> for
11758 // String` (this lift), the paired owned-input owned-`String`
11759 // `From<RestartPolicy> for String` (7851725), the paired
11760 // borrowed-input owned-`&'static str` `From<&RestartPolicy>
11761 // for &'static str` (842c7f3), and the paired owned-input
11762 // owned-`&'static str` `From<RestartPolicy> for &'static str`
11763 // (9fb37d0) — every corner of the `{Self, &Self} × {&'static
11764 // str, String}` 2×2 trait-idiomatic projection family — must
11765 // resolve identically on every arm, locking the four
11766 // return-shape × input-shape paths together so any future
11767 // detour trips at caixa-core test time. Also byte-parity
11768 // witness against the sibling [`ToString::to_string`] surface
11769 // routed through [`std::fmt::Display`] and a direct round-trip
11770 // witness through the paired trait-idiomatic reverse
11771 // [`TryFrom<&str>`] axis on the owned-`String`'s
11772 // [`String::as_str`] borrow that closes the two-way
11773 // `&Self → String → Self` round-trip on the trait-idiomatic
11774 // borrowed-input owned-`String` forward + reverse axis pair.
11775 // Peer of the first-mover
11776 // [`restart_strategy_from_into_borrowed_owned_string_agrees_with_paired_axes_on_every_arm`]
11777 // (579385f) — closes the whole `{Self, &Self} × {&'static str,
11778 // String}` 2×2 projection corner on both M2 OTP-shape sibling
11779 // peers.
11780 for &variant in RestartPolicy::ALL {
11781 let borrowed_string: String = <String as From<&RestartPolicy>>::from(&variant);
11782 let owned_string: String = <String as From<RestartPolicy>>::from(variant);
11783 let borrowed_static: &'static str =
11784 <&'static str as From<&RestartPolicy>>::from(&variant);
11785 let owned_static: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
11786 assert_eq!(
11787 borrowed_string, owned_string,
11788 "From<&RestartPolicy> for String and From<RestartPolicy> \
11789 for String must resolve identically on \
11790 RestartPolicy::{variant:?} — divergence signals the \
11791 borrowed-input and owned-input owned-`String` \
11792 forward-projection input-shape paths have drifted onto \
11793 different emit-sets"
11794 );
11795 assert_eq!(
11796 borrowed_string.as_str(),
11797 borrowed_static,
11798 "From<&RestartPolicy> for String and From<&RestartPolicy> \
11799 for &'static str must resolve identically on \
11800 RestartPolicy::{variant:?} — divergence signals the \
11801 borrowed-input `&'static str` and owned-`String` \
11802 return-shape paths have drifted onto different \
11803 emit-sets"
11804 );
11805 assert_eq!(
11806 borrowed_string.as_str(),
11807 owned_static,
11808 "From<&RestartPolicy> for String and From<RestartPolicy> \
11809 for &'static str must resolve identically on \
11810 RestartPolicy::{variant:?} — divergence signals a \
11811 break in the diagonal corner of the {{Self, &Self}} × \
11812 {{&'static str, String}} 2×2 trait-idiomatic \
11813 projection family"
11814 );
11815 let via_to_string: String = variant.to_string();
11816 assert_eq!(
11817 borrowed_string, via_to_string,
11818 "From<&RestartPolicy> for String must byte-equal \
11819 RestartPolicy::to_string on RestartPolicy::{variant:?} \
11820 — divergence signals the trait-idiomatic borrowed-input \
11821 owned-`String` forward-projection axis and the \
11822 ToString-through-Display axis have drifted onto \
11823 different emit-sets"
11824 );
11825 }
11826 let via_iter: Vec<String> = RestartPolicy::ALL.iter().map(String::from).collect();
11827 let via_method: Vec<String> = RestartPolicy::ALL
11828 .iter()
11829 .map(|p| p.as_str().to_owned())
11830 .collect();
11831 assert_eq!(
11832 via_iter, via_method,
11833 "`.iter().map(String::from)` over RestartPolicy::ALL — a \
11834 call site whose iteration axis holds `&RestartPolicy` by \
11835 construction — must byte-equal `.iter().map(|p| \
11836 p.as_str().to_owned())` on every arm — the borrowed-input \
11837 owned-`String` `From<&RestartPolicy> for String` axis is \
11838 what makes the `String::from` composition route through \
11839 the substrate-primitive `RestartPolicy::as_str` accessor \
11840 without a spurious `Copy` deref (which would only be \
11841 reachable through the owned-input `From<RestartPolicy> \
11842 for String` axis by first calling `.copied()` on the \
11843 iterator)"
11844 );
11845 for &variant in RestartPolicy::ALL {
11846 let emitted: String = (&variant).into();
11847 let re_parsed: Result<RestartPolicy, ()> =
11848 <RestartPolicy as TryFrom<&str>>::try_from(emitted.as_str());
11849 assert_eq!(
11850 re_parsed,
11851 Ok(variant),
11852 "trait-idiomatic borrowed-input owned-`String` \
11853 forward-projection + reverse-projection axis pair must \
11854 round-trip &RestartPolicy::{variant:?} through \
11855 `.into::<String>()` on the borrowed-input surface and \
11856 back through `TryFrom<&str>` on the owned-`String`'s \
11857 String::as_str borrow — a break signals the \
11858 borrowed-input owned-`String` forward-emit and \
11859 reverse-parse axes have drifted onto different \
11860 vocabularies"
11861 );
11862 }
11863 }
11864
11865 #[test]
11866 fn restart_policy_from_into_static_cow_str_routes_through_as_str_accessor() {
11867 // Fail-before-pass-after byte-parity pin on the newly lifted
11868 // `impl From<RestartPolicy> for std::borrow::Cow<'static, str>` —
11869 // asserts the standard-library trait impl and the substrate-
11870 // primitive [`super::RestartPolicy::as_str`] `pub const fn`
11871 // accessor resolve to the same three-arm emit-set across every
11872 // arm the exhaustive [`super::RestartPolicy::ALL`] slice
11873 // enumerates. Rust's standard library does not carry a blanket
11874 // `impl<T: AsRef<str>> From<T> for Cow<'static, str>` (nor an
11875 // `impl<T: fmt::Display> From<T> for Cow<'static, str>`), so
11876 // the `Cow<'static, str>` forward-projection axis is a
11877 // distinct trait-idiomatic surface that a
11878 // `let key: Cow<'static, str> = policy.into();`-shaped call
11879 // site reaches through this impl and no other — the paired
11880 // sibling `From<RestartPolicy> for &'static str` and
11881 // `From<RestartPolicy> for String` impls force every
11882 // `Cow<'static, str>`-parameterized call site through a
11883 // `Cow::Borrowed(policy.as_str())` /
11884 // `Cow::Owned(policy.to_string())` composition whose type
11885 // bounds have no compile-time link back to the substrate
11886 // primitive.
11887 //
11888 // Also asserts the projection lands on the zero-alloc
11889 // [`std::borrow::Cow::Borrowed`] arm (not the
11890 // [`std::borrow::Cow::Owned`] arm) — the substrate-primitive
11891 // [`super::RestartPolicy::as_str`] accessor's `&'static str`
11892 // return lifetime by construction makes the borrowed arm the
11893 // type-correct projection with no runtime allocation. Any
11894 // future silent detour that routes the impl through the owned
11895 // arm (an accidental `Cow::Owned(policy.to_string())` rewrite
11896 // that would allocate on every call site where the
11897 // `&'static str` return of [`super::RestartPolicy::as_str`]
11898 // makes the zero-alloc borrowed projection type-correct) trips
11899 // at caixa-core test time under the
11900 // [`std::borrow::Cow::Borrowed`] discriminator witness rather
11901 // than at a downstream `Cow<'static, str>`-bound consumer's
11902 // silent allocation.
11903 //
11904 // Second peer on the substrate-wide trait-idiomatic
11905 // [`std::borrow::Cow<'static, str>`] forward-projection family
11906 // to extend the axis off the top-level [`super::CaixaKind`]
11907 // enum (99c1735 owned-input, d45c409 borrowed-input) onto the
11908 // second (and second-of-two-in-M2) M2 OTP-shape closed-set
11909 // fieldless typed enum peer on the caixa surface — closes the
11910 // M2 OTP-shape tier of the campaign on the owned-input axis
11911 // (both sibling peers, `RestartStrategy` and `RestartPolicy`,
11912 // now carry the owned-input Cow<'static, str> forward
11913 // projection).
11914 for &variant in RestartPolicy::ALL {
11915 let via_trait: std::borrow::Cow<'static, str> =
11916 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(variant);
11917 let via_method: &'static str = variant.as_str();
11918 assert_eq!(
11919 via_trait.as_ref(),
11920 via_method,
11921 "From<RestartPolicy> for Cow<'static, str> impl must \
11922 round-trip RestartPolicy::{variant:?} to the same \
11923 lifted SUPERVISOR_CHILD_RESTART_* const \
11924 RestartPolicy::as_str returns — divergence signals a \
11925 silent detour off the substrate-primitive accessor"
11926 );
11927 assert!(
11928 matches!(via_trait, std::borrow::Cow::Borrowed(_)),
11929 "From<RestartPolicy> for Cow<'static, str> impl must \
11930 land on the zero-alloc Cow::Borrowed arm on \
11931 RestartPolicy::{variant:?} — a Cow::Owned outcome \
11932 signals the projection has silently allocated where \
11933 the substrate-primitive RestartPolicy::as_str \
11934 `&'static str` return makes the borrowed arm the \
11935 type-correct projection"
11936 );
11937 let via_into: std::borrow::Cow<'static, str> = variant.into();
11938 assert_eq!(
11939 via_into.as_ref(),
11940 via_method,
11941 "Into<Cow<'static, str>>::into on \
11942 RestartPolicy::{variant:?} must byte-equal \
11943 RestartPolicy::as_str on the same input — the \
11944 blanket-derived Into shape must resolve to the same \
11945 as_str dispatch as the explicit From impl"
11946 );
11947 assert!(
11948 matches!(via_into, std::borrow::Cow::Borrowed(_)),
11949 "Into<Cow<'static, str>>::into on \
11950 RestartPolicy::{variant:?} must land on the \
11951 zero-alloc Cow::Borrowed arm — the blanket-derived \
11952 Into shape must resolve to the same Cow::Borrowed \
11953 dispatch as the explicit From impl"
11954 );
11955 }
11956 }
11957
11958 #[test]
11959 fn restart_policy_from_into_static_cow_str_agrees_with_paired_axes_on_every_arm() {
11960 // Cross-axis partition pin: the newly lifted trait-idiomatic
11961 // `From<RestartPolicy> for std::borrow::Cow<'static, str>`
11962 // (this lift), the paired owned-input `From<RestartPolicy>
11963 // for &'static str` (9fb37d0), and the paired owned-input
11964 // `From<RestartPolicy> for String` (7851725) forward
11965 // projections must resolve identically on every arm, locking
11966 // the three return-shape paths together by construction so any
11967 // future detour trips at caixa-core test time. Also byte-parity
11968 // witness against the sibling [`ToString::to_string`] surface
11969 // routed through [`std::fmt::Display`] — every owned-heap-
11970 // string path (the `Cow::Owned` promotion of this axis's
11971 // `.into_owned()`, `From<RestartPolicy> for String`, and
11972 // `.to_string()`) resolves to the same lifted
11973 // [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const per arm.
11974 //
11975 // Then a `.iter().copied().map(std::borrow::Cow::from)` pipe
11976 // witness over [`super::RestartPolicy::ALL`] that
11977 // materializes the three-arm accept-set through the
11978 // [`std::borrow::Cow<'static, str>`] axis alone — the exact
11979 // shape a future `axum::response::IntoResponse` per-policy
11980 // rejection-body composer, a future M4 admission-webhook
11981 // per-policy rejection-reason emitter whose typing rules out
11982 // the sibling [`AsRef<str>`] borrowed return, or a future
11983 // substrate-wide per-policy diagnostic surface that binds
11984 // through a [`Cow<'static, str>`] boundary reaches through.
11985 // The pipe witness also pins the zero-alloc discipline: every
11986 // element in the collected vector satisfies the
11987 // [`std::borrow::Cow::Borrowed`] arm predicate, so a future
11988 // accidental silent-allocation regression on the pipe's
11989 // iteration axis is a caixa-core-test-time failure. Peer of
11990 // the first-mover
11991 // [`restart_strategy_from_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
11992 // (7dd28b3) on the sibling M2 OTP-shape sibling-restart axis
11993 // — closes the whole owned-input `Cow<'static, str>` +
11994 // paired `{&'static str, String}` cross-axis-parity corner on
11995 // both M2 OTP-shape sibling peers.
11996 for &variant in RestartPolicy::ALL {
11997 let via_cow: std::borrow::Cow<'static, str> =
11998 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(variant);
11999 let via_static: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
12000 let via_string: String = <String as From<RestartPolicy>>::from(variant);
12001 assert_eq!(
12002 via_cow.as_ref(),
12003 via_static,
12004 "From<RestartPolicy> for Cow<'static, str> and \
12005 From<RestartPolicy> for &'static str must resolve \
12006 identically on RestartPolicy::{variant:?} — \
12007 divergence signals the Cow<'static, str> and \
12008 &'static str return-shape paths have drifted onto \
12009 different emit-sets"
12010 );
12011 assert_eq!(
12012 via_cow.as_ref(),
12013 via_string.as_str(),
12014 "From<RestartPolicy> for Cow<'static, str> and \
12015 From<RestartPolicy> for String must resolve \
12016 identically on RestartPolicy::{variant:?} — \
12017 divergence signals the Cow<'static, str> and String \
12018 return-shape paths have drifted onto different \
12019 emit-sets"
12020 );
12021 let via_to_string: String = variant.to_string();
12022 assert_eq!(
12023 via_cow.as_ref(),
12024 via_to_string.as_str(),
12025 "From<RestartPolicy> for Cow<'static, str> must \
12026 byte-equal RestartPolicy::to_string on \
12027 RestartPolicy::{variant:?} — divergence signals the \
12028 trait-idiomatic Cow<'static, str> forward-projection \
12029 axis and the ToString-through-Display axis have \
12030 drifted onto different emit-sets"
12031 );
12032 }
12033 let via_iter: Vec<std::borrow::Cow<'static, str>> = RestartPolicy::ALL
12034 .iter()
12035 .copied()
12036 .map(std::borrow::Cow::from)
12037 .collect();
12038 let via_method: Vec<std::borrow::Cow<'static, str>> = RestartPolicy::ALL
12039 .iter()
12040 .map(|p| std::borrow::Cow::Borrowed(p.as_str()))
12041 .collect();
12042 assert_eq!(
12043 via_iter, via_method,
12044 "`.iter().copied().map(Cow::from)` over \
12045 RestartPolicy::ALL must byte-equal `.iter().map(|p| \
12046 Cow::Borrowed(p.as_str()))` on every arm — the \
12047 trait-idiomatic `From<RestartPolicy> for Cow<'static, \
12048 str>` axis is what makes the `Cow::from` composition \
12049 route through the substrate-primitive \
12050 `RestartPolicy::as_str` accessor with the zero-alloc \
12051 Cow::Borrowed arm by construction, rather than a \
12052 per-call-site `Cow::Owned(policy.to_string())` \
12053 allocation"
12054 );
12055 for cow in &via_iter {
12056 assert!(
12057 matches!(cow, std::borrow::Cow::Borrowed(_)),
12058 "every element of the \
12059 .iter().copied().map(Cow::from) pipe over \
12060 RestartPolicy::ALL must land on the zero-alloc \
12061 Cow::Borrowed arm — a Cow::Owned outcome on any arm \
12062 signals the pipe's iteration axis has silently \
12063 allocated where the substrate-primitive \
12064 RestartPolicy::as_str `&'static str` return makes \
12065 the borrowed arm the type-correct projection"
12066 );
12067 }
12068 }
12069
12070 #[test]
12071 fn restart_policy_from_borrowed_into_static_cow_str_routes_through_as_str_accessor() {
12072 // Fail-before-pass-after byte-parity pin on the newly lifted
12073 // `impl From<&RestartPolicy> for std::borrow::Cow<'static, str>` —
12074 // asserts the borrowed-input standard-library trait impl and
12075 // the substrate-primitive [`super::RestartPolicy::as_str`]
12076 // `pub const fn` accessor resolve to the same three-arm emit-
12077 // set across every arm the exhaustive
12078 // [`super::RestartPolicy::ALL`] slice enumerates. Rust's
12079 // standard library does not carry a blanket
12080 // `impl<T: AsRef<str>> From<&T> for Cow<'static, str>` (nor a
12081 // `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`), so
12082 // the borrowed-input `Cow<'static, str>` forward-projection
12083 // axis is a distinct trait-idiomatic surface that a
12084 // `let key: Cow<'static, str> = (&policy).into();`-shaped
12085 // call site or a
12086 // `RestartPolicy::ALL.iter().map(Cow::from)`-shaped pipe
12087 // reaches through this impl and no other — the paired owned-
12088 // input `From<RestartPolicy> for Cow<'static, str>` impl
12089 // (0612398) forces every borrowed-input call site through an
12090 // explicit `Copy` deref (`Cow::from(*policy)`) or a
12091 // `Cow::Borrowed(policy.as_str())` open-code whose type
12092 // bounds have no compile-time link back to the substrate
12093 // primitive.
12094 //
12095 // Also asserts the projection lands on the zero-alloc
12096 // [`std::borrow::Cow::Borrowed`] arm (not the
12097 // [`std::borrow::Cow::Owned`] arm) — the substrate-primitive
12098 // [`super::RestartPolicy::as_str`] accessor's `&'static str`
12099 // return lifetime by construction makes the borrowed arm the
12100 // type-correct projection with no runtime allocation on the
12101 // borrowed-input surface just as on the paired owned-input
12102 // surface.
12103 //
12104 // Closes the `{Self, &Self}` input-shape corner on the M2
12105 // OTP-shape per-child-restart [`Cow<'static, str>`] axis on
12106 // the second-of-two-in-M2 closed-set fieldless typed enum peer
12107 // on the caixa surface (`:supervisor :children :restart`),
12108 // exactly as d45c409 closed it on the top-level
12109 // [`super::CaixaKind`] one commit after the owning half
12110 // (99c1735) landed and as 9b3e4b3 closed it on the sibling
12111 // M2 OTP-shape [`super::RestartStrategy`] one commit after
12112 // (7dd28b3) landed. This lift closes the whole M2 OTP-shape
12113 // tier of the substrate-wide Cow<'static, str> forward-
12114 // projection campaign on both input-shape corners
12115 // ({Self, &Self}) of both M2 OTP-shape sibling peers.
12116 for &variant in RestartPolicy::ALL {
12117 let via_trait: std::borrow::Cow<'static, str> =
12118 <std::borrow::Cow<'static, str> as From<&RestartPolicy>>::from(&variant);
12119 let via_method: &'static str = variant.as_str();
12120 assert_eq!(
12121 via_trait.as_ref(),
12122 via_method,
12123 "From<&RestartPolicy> for Cow<'static, str> impl must \
12124 round-trip &RestartPolicy::{variant:?} to the same \
12125 lifted SUPERVISOR_CHILD_RESTART_* const \
12126 RestartPolicy::as_str returns — divergence signals a \
12127 silent detour off the substrate-primitive accessor"
12128 );
12129 assert!(
12130 matches!(via_trait, std::borrow::Cow::Borrowed(_)),
12131 "From<&RestartPolicy> for Cow<'static, str> impl must \
12132 land on the zero-alloc Cow::Borrowed arm on \
12133 &RestartPolicy::{variant:?} — a Cow::Owned outcome \
12134 signals the projection has silently allocated where \
12135 the substrate-primitive RestartPolicy::as_str \
12136 `&'static str` return makes the borrowed arm the \
12137 type-correct projection"
12138 );
12139 let via_into: std::borrow::Cow<'static, str> = (&variant).into();
12140 assert_eq!(
12141 via_into.as_ref(),
12142 via_method,
12143 "Into<Cow<'static, str>>::into on \
12144 &RestartPolicy::{variant:?} must byte-equal \
12145 RestartPolicy::as_str on the same input — the \
12146 blanket-derived Into shape must resolve to the same \
12147 as_str dispatch as the explicit From impl"
12148 );
12149 assert!(
12150 matches!(via_into, std::borrow::Cow::Borrowed(_)),
12151 "Into<Cow<'static, str>>::into on \
12152 &RestartPolicy::{variant:?} must land on the \
12153 zero-alloc Cow::Borrowed arm — the blanket-derived \
12154 Into shape must resolve to the same Cow::Borrowed \
12155 dispatch as the explicit From impl"
12156 );
12157 }
12158 }
12159
12160 #[test]
12161 fn restart_policy_from_borrowed_into_static_cow_str_agrees_with_paired_axes_on_every_arm() {
12162 // Cross-axis partition pin: the newly lifted trait-idiomatic
12163 // borrowed-input `From<&RestartPolicy> for
12164 // std::borrow::Cow<'static, str>` (this lift), the paired
12165 // owned-input `From<RestartPolicy> for
12166 // std::borrow::Cow<'static, str>` (0612398), the paired
12167 // borrowed-input owned-`&'static str` `From<&RestartPolicy>
12168 // for &'static str`, and the paired borrowed-input owned-
12169 // `String` `From<&RestartPolicy> for String` must resolve
12170 // identically on every arm, locking the four
12171 // return-shape × input-shape paths together by construction so
12172 // any future detour trips at caixa-core test time. Also byte-
12173 // parity witness against the sibling [`ToString::to_string`]
12174 // surface routed through [`std::fmt::Display`] — every owned-
12175 // heap-string path (this axis's `.into_owned()` promotion, the
12176 // paired [`From<&RestartPolicy> for String`], and
12177 // `.to_string()`) resolves to the same lifted
12178 // [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const per arm.
12179 //
12180 // Then a `.iter().map(std::borrow::Cow::from)` pipe witness
12181 // over [`super::RestartPolicy::ALL`] — whose iterator yields
12182 // `&RestartPolicy` by construction, so the borrowed-input
12183 // [`Cow<'static, str>`] axis is what routes the pipe through
12184 // the substrate-primitive [`super::RestartPolicy::as_str`]
12185 // accessor without a spurious [`Copy`] deref (which would only
12186 // be reachable through the owned-input
12187 // [`From<RestartPolicy> for Cow<'static, str>`] axis by first
12188 // calling `.copied()` on the iterator). The pipe witness also
12189 // pins the zero-alloc discipline: every element in the
12190 // collected vector satisfies the [`std::borrow::Cow::Borrowed`]
12191 // arm predicate, so a future accidental silent-allocation
12192 // regression on the pipe's iteration axis is a caixa-core-
12193 // test-time failure. Peer of the sibling
12194 // [`restart_strategy_from_borrowed_into_static_cow_str_agrees_with_paired_axes_on_every_arm`]
12195 // (9b3e4b3) on the M2 OTP-shape sibling-restart axis — closes
12196 // the whole borrowed-input `Cow<'static, str>` +
12197 // paired `{&'static str, String}` cross-axis-parity corner on
12198 // both M2 OTP-shape sibling peers.
12199 for &policy in RestartPolicy::ALL {
12200 let borrowed_cow: std::borrow::Cow<'static, str> =
12201 <std::borrow::Cow<'static, str> as From<&RestartPolicy>>::from(&policy);
12202 let owned_cow: std::borrow::Cow<'static, str> =
12203 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(policy);
12204 let borrowed_static: &'static str =
12205 <&'static str as From<&RestartPolicy>>::from(&policy);
12206 let borrowed_string: String = <String as From<&RestartPolicy>>::from(&policy);
12207 assert_eq!(
12208 borrowed_cow, owned_cow,
12209 "From<&RestartPolicy> for Cow<'static, str> and \
12210 From<RestartPolicy> for Cow<'static, str> must \
12211 resolve identically on RestartPolicy::{policy:?} — \
12212 divergence signals the borrowed-input and owned-input \
12213 Cow<'static, str> forward-projection input-shape \
12214 paths have drifted onto different emit-sets"
12215 );
12216 assert_eq!(
12217 borrowed_cow.as_ref(),
12218 borrowed_static,
12219 "From<&RestartPolicy> for Cow<'static, str> and \
12220 From<&RestartPolicy> for &'static str must resolve \
12221 identically on RestartPolicy::{policy:?} — \
12222 divergence signals the borrowed-input Cow<'static, \
12223 str> and &'static str return-shape paths have drifted \
12224 onto different emit-sets"
12225 );
12226 assert_eq!(
12227 borrowed_cow.as_ref(),
12228 borrowed_string.as_str(),
12229 "From<&RestartPolicy> for Cow<'static, str> and \
12230 From<&RestartPolicy> for String must resolve \
12231 identically on RestartPolicy::{policy:?} — \
12232 divergence signals the borrowed-input Cow<'static, \
12233 str> and owned-`String` return-shape paths have \
12234 drifted onto different emit-sets"
12235 );
12236 let via_to_string: String = policy.to_string();
12237 assert_eq!(
12238 borrowed_cow.as_ref(),
12239 via_to_string.as_str(),
12240 "From<&RestartPolicy> for Cow<'static, str> must \
12241 byte-equal RestartPolicy::to_string on \
12242 RestartPolicy::{policy:?} — divergence signals \
12243 the trait-idiomatic borrowed-input Cow<'static, str> \
12244 forward-projection axis and the ToString-through-\
12245 Display axis have drifted onto different emit-sets"
12246 );
12247 }
12248 let via_iter: Vec<std::borrow::Cow<'static, str>> = RestartPolicy::ALL
12249 .iter()
12250 .map(std::borrow::Cow::from)
12251 .collect();
12252 let via_method: Vec<std::borrow::Cow<'static, str>> = RestartPolicy::ALL
12253 .iter()
12254 .map(|p| std::borrow::Cow::Borrowed(p.as_str()))
12255 .collect();
12256 assert_eq!(
12257 via_iter, via_method,
12258 "`.iter().map(Cow::from)` over RestartPolicy::ALL — a \
12259 call site whose iteration axis holds `&RestartPolicy` \
12260 by construction — must byte-equal `.iter().map(|p| \
12261 Cow::Borrowed(p.as_str()))` on every arm — the borrowed-\
12262 input Cow<'static, str> `From<&RestartPolicy> for \
12263 Cow<'static, str>` axis is what makes the `Cow::from` \
12264 composition route through the substrate-primitive \
12265 `RestartPolicy::as_str` accessor with the zero-alloc \
12266 Cow::Borrowed arm by construction and without a spurious \
12267 `Copy` deref (which would only be reachable through the \
12268 owned-input `From<RestartPolicy> for Cow<'static, str>` \
12269 axis by first calling `.copied()` on the iterator)"
12270 );
12271 for cow in &via_iter {
12272 assert!(
12273 matches!(cow, std::borrow::Cow::Borrowed(_)),
12274 "every element of the .iter().map(Cow::from) pipe \
12275 over RestartPolicy::ALL must land on the zero-\
12276 alloc Cow::Borrowed arm — a Cow::Owned outcome on \
12277 any arm signals the pipe's iteration axis has \
12278 silently allocated where the substrate-primitive \
12279 RestartPolicy::as_str `&'static str` return makes \
12280 the borrowed arm the type-correct projection"
12281 );
12282 }
12283 }
12284
12285 #[test]
12286 fn restart_policy_from_into_box_str_routes_through_as_str_accessor() {
12287 // Fail-before-pass-after byte-parity pin on the newly lifted
12288 // `impl From<RestartPolicy> for Box<str>` — asserts the
12289 // owned-input standard-library trait impl and the
12290 // substrate-primitive [`super::RestartPolicy::as_str`]
12291 // `pub const fn` accessor resolve to the same three-arm emit-
12292 // set across every arm the exhaustive
12293 // [`super::RestartPolicy::ALL`] slice enumerates. Extends the
12294 // substrate-wide `Box<str>` forward-projection campaign tier
12295 // opened one commit prior (69ef45c) on the paired sibling-
12296 // restart [`RestartStrategy`] onto the second (and third-and-
12297 // final) M2 OTP-shape closed-set fieldless typed enum peer on
12298 // the caixa surface (`:children :restart`), immediately after
12299 // the paired `Cow<'static, str>` axis (0612398 / b4dc55c)
12300 // closed the
12301 // `{Self, &Self} × {&'static str, String, Cow<'static, str>}`
12302 // 2×3 corner on this enum. Rust's standard library carries
12303 // `impl From<&str> for Box<str>` and
12304 // `impl From<String> for Box<str>` but no blanket
12305 // `impl<T: AsRef<str>> From<T> for Box<str>`, so this axis is
12306 // a distinct trait-idiomatic surface that a
12307 // `let key: Box<str> = policy.into();`-shaped call site
12308 // reaches through this impl and no other — a paired
12309 // `Box::from(policy.as_str())` open-code has no compile-time
12310 // link back to the substrate primitive. Peer of the sibling
12311 // [`restart_strategy_from_into_box_str_routes_through_as_str_accessor`]
12312 // (69ef45c) — extends the trait-idiomatic owned-input
12313 // [`Box<str>`] forward-projection axis onto the third and
12314 // final M2-OTP-shape closed-set typed enum on the caixa
12315 // surface.
12316 for &variant in RestartPolicy::ALL {
12317 let via_trait: Box<str> = <Box<str> as From<RestartPolicy>>::from(variant);
12318 let via_method: &'static str = variant.as_str();
12319 assert_eq!(
12320 via_trait.as_ref(),
12321 via_method,
12322 "From<RestartPolicy> for Box<str> impl must round-\
12323 trip RestartPolicy::{variant:?} to the same lifted \
12324 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str \
12325 returns — divergence signals a silent detour off the \
12326 substrate-primitive accessor"
12327 );
12328 let via_into: Box<str> = variant.into();
12329 assert_eq!(
12330 via_into.as_ref(),
12331 via_method,
12332 "Into<Box<str>>::into on RestartPolicy::{variant:?} \
12333 must byte-equal RestartPolicy::as_str on the same \
12334 input — the blanket-derived Into shape must resolve \
12335 to the same as_str dispatch as the explicit From impl"
12336 );
12337 }
12338 }
12339
12340 #[test]
12341 fn restart_policy_from_borrowed_into_box_str_routes_through_as_str_accessor() {
12342 // Fail-before-pass-after byte-parity pin on the newly lifted
12343 // `impl From<&RestartPolicy> for Box<str>` — asserts the
12344 // borrowed-input standard-library trait impl and the
12345 // substrate-primitive [`super::RestartPolicy::as_str`]
12346 // `pub const fn` accessor resolve to the same three-arm emit-
12347 // set across every arm the exhaustive
12348 // [`super::RestartPolicy::ALL`] slice enumerates. Rust's
12349 // standard library does not carry a blanket
12350 // `impl<T: AsRef<str>> From<&T> for Box<str>` (nor a
12351 // `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`),
12352 // so the borrowed-input `Box<str>` forward-projection axis
12353 // is a distinct trait-idiomatic surface that a
12354 // `let key: Box<str> = (&policy).into();`-shaped call site
12355 // or a `RestartPolicy::ALL.iter().map(Box::<str>::from)`-
12356 // shaped pipe reaches through this impl and no other — the
12357 // paired owned-input `From<RestartPolicy> for Box<str>`
12358 // impl (0a1b313) forces every borrowed-input call site
12359 // through an explicit `Copy` deref
12360 // (`Box::<str>::from((*policy).as_str())`) or a
12361 // `Box::<str>::from(policy.as_str())` open-code whose
12362 // type bounds have no compile-time link back to the
12363 // substrate primitive.
12364 //
12365 // Fourth (and closing) peer on the substrate-wide trait-
12366 // idiomatic [`Box<str>`] forward-projection family on the
12367 // M2 OTP-shape tier — closes the `{Self, &Self}` input-
12368 // shape corner of the [`Box<str>`] axis on the second (and
12369 // third-and-final) M2 OTP-shape closed-set fieldless typed
12370 // enum peer on the caixa surface (`:children :restart`),
12371 // exactly as b4dc55c closed the paired [`Cow<'static, str>`]
12372 // axis one commit after its owning half (0612398) landed
12373 // on this enum. Every remaining closed-set fieldless typed
12374 // enum peer on the M3 mesh-shape / outside-M3 caixa-core /
12375 // render-side / outside-caixa-core tiers is a future
12376 // target of the campaign.
12377 //
12378 // Also byte-parity witness against the paired owned-input
12379 // [`From<RestartPolicy> for Box<str>`] and the sibling
12380 // borrowed-input [`From<&RestartPolicy> for &'static str`],
12381 // [`From<&RestartPolicy> for String`], and
12382 // [`From<&RestartPolicy> for Cow<'static, str>`]
12383 // return-shape axes — locking the four
12384 // return-shape × input-shape paths together by construction
12385 // so any future detour trips at caixa-core test time. Then a
12386 // `.iter().map(Box::<str>::from)` pipe witness over
12387 // [`super::RestartPolicy::ALL`] — whose iterator yields
12388 // `&RestartPolicy` by construction, so the borrowed-input
12389 // [`Box<str>`] axis is what routes the pipe through the
12390 // substrate-primitive [`super::RestartPolicy::as_str`]
12391 // accessor without a spurious [`Copy`] deref (which would
12392 // only be reachable through the owned-input
12393 // [`From<RestartPolicy> for Box<str>`] axis by first
12394 // calling `.copied()` on the iterator).
12395 for &variant in RestartPolicy::ALL {
12396 let via_trait: Box<str> = <Box<str> as From<&RestartPolicy>>::from(&variant);
12397 let via_method: &'static str = variant.as_str();
12398 assert_eq!(
12399 via_trait.as_ref(),
12400 via_method,
12401 "From<&RestartPolicy> for Box<str> impl must round-\
12402 trip &RestartPolicy::{variant:?} to the same lifted \
12403 SUPERVISOR_CHILD_RESTART_* const RestartPolicy::as_str \
12404 returns — divergence signals a silent detour off the \
12405 substrate-primitive accessor"
12406 );
12407 let via_into: Box<str> = (&variant).into();
12408 assert_eq!(
12409 via_into.as_ref(),
12410 via_method,
12411 "Into<Box<str>>::into on &RestartPolicy::{variant:?} \
12412 must byte-equal RestartPolicy::as_str on the same \
12413 input — the blanket-derived Into shape must resolve \
12414 to the same as_str dispatch as the explicit From impl"
12415 );
12416 let owned_box: Box<str> = <Box<str> as From<RestartPolicy>>::from(variant);
12417 assert_eq!(
12418 via_trait, owned_box,
12419 "From<&RestartPolicy> for Box<str> and \
12420 From<RestartPolicy> for Box<str> must resolve \
12421 identically on RestartPolicy::{variant:?} — \
12422 divergence signals the borrowed-input and owned-input \
12423 Box<str> forward-projection input-shape paths have \
12424 drifted onto different emit-sets"
12425 );
12426 let borrowed_static: &'static str =
12427 <&'static str as From<&RestartPolicy>>::from(&variant);
12428 assert_eq!(
12429 via_trait.as_ref(),
12430 borrowed_static,
12431 "From<&RestartPolicy> for Box<str> and \
12432 From<&RestartPolicy> for &'static str must resolve \
12433 identically on RestartPolicy::{variant:?} — \
12434 divergence signals the borrowed-input Box<str> and \
12435 &'static str return-shape paths have drifted onto \
12436 different emit-sets"
12437 );
12438 let borrowed_string: String = <String as From<&RestartPolicy>>::from(&variant);
12439 assert_eq!(
12440 via_trait.as_ref(),
12441 borrowed_string.as_str(),
12442 "From<&RestartPolicy> for Box<str> and \
12443 From<&RestartPolicy> for String must resolve \
12444 identically on RestartPolicy::{variant:?} — \
12445 divergence signals the borrowed-input Box<str> and \
12446 owned-`String` return-shape paths have drifted onto \
12447 different emit-sets"
12448 );
12449 let borrowed_cow: std::borrow::Cow<'static, str> =
12450 <std::borrow::Cow<'static, str> as From<&RestartPolicy>>::from(&variant);
12451 assert_eq!(
12452 via_trait.as_ref(),
12453 borrowed_cow.as_ref(),
12454 "From<&RestartPolicy> for Box<str> and \
12455 From<&RestartPolicy> for Cow<'static, str> must \
12456 resolve identically on RestartPolicy::{variant:?} — \
12457 divergence signals the borrowed-input Box<str> and \
12458 Cow<'static, str> return-shape paths have drifted \
12459 onto different emit-sets"
12460 );
12461 }
12462 let via_iter: Vec<Box<str>> = RestartPolicy::ALL.iter().map(Box::<str>::from).collect();
12463 let via_method: Vec<Box<str>> = RestartPolicy::ALL
12464 .iter()
12465 .map(|p| Box::<str>::from(p.as_str()))
12466 .collect();
12467 assert_eq!(
12468 via_iter, via_method,
12469 "`.iter().map(Box::<str>::from)` over \
12470 RestartPolicy::ALL — a call site whose iteration axis \
12471 holds `&RestartPolicy` by construction — must byte-\
12472 equal `.iter().map(|p| Box::<str>::from(p.as_str()))` \
12473 on every arm — the borrowed-input Box<str> \
12474 `From<&RestartPolicy> for Box<str>` axis is what \
12475 makes the `Box::<str>::from` composition route through \
12476 the substrate-primitive `RestartPolicy::as_str` \
12477 accessor without a spurious `Copy` deref (which would \
12478 only be reachable through the owned-input \
12479 `From<RestartPolicy> for Box<str>` axis by first \
12480 calling `.copied()` on the iterator)"
12481 );
12482 }
12483
12484 #[test]
12485 fn restart_policy_from_into_arc_str_routes_through_as_str_accessor() {
12486 // Fail-before-pass-after byte-parity pin on the newly lifted
12487 // `impl From<RestartPolicy> for std::sync::Arc<str>` — asserts
12488 // the owned-input standard-library trait impl and the
12489 // substrate-primitive [`super::RestartPolicy::as_str`]
12490 // `pub const fn` accessor resolve to the same three-arm emit-
12491 // set across every arm the exhaustive
12492 // [`super::RestartPolicy::ALL`] slice enumerates. Extends the
12493 // substrate-wide [`std::sync::Arc<str>`] forward-projection
12494 // campaign tier opened one projection tier prior (bca2ec8) on
12495 // the paired sibling-restart [`RestartStrategy`] owned-input
12496 // first-mover onto the second (and third-and-final) M2 OTP-
12497 // shape closed-set fieldless typed enum peer on the caixa
12498 // surface (`:children :restart`), immediately after the paired
12499 // [`Box<str>`] axis (0a1b313 / cb1d068) closed the
12500 // `{Self, &Self} × {&'static str, String, Cow<'static, str>,
12501 // Box<str>}` 2×4 corner on this enum. Rust's standard library
12502 // carries `impl From<&str> for std::sync::Arc<str>` and
12503 // `impl From<String> for std::sync::Arc<str>` but no blanket
12504 // `impl<T: AsRef<str>> From<T> for std::sync::Arc<str>` (nor
12505 // an `impl<T: fmt::Display> From<T> for std::sync::Arc<str>`),
12506 // so this axis is a distinct trait-idiomatic surface that a
12507 // `let key: std::sync::Arc<str> = policy.into();`-shaped call
12508 // site reaches through this impl and no other — a paired
12509 // `std::sync::Arc::<str>::from(policy.as_str())` open-code
12510 // has no compile-time link back to the substrate primitive,
12511 // and a two-step `std::sync::Arc::<str>::from(String::from(
12512 // policy))` composition through the owned-`String` axis
12513 // allocates twice (once into the intermediate `String`, once
12514 // into the [`Arc<str>`] on the `From<String>` conversion)
12515 // where the single-step trait impl allocates once.
12516 //
12517 // Cross-axis byte-parity witness against the sibling owned-
12518 // input `{&'static str, String, Cow<'static, str>, Box<str>}`
12519 // return-shape axes — locking the five return-shape paths on
12520 // the owned-input surface together by construction so any
12521 // future detour off the substrate-primitive
12522 // [`super::RestartPolicy::as_str`] accessor trips at caixa-
12523 // core test time.
12524 for &variant in RestartPolicy::ALL {
12525 let via_trait: std::sync::Arc<str> =
12526 <std::sync::Arc<str> as From<RestartPolicy>>::from(variant);
12527 let via_method: &'static str = variant.as_str();
12528 assert_eq!(
12529 via_trait.as_ref(),
12530 via_method,
12531 "From<RestartPolicy> for std::sync::Arc<str> impl \
12532 must round-trip RestartPolicy::{variant:?} to the \
12533 same lifted SUPERVISOR_CHILD_RESTART_* const \
12534 RestartPolicy::as_str returns — divergence signals \
12535 a silent detour off the substrate-primitive accessor"
12536 );
12537 let via_into: std::sync::Arc<str> = variant.into();
12538 assert_eq!(
12539 via_into.as_ref(),
12540 via_method,
12541 "Into<std::sync::Arc<str>>::into on \
12542 RestartPolicy::{variant:?} must byte-equal \
12543 RestartPolicy::as_str on the same input — the \
12544 blanket-derived Into shape must resolve to the same \
12545 as_str dispatch as the explicit From impl"
12546 );
12547 let owned_static: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
12548 assert_eq!(
12549 via_trait.as_ref(),
12550 owned_static,
12551 "From<RestartPolicy> for std::sync::Arc<str> and \
12552 From<RestartPolicy> for &'static str must resolve \
12553 identically on RestartPolicy::{variant:?} — \
12554 divergence signals the owned-input std::sync::Arc<str> \
12555 and &'static str return-shape paths have drifted onto \
12556 different emit-sets"
12557 );
12558 let owned_string: String = <String as From<RestartPolicy>>::from(variant);
12559 assert_eq!(
12560 via_trait.as_ref(),
12561 owned_string.as_str(),
12562 "From<RestartPolicy> for std::sync::Arc<str> and \
12563 From<RestartPolicy> for String must resolve \
12564 identically on RestartPolicy::{variant:?} — \
12565 divergence signals the owned-input std::sync::Arc<str> \
12566 and owned-`String` return-shape paths have drifted \
12567 onto different emit-sets"
12568 );
12569 let owned_cow: std::borrow::Cow<'static, str> =
12570 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(variant);
12571 assert_eq!(
12572 via_trait.as_ref(),
12573 owned_cow.as_ref(),
12574 "From<RestartPolicy> for std::sync::Arc<str> and \
12575 From<RestartPolicy> for Cow<'static, str> must \
12576 resolve identically on RestartPolicy::{variant:?} — \
12577 divergence signals the owned-input std::sync::Arc<str> \
12578 and Cow<'static, str> return-shape paths have drifted \
12579 onto different emit-sets"
12580 );
12581 let owned_box: Box<str> = <Box<str> as From<RestartPolicy>>::from(variant);
12582 assert_eq!(
12583 via_trait.as_ref(),
12584 owned_box.as_ref(),
12585 "From<RestartPolicy> for std::sync::Arc<str> and \
12586 From<RestartPolicy> for Box<str> must resolve \
12587 identically on RestartPolicy::{variant:?} — \
12588 divergence signals the owned-input std::sync::Arc<str> \
12589 and Box<str> return-shape paths have drifted onto \
12590 different emit-sets"
12591 );
12592 }
12593 }
12594
12595 #[test]
12596 fn restart_policy_from_borrowed_into_arc_str_routes_through_as_str_accessor() {
12597 // Fail-before-pass-after byte-parity pin on the newly lifted
12598 // `impl From<&RestartPolicy> for std::sync::Arc<str>` —
12599 // asserts the borrowed-input standard-library trait impl and
12600 // the substrate-primitive [`super::RestartPolicy::as_str`]
12601 // `pub const fn` accessor resolve to the same three-arm
12602 // emit-set across every arm the exhaustive
12603 // [`super::RestartPolicy::ALL`] slice enumerates. Rust's
12604 // standard library carries `impl From<&str> for
12605 // std::sync::Arc<str>` and `impl From<String> for
12606 // std::sync::Arc<str>` but no blanket
12607 // `impl<T: AsRef<str>> From<&T> for std::sync::Arc<str>` (nor
12608 // a `Copy`-based `impl<T: Copy, U: From<T>> From<&T> for U`),
12609 // so the borrowed-input [`std::sync::Arc<str>`] forward-
12610 // projection axis is a distinct trait-idiomatic surface that
12611 // a `let key: std::sync::Arc<str> = (&policy).into();`-shaped
12612 // call site or a
12613 // `RestartPolicy::ALL.iter().map(std::sync::Arc::<str>::from)`-
12614 // shaped pipe reaches through this impl and no other — the
12615 // paired owned-input [`From<RestartPolicy> for
12616 // std::sync::Arc<str>`] impl (b05724e) forces every borrowed-
12617 // input call site through an explicit [`Copy`] deref
12618 // (`std::sync::Arc::<str>::from((*policy).as_str())`) or a
12619 // `std::sync::Arc::<str>::from(policy.as_str())` open-code
12620 // whose type bounds have no compile-time link back to the
12621 // substrate primitive.
12622 //
12623 // Closes the `{Self, &Self}` input-shape corner of the
12624 // substrate-wide trait-idiomatic [`std::sync::Arc<str>`]
12625 // forward-projection family on the second (and third-and-
12626 // final) M2 OTP-shape closed-set fieldless typed enum peer
12627 // on the caixa surface (`:children :restart`), one commit
12628 // after b05724e opened the owned-input half — exactly as
12629 // b3e72d7 closed the paired [`std::sync::Arc<str>`] corner on
12630 // the sibling-restart [`RestartStrategy`] first-mover one
12631 // commit after its owning half (bca2ec8) landed, and as
12632 // cb1d068 closed the paired [`Box<str>`] corner on this
12633 // enum one commit after its owning half (0a1b313) landed.
12634 //
12635 // Also byte-parity witness against the paired owned-input
12636 // [`From<RestartPolicy> for std::sync::Arc<str>`] and the
12637 // sibling borrowed-input [`From<&RestartPolicy> for
12638 // &'static str`], [`From<&RestartPolicy> for String`],
12639 // [`From<&RestartPolicy> for Cow<'static, str>`], and
12640 // [`From<&RestartPolicy> for Box<str>`] return-shape axes —
12641 // locking the five return-shape × input-shape paths together
12642 // by construction so any future detour off the substrate-
12643 // primitive [`super::RestartPolicy::as_str`] accessor trips
12644 // at caixa-core test time. Then a
12645 // `.iter().map(std::sync::Arc::<str>::from)` pipe witness
12646 // over [`super::RestartPolicy::ALL`] — whose iterator yields
12647 // `&RestartPolicy` by construction, so the borrowed-input
12648 // [`std::sync::Arc<str>`] axis is what routes the pipe
12649 // through the substrate-primitive
12650 // [`super::RestartPolicy::as_str`] accessor without a
12651 // spurious [`Copy`] deref (which would only be reachable
12652 // through the owned-input
12653 // [`From<RestartPolicy> for std::sync::Arc<str>`] axis by
12654 // first calling `.copied()` on the iterator).
12655 for &variant in RestartPolicy::ALL {
12656 let via_trait: std::sync::Arc<str> =
12657 <std::sync::Arc<str> as From<&RestartPolicy>>::from(&variant);
12658 let via_method: &'static str = variant.as_str();
12659 assert_eq!(
12660 via_trait.as_ref(),
12661 via_method,
12662 "From<&RestartPolicy> for std::sync::Arc<str> impl \
12663 must round-trip &RestartPolicy::{variant:?} to the \
12664 same lifted SUPERVISOR_CHILD_RESTART_* const \
12665 RestartPolicy::as_str returns — divergence signals \
12666 a silent detour off the substrate-primitive accessor"
12667 );
12668 let via_into: std::sync::Arc<str> = (&variant).into();
12669 assert_eq!(
12670 via_into.as_ref(),
12671 via_method,
12672 "Into<std::sync::Arc<str>>::into on \
12673 &RestartPolicy::{variant:?} must byte-equal \
12674 RestartPolicy::as_str on the same input — the \
12675 blanket-derived Into shape must resolve to the same \
12676 as_str dispatch as the explicit From impl"
12677 );
12678 let owned_arc: std::sync::Arc<str> =
12679 <std::sync::Arc<str> as From<RestartPolicy>>::from(variant);
12680 assert_eq!(
12681 via_trait, owned_arc,
12682 "From<&RestartPolicy> for std::sync::Arc<str> and \
12683 From<RestartPolicy> for std::sync::Arc<str> must \
12684 resolve identically on RestartPolicy::{variant:?} — \
12685 divergence signals the borrowed-input and owned-input \
12686 std::sync::Arc<str> forward-projection input-shape \
12687 paths have drifted onto different emit-sets"
12688 );
12689 let borrowed_static: &'static str =
12690 <&'static str as From<&RestartPolicy>>::from(&variant);
12691 assert_eq!(
12692 via_trait.as_ref(),
12693 borrowed_static,
12694 "From<&RestartPolicy> for std::sync::Arc<str> and \
12695 From<&RestartPolicy> for &'static str must resolve \
12696 identically on RestartPolicy::{variant:?} — \
12697 divergence signals the borrowed-input std::sync::Arc<str> \
12698 and &'static str return-shape paths have drifted onto \
12699 different emit-sets"
12700 );
12701 let borrowed_string: String = <String as From<&RestartPolicy>>::from(&variant);
12702 assert_eq!(
12703 via_trait.as_ref(),
12704 borrowed_string.as_str(),
12705 "From<&RestartPolicy> for std::sync::Arc<str> and \
12706 From<&RestartPolicy> for String must resolve \
12707 identically on RestartPolicy::{variant:?} — \
12708 divergence signals the borrowed-input std::sync::Arc<str> \
12709 and owned-`String` return-shape paths have drifted \
12710 onto different emit-sets"
12711 );
12712 let borrowed_cow: std::borrow::Cow<'static, str> =
12713 <std::borrow::Cow<'static, str> as From<&RestartPolicy>>::from(&variant);
12714 assert_eq!(
12715 via_trait.as_ref(),
12716 borrowed_cow.as_ref(),
12717 "From<&RestartPolicy> for std::sync::Arc<str> and \
12718 From<&RestartPolicy> for Cow<'static, str> must \
12719 resolve identically on RestartPolicy::{variant:?} — \
12720 divergence signals the borrowed-input std::sync::Arc<str> \
12721 and Cow<'static, str> return-shape paths have drifted \
12722 onto different emit-sets"
12723 );
12724 let borrowed_box: Box<str> = <Box<str> as From<&RestartPolicy>>::from(&variant);
12725 assert_eq!(
12726 via_trait.as_ref(),
12727 borrowed_box.as_ref(),
12728 "From<&RestartPolicy> for std::sync::Arc<str> and \
12729 From<&RestartPolicy> for Box<str> must resolve \
12730 identically on RestartPolicy::{variant:?} — \
12731 divergence signals the borrowed-input std::sync::Arc<str> \
12732 and Box<str> return-shape paths have drifted onto \
12733 different emit-sets"
12734 );
12735 }
12736 let via_iter: Vec<std::sync::Arc<str>> = RestartPolicy::ALL
12737 .iter()
12738 .map(std::sync::Arc::<str>::from)
12739 .collect();
12740 let via_method: Vec<std::sync::Arc<str>> = RestartPolicy::ALL
12741 .iter()
12742 .map(|p| std::sync::Arc::<str>::from(p.as_str()))
12743 .collect();
12744 assert_eq!(
12745 via_iter, via_method,
12746 "`.iter().map(std::sync::Arc::<str>::from)` over \
12747 RestartPolicy::ALL — a call site whose iteration axis \
12748 holds `&RestartPolicy` by construction — must byte-\
12749 equal `.iter().map(|p| std::sync::Arc::<str>::from(p.as_str()))` \
12750 on every arm — the borrowed-input std::sync::Arc<str> \
12751 `From<&RestartPolicy> for std::sync::Arc<str>` axis is \
12752 what makes the `std::sync::Arc::<str>::from` composition \
12753 route through the substrate-primitive \
12754 `RestartPolicy::as_str` accessor without a spurious \
12755 `Copy` deref (which would only be reachable through the \
12756 owned-input `From<RestartPolicy> for std::sync::Arc<str>` \
12757 axis by first calling `.copied()` on the iterator)"
12758 );
12759 }
12760
12761 // ── drift-detection: serde-derive-to-SUPERVISOR_CHILD_RESTART_* identity ─
12762
12763 #[test]
12764 fn restart_policy_variants_serialize_to_lifted_scalar_values() {
12765 // The fail-before-pass-after pin: pre-lift there was no
12766 // single-source binding between the [`RestartPolicy`] variant
12767 // name the un-`rename`d `Serialize` derive emits under
12768 // [`crate::render::SUPERVISOR_CHILD_KEY_RESTART`] and the
12769 // byte-string every downstream cluster-side dispatcher (the
12770 // future wasm-operator's per-child post-exit restart-decision
12771 // branch, the future M4 `mesh.pleme.io/v1alpha1/Supervisor` CR
12772 // materializer's admission-time enum-arm bind, the
12773 // `caixa-operator`'s hierarchical reconciliation scheduler's
12774 // per-child-policy fan-out) probes verbatim. A future
12775 // `#[serde(rename_all = "kebab-case")]` attribute on the enum —
12776 // or a per-variant `#[serde(rename = "…")]` override, or a
12777 // variant rename in the source — would silently rebrand the
12778 // emitted scalar under one spelling while every downstream
12779 // dispatcher still probed the other, with the failure surfacing
12780 // at the operator's reconcile posture (children coming up under
12781 // the `default()` `Permanent` arm rather than the typed slot's
12782 // declared policy — a `:temporary` `oneShot` child would be
12783 // restarted on clean exit, treating the successful-completion
12784 // signal as failure and re-running the completion-terminal
12785 // one-shot indefinitely; a `:transient` child that clean-exited
12786 // would be restarted, masking the clean-completion contract)
12787 // far from the source rebrand commit and with no field naming
12788 // the drift. Pinning the two paths (the `Serialize` derive's
12789 // serialized string AND the [`RestartPolicy::as_str`] helper)
12790 // to the same three lifted
12791 // [`crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT`] /
12792 // [`crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY`] /
12793 // [`crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT`]
12794 // byte-strings makes any future drift on either endpoint fail
12795 // here at caixa-core build time. Peer of the sibling
12796 // [`restart_strategy_variants_serialize_to_lifted_scalar_values`]
12797 // (09ffb2d) on the per-supervisor sibling-restart-strategy axis
12798 // and the M3
12799 // `placement_strategy_variants_serialize_to_lifted_scalar_values`
12800 // (3f0e21c) on the per-Aplicacao distribution-strategy axis —
12801 // same three-path-convergence discipline, extended to close the
12802 // third OTP-shaped closed-enum discriminator axis on the caixa
12803 // typed surface (per-child restart-decision policy).
12804 for (variant, expected) in [
12805 (
12806 RestartPolicy::Permanent,
12807 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
12808 ),
12809 (
12810 RestartPolicy::Temporary,
12811 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
12812 ),
12813 (
12814 RestartPolicy::Transient,
12815 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
12816 ),
12817 ] {
12818 let json = serde_json::to_string(&variant).unwrap();
12819 assert_eq!(
12820 json,
12821 format!("\"{expected}\""),
12822 "RestartPolicy::{variant:?} must serialize to {expected:?}"
12823 );
12824 assert_eq!(
12825 variant.as_str(),
12826 expected,
12827 "RestartPolicy::{variant:?}.as_str() must return the lifted \
12828 SUPERVISOR_CHILD_RESTART_* constant"
12829 );
12830 }
12831 }
12832
12833 #[test]
12834 fn supervisor_child_restart_consts_are_pairwise_distinct() {
12835 // Cross-arm drift-detection pin: a future collapse of two
12836 // canonical variant byte-strings onto the same value (e.g. an
12837 // accidental copy-paste flip of `SUPERVISOR_CHILD_RESTART_TRANSIENT`
12838 // to also read `"Permanent"`) would silently reroute every
12839 // downstream operator's per-child-policy dispatch onto the
12840 // sibling arm's reconcile branch and pass every propagation-probe
12841 // test that expected only the stale arm's value — a `:transient`
12842 // child would come up under the `:permanent` restart-decision
12843 // posture on every subsequent clean exit, so a completion-terminal
12844 // child would be restarted indefinitely against its declared
12845 // policy. Peer of the sibling
12846 // [`supervisor_estrategia_consts_are_pairwise_distinct`]
12847 // (09ffb2d) on the per-supervisor sibling-restart-strategy axis
12848 // and the four-way distinct pin
12849 // `supervisor_key_consts_are_pairwise_distinct` (40cc4e5) on the
12850 // top-level `SUPERVISOR_KEY_*` axis.
12851 let all = [
12852 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
12853 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
12854 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
12855 ];
12856 for (i, a) in all.iter().enumerate() {
12857 for (j, b) in all.iter().enumerate() {
12858 if i != j {
12859 assert_ne!(
12860 a, b,
12861 "SUPERVISOR_CHILD_RESTART_* consts must be pairwise distinct \
12862 — got duplicate {a:?} at indices {i} and {j}",
12863 );
12864 }
12865 }
12866 }
12867 }
12868
12869 #[test]
12870 fn restart_policy_display_routes_through_as_str_helper() {
12871 // The fail-before-pass-after pin on the first half of the
12872 // three-path convergence: pre-convergence [`RestartPolicy`]
12873 // carried a [`std::fmt::Display`] surface via its
12874 // `#[discriminant(also_display)]` gen-platform derive route,
12875 // which arrived kebab-case as `"permanent"` / `"temporary"`
12876 // / `"transient"` on this three-arm enum (whose variant
12877 // names each collapse to their own lowercase form under the
12878 // kebab-case transform) while the wire format ran as
12879 // PascalCase `"Permanent"` / `"Temporary"` / `"Transient"`
12880 // through the un-`rename`d serde derive. Every consumer
12881 // reaching for a policy byte-string past the wire format had
12882 // to pick between three paths ([`RestartPolicy::as_str`],
12883 // the `Serialize` derive's serialized string, or
12884 // `format!("{v}")` on the discriminant-Display route), any
12885 // two of which a future variant rename or
12886 // `#[serde(rename_all = "kebab-case")]` attribute would
12887 // silently desynchronize. Wiring [`std::fmt::Display`]
12888 // through [`RestartPolicy::as_str`] closes the third path:
12889 // every `format!("{v}")` call reaches the same lifted
12890 // [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const the
12891 // wire format and the [`RestartPolicy::as_str`] helper
12892 // already route through, so a future variant rename lands at
12893 // exactly one place. Pin the routing here so a future
12894 // `impl std::fmt::Display for RestartPolicy`
12895 // reimplementation that hand-rolls the arms instead of
12896 // delegating to [`RestartPolicy::as_str`] fails at
12897 // caixa-core build time. Peer of the sibling
12898 // [`restart_strategy_display_routes_through_as_str_helper`]
12899 // on the per-supervisor sibling-restart-strategy axis and
12900 // the M3
12901 // `placement_strategy_display_routes_through_as_str_helper`
12902 // (cc8f749) — the third of three OTP-shape closed-enum
12903 // discriminator axes on the caixa typed surface now
12904 // converged onto the same three-path
12905 // (Display → as_str → lifted const) discipline.
12906 for variant in [
12907 RestartPolicy::Permanent,
12908 RestartPolicy::Temporary,
12909 RestartPolicy::Transient,
12910 ] {
12911 assert_eq!(
12912 variant.to_string(),
12913 variant.as_str(),
12914 "RestartPolicy::{variant:?} Display must route through \
12915 RestartPolicy::as_str (single source of truth: the lifted \
12916 SUPERVISOR_CHILD_RESTART_* const the wire format also emits)"
12917 );
12918 }
12919 }
12920
12921 #[test]
12922 fn restart_policy_display_matches_serialized_wire_byte_string() {
12923 // The fail-before-pass-after pin on the second half of the
12924 // three-path convergence: `Display` (user-facing text) agrees
12925 // byte-for-byte with the `Serialize` derive's wire format
12926 // (canonical camelCase-schema `SUPERVISOR_CHILD_KEY_RESTART`
12927 // scalar) on every variant. Pre-convergence the two paths
12928 // were structurally independent — a future
12929 // `#[serde(rename_all = "kebab-case")]` attribute on the
12930 // enum would silently rebrand the emitted wire scalar
12931 // (`permanent`, `temporary`, `transient`) while every
12932 // consumer that pretty-prints the policy (the future
12933 // wasm-operator's per-child post-exit restart-decision
12934 // diagnostic line, the future `feira app graph` per-child
12935 // restart column, the future M4
12936 // `mesh.pleme.io/v1alpha1/Supervisor` CR materializer's
12937 // per-child admission-webhook rejection body) would still
12938 // emit the PascalCase form the `as_str` / `Display` route
12939 // returns, with the mismatch surfacing at consumer parse
12940 // time / operator dispatch time far from the source rebrand
12941 // commit. Pin the two paths byte-for-byte here so any future
12942 // serde-attribute or variant-rename drift is a
12943 // caixa-core-build-time test failure at this call, not a
12944 // silent per-consumer dispatch miss. Peer of the sibling
12945 // [`restart_strategy_display_matches_serialized_wire_byte_string`]
12946 // on the per-supervisor sibling-restart-strategy axis and
12947 // the M3
12948 // `placement_strategy_display_matches_serialized_wire_byte_string`
12949 // (cc8f749).
12950 for variant in [
12951 RestartPolicy::Permanent,
12952 RestartPolicy::Temporary,
12953 RestartPolicy::Transient,
12954 ] {
12955 let wire = serde_json::to_string(&variant).unwrap();
12956 let unquoted = wire
12957 .strip_prefix('"')
12958 .and_then(|s| s.strip_suffix('"'))
12959 .expect("serialized RestartPolicy is a JSON string");
12960 assert_eq!(
12961 variant.to_string(),
12962 unquoted,
12963 "RestartPolicy::{variant:?} Display byte-string must match the \
12964 Serialize derive's wire byte-string (three-path convergence: \
12965 Display + as_str + Serialize all resolve to the same \
12966 SUPERVISOR_CHILD_RESTART_* const)"
12967 );
12968 }
12969 }
12970
12971 #[test]
12972 fn restart_policy_as_ref_str_routes_through_as_str_accessor() {
12973 // Fail-before-pass-after byte-parity pin on the lifted
12974 // `impl AsRef<str> for RestartPolicy` — asserts the
12975 // standard-library trait impl and the substrate-primitive
12976 // [`RestartPolicy::as_str`] `pub const fn` accessor resolve
12977 // to the same `&str` per instance across the three-arm
12978 // closed set, so any future silent detour that routes the
12979 // impl through a divergent projection (a per-arm inline
12980 // `match self { RestartPolicy::Permanent => "Permanent", … }`
12981 // re-inlining that opens a compile-time link to the un-lifted
12982 // arm-literal, a swap onto the kebab-case
12983 // [`gen_platform::Discriminant`] catalog identity that would
12984 // collide the wire axis with the dispatcher-catalog axis) trips
12985 // at caixa-core test time under `PartialEq` rather than at a
12986 // downstream `impl AsRef<str>`-bound consumer's silent split.
12987 // Sweeps every one of the three arms
12988 // [`RestartPolicy::ALL`] carries so no arm's projection is
12989 // covered only by the sibling wire-format `Serialize` derive
12990 // path. Peer of the sibling
12991 // [`restart_strategy_as_ref_str_routes_through_as_str_accessor`]
12992 // (63eb1a4) on the paired per-supervisor sibling-restart-
12993 // strategy axis and the [`crate::CaixaVersion`]
12994 // `AsRef<str>`-byte-parity pin (16d5c7e) on the paired
12995 // top-level `:versao` typed newtype — the three pins together
12996 // cover the substrate primitive's `AsRef<str>` projection axis
12997 // on the paired newtype + M2 closed-set-typed-enum surface.
12998 for &variant in RestartPolicy::ALL {
12999 assert_eq!(
13000 <RestartPolicy as AsRef<str>>::as_ref(&variant),
13001 variant.as_str(),
13002 "AsRef<str> impl on RestartPolicy::{variant:?} must \
13003 byte-equal RestartPolicy::as_str on the same instance \
13004 — divergence signals a silent detour off the substrate-\
13005 primitive accessor"
13006 );
13007 }
13008 }
13009
13010 #[test]
13011 fn restart_policy_as_ref_str_routes_through_display_via_shared_accessor() {
13012 // Fail-before-pass-after byte-parity pin on the three-path
13013 // convergence discipline the M2 per-child-restart-policy
13014 // primitive now carries on the `&str`-projection axis:
13015 // `<RestartPolicy as AsRef<str>>::as_ref(&v)` (the newly
13016 // lifted impl), `format!("{v}")` (the pre-existing
13017 // [`fmt::Display`] impl), and `v.as_str()` (the substrate-
13018 // primitive `pub const fn` accessor both trait impls delegate
13019 // through) must resolve to the same byte-string on every
13020 // instance across the three-arm closed set. Refuses any future
13021 // divergence between the two trait impls (a stray
13022 // [`fmt::Display::fmt`] rewrite that hand-rolls the arms
13023 // rather than delegating through the shared accessor; a
13024 // hypothetical `AsRef<str>` rewrite that inlines a per-arm
13025 // literal cascade) that would silently split the two
13026 // projection paths of the same closed-set typed enum. Mirrors
13027 // the sibling three-path-convergence discipline the peer
13028 // [`RestartStrategy`] typed enum carries on its
13029 // `AsRef<str>` / `Display` / `as_str` triple
13030 // (supervisor.rs pin
13031 // `restart_strategy_as_ref_str_routes_through_display_via_shared_accessor`,
13032 // 63eb1a4) and the [`crate::CaixaVersion`] typed newtype
13033 // carries on the same triple (version.rs pin
13034 // `caixa_version_as_ref_str_routes_through_display_via_shared_accessor`,
13035 // 16d5c7e).
13036 for &variant in RestartPolicy::ALL {
13037 let via_as_ref: &str = <RestartPolicy as AsRef<str>>::as_ref(&variant);
13038 let via_display: String = format!("{variant}");
13039 let via_accessor: &str = variant.as_str();
13040 assert_eq!(via_as_ref, via_accessor);
13041 assert_eq!(via_display, via_accessor);
13042 assert_eq!(via_as_ref, via_display.as_str());
13043 }
13044 }
13045
13046 // The `generic_bytes_sink(&variant)` and `borrowed_hasher.update(&variant)`
13047 // shapes below are the borrowed-input witness half of the by-value +
13048 // by-reference partition the paired witness pair carries: the pair proves
13049 // the trait bound accepts both owned (`variant`) and borrowed (`&variant`)
13050 // shapes through the same substrate-primitive `as_str` accessor, which is
13051 // the shape the caixa-lacre BLAKE3 content-address closure composes.
13052 // `clippy::needless_borrows_for_generic_args` would fold the borrowed half
13053 // into the owned half and collapse the by-value/by-reference partition
13054 // this test load-bears; the `#[allow]` documents that the partition is
13055 // deliberate, not an oversight.
13056 #[allow(clippy::needless_borrows_for_generic_args)]
13057 #[test]
13058 fn restart_policy_as_ref_bytes_routes_through_as_str_accessor() {
13059 // `<T: AsRef<[u8]>>`-bound generic-consumer witness: a byte-input
13060 // function that binds its argument through the standard-library
13061 // [`AsRef<[u8]>`] trait bound accepts a [`super::RestartPolicy`]
13062 // directly, without the caller open-coding the two-hop
13063 // `restart.as_str().as_bytes()` composition. Lifted to the top
13064 // of the function per `clippy::items_after_statements`.
13065 fn generic_bytes_sink<T: AsRef<[u8]>>(t: T) -> Vec<u8> {
13066 t.as_ref().to_vec()
13067 }
13068 // `blake3::Hasher::update`-shape byte-input surface mock: mirrors
13069 // `blake3::Hasher::update` / `ring::digest::Context::update` /
13070 // `sha2::Sha256::update`'s `impl AsRef<[u8]>`-bound `update`
13071 // signature so a per-child BLAKE3 content-address closure that
13072 // composes `hasher.update(restart)` on the [`crate::Lacre`]
13073 // closure builder reaches the substrate-primitive `as_str`
13074 // accessor through the [`super::RestartPolicy`] `AsRef<[u8]>`
13075 // axis and no other. Lifted to the top of the function per
13076 // `clippy::items_after_statements`.
13077 struct MockHasher(Vec<u8>);
13078 impl MockHasher {
13079 fn new() -> Self {
13080 Self(Vec::new())
13081 }
13082 fn update(&mut self, bytes: impl AsRef<[u8]>) -> &mut Self {
13083 self.0.extend_from_slice(bytes.as_ref());
13084 self
13085 }
13086 fn finalize(self) -> Vec<u8> {
13087 self.0
13088 }
13089 }
13090
13091 // Fail-before-pass-after byte-parity pin on the newly lifted
13092 // `impl AsRef<[u8]> for RestartPolicy` — asserts the trait-
13093 // idiomatic byte-view standard-library impl and the substrate-
13094 // primitive [`super::RestartPolicy::as_str`] `pub const fn`
13095 // accessor's `.as_bytes()` byte-tail resolve to the same three-
13096 // arm `PascalCase` wire byte-string emit-set across every arm
13097 // the exhaustive [`super::RestartPolicy::ALL`] slice enumerates.
13098 // Extends the trait-idiomatic byte-view axis onto the second
13099 // (and final) M2 OTP-shape closed-set fieldless typed enum peer
13100 // on the caixa surface (the paired per-child restart-decision
13101 // policy sibling on the same M2 `:supervisor` slot), closing
13102 // the byte-view axis across the `:supervisor :estrategia` +
13103 // `:children :restart` M2 slot pair the sibling
13104 // [`super::RestartStrategy`] first-mover (cd4c4e0) opened.
13105 //
13106 // Rust's standard library carries `impl AsRef<[u8]> for str` and
13107 // `impl AsRef<[u8]> for String`, so a two-hop composition
13108 // `restart.as_str().as_bytes()` (or the equally two-hop
13109 // `AsRef::<str>::as_ref(&restart).as_bytes()`) is reachable
13110 // through the pre-existing str-view axis alone. But that two-hop
13111 // shape has no compile-time link back to the byte-projection
13112 // axis, forces every downstream `<T: AsRef<[u8]>>`-bound
13113 // consumer to open-code the two-hop composition at every call
13114 // site, and admits a silent split whenever a future call site
13115 // takes a sibling reverse-projection axis whose `.as_bytes()`
13116 // byte-tail carries no compile-time byte-view surface. This
13117 // impl closes the byte-view axis at the substrate-primitive
13118 // [`super::RestartPolicy::as_str`] accessor so every future
13119 // `<T: AsRef<[u8]>>`-bound consumer reaches the same lifted
13120 // [`super::crate::render::SUPERVISOR_CHILD_RESTART_*`] const
13121 // roster the paired str-view axes already return through —
13122 // through one trait dispatch.
13123 for &variant in RestartPolicy::ALL {
13124 let via_trait: &[u8] = <RestartPolicy as AsRef<[u8]>>::as_ref(&variant);
13125 let via_method_bytes: &[u8] = variant.as_str().as_bytes();
13126 assert_eq!(
13127 via_trait, via_method_bytes,
13128 "AsRef<[u8]> for RestartPolicy impl must byte-equal \
13129 RestartPolicy::as_str().as_bytes() on \
13130 RestartPolicy::{variant:?} — divergence signals a \
13131 silent detour off the substrate-primitive accessor"
13132 );
13133 // Cross-axis witness against the paired str-view axes'
13134 // `.as_bytes()` byte-tails: [`AsRef<str>`] /
13135 // [`std::fmt::Display`] / [`super::RestartPolicy::as_str`]
13136 // all resolve to the same lifted
13137 // [`super::crate::render::SUPERVISOR_CHILD_RESTART_*`] const
13138 // roster, and the byte-view axis must byte-equal each of
13139 // their `.as_bytes()` byte-tails by construction — locking
13140 // the str-view and byte-view axes together at the
13141 // substrate-primitive accessor.
13142 let str_view_ref: &str = <RestartPolicy as AsRef<str>>::as_ref(&variant);
13143 assert_eq!(
13144 via_trait,
13145 str_view_ref.as_bytes(),
13146 "AsRef<[u8]> for RestartPolicy and AsRef<str> for \
13147 RestartPolicy must resolve to byte-equal byte-tails \
13148 on RestartPolicy::{variant:?} — divergence signals \
13149 the byte-view and str-view axes have drifted off the \
13150 same substrate-primitive as_str accessor"
13151 );
13152 let display_bytes = variant.to_string();
13153 assert_eq!(
13154 via_trait,
13155 display_bytes.as_bytes(),
13156 "AsRef<[u8]> for RestartPolicy and \
13157 <RestartPolicy as std::fmt::Display>::to_string must \
13158 resolve to byte-equal byte-tails on \
13159 RestartPolicy::{variant:?} — divergence signals the \
13160 byte-view axis and the Display formatter axis have \
13161 drifted off the same substrate-primitive as_str \
13162 accessor"
13163 );
13164 // Cross-axis witness against the paired reverse-projection
13165 // axes' `.as_bytes()` byte-tails: every one of `{&'static
13166 // str, String, Cow<'static, str>, Box<str>,
13167 // std::sync::Arc<str>}` allocates (or borrows) the same
13168 // `PascalCase` wire byte-string the substrate-primitive
13169 // accessor emits, so the byte-view axis must byte-equal
13170 // each of their `.as_bytes()` byte-tails by construction.
13171 let owned_static: &'static str = <&'static str as From<RestartPolicy>>::from(variant);
13172 assert_eq!(
13173 via_trait,
13174 owned_static.as_bytes(),
13175 "AsRef<[u8]> for RestartPolicy and From<RestartPolicy> \
13176 for &'static str must resolve to byte-equal byte-tails \
13177 on RestartPolicy::{variant:?}"
13178 );
13179 let owned_string: String = <String as From<RestartPolicy>>::from(variant);
13180 assert_eq!(
13181 via_trait,
13182 owned_string.as_bytes(),
13183 "AsRef<[u8]> for RestartPolicy and From<RestartPolicy> \
13184 for String must resolve to byte-equal byte-tails on \
13185 RestartPolicy::{variant:?}"
13186 );
13187 let owned_cow: std::borrow::Cow<'static, str> =
13188 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(variant);
13189 assert_eq!(
13190 via_trait,
13191 owned_cow.as_bytes(),
13192 "AsRef<[u8]> for RestartPolicy and From<RestartPolicy> \
13193 for Cow<'static, str> must resolve to byte-equal byte-\
13194 tails on RestartPolicy::{variant:?}"
13195 );
13196 let owned_box: Box<str> = <Box<str> as From<RestartPolicy>>::from(variant);
13197 assert_eq!(
13198 via_trait,
13199 owned_box.as_bytes(),
13200 "AsRef<[u8]> for RestartPolicy and From<RestartPolicy> \
13201 for Box<str> must resolve to byte-equal byte-tails on \
13202 RestartPolicy::{variant:?}"
13203 );
13204 let owned_arc: std::sync::Arc<str> =
13205 <std::sync::Arc<str> as From<RestartPolicy>>::from(variant);
13206 assert_eq!(
13207 via_trait,
13208 owned_arc.as_bytes(),
13209 "AsRef<[u8]> for RestartPolicy and From<RestartPolicy> \
13210 for std::sync::Arc<str> must resolve to byte-equal \
13211 byte-tails on RestartPolicy::{variant:?}"
13212 );
13213 }
13214 // `<T: AsRef<[u8]>>`-bound-consumer witness: the generic byte-
13215 // input function `generic_bytes_sink` (lifted above per
13216 // `clippy::items_after_statements`) accepts a
13217 // [`super::RestartPolicy`] directly through the trait bound,
13218 // without the caller open-coding the two-hop
13219 // `restart.as_str().as_bytes()` composition. This is the shape
13220 // that reaches the caixa-lacre BLAKE3 content-address closure's
13221 // `blake3::Hasher::update(impl AsRef<[u8]>)` byte-input surface
13222 // through this impl and no other.
13223 for &variant in RestartPolicy::ALL {
13224 let via_generic = generic_bytes_sink(variant);
13225 let via_borrowed_generic = generic_bytes_sink(&variant);
13226 let via_method_bytes = variant.as_str().as_bytes().to_vec();
13227 assert_eq!(
13228 via_generic, via_method_bytes,
13229 "generic `<T: AsRef<[u8]>>`-bound consumer on \
13230 RestartPolicy::{variant:?} must yield the same byte-\
13231 tail RestartPolicy::as_str().as_bytes() returns — \
13232 divergence signals the byte-view axis fails to bridge \
13233 a generic byte-input trait bound to the substrate-\
13234 primitive accessor"
13235 );
13236 assert_eq!(
13237 via_borrowed_generic, via_method_bytes,
13238 "generic `<T: AsRef<[u8]>>`-bound consumer on \
13239 &RestartPolicy::{variant:?} must yield the same byte-\
13240 tail RestartPolicy::as_str().as_bytes() returns — the \
13241 borrowed-input surface must resolve to the same as_str \
13242 dispatch"
13243 );
13244 }
13245 // `blake3::Hasher::update`-shape byte-input surface witness on
13246 // the caixa-lacre compounding target: the `MockHasher` (lifted
13247 // above per `clippy::items_after_statements`) mirrors
13248 // `blake3::Hasher::update` / `ring::digest::Context::update` /
13249 // `sha2::Sha256::update`'s `impl AsRef<[u8]>`-bound update
13250 // signature and accepts a [`super::RestartPolicy`] directly,
13251 // routing its byte-tail through the substrate-primitive
13252 // `as_str` accessor — the shape a future per-child BLAKE3
13253 // content-address closure composes to fold a `:restart`
13254 // discriminator byte-tag into the [`crate::Lacre`] closure
13255 // body.
13256 for &variant in RestartPolicy::ALL {
13257 let mut owned_hasher = MockHasher::new();
13258 owned_hasher.update(variant);
13259 let owned_folded = owned_hasher.finalize();
13260 assert_eq!(
13261 owned_folded,
13262 variant.as_str().as_bytes(),
13263 "`hasher.update(restart)`-shape composition on \
13264 RestartPolicy::{variant:?} must fold the same byte-\
13265 tail RestartPolicy::as_str().as_bytes() returns — the \
13266 shape a future per-child BLAKE3 content-address \
13267 closure composes to fold a `:restart` discriminator \
13268 byte-tag into the Lacre closure body"
13269 );
13270 let mut borrowed_hasher = MockHasher::new();
13271 borrowed_hasher.update(&variant);
13272 let borrowed_folded = borrowed_hasher.finalize();
13273 assert_eq!(
13274 borrowed_folded,
13275 variant.as_str().as_bytes(),
13276 "`hasher.update(&restart)`-shape composition on \
13277 &RestartPolicy::{variant:?} must fold the same byte-\
13278 tail RestartPolicy::as_str().as_bytes() returns — the \
13279 borrowed-input surface must resolve to the same as_str \
13280 dispatch"
13281 );
13282 }
13283 }
13284
13285 #[test]
13286 #[expect(
13287 clippy::too_many_lines,
13288 reason = "the byte-owned reverse-projection axis is closed \
13289 here across the M2-OTP-shape :supervisor slot pair by \
13290 extending onto the second and final M2-OTP-shape \
13291 closed-set fieldless typed-enum peer, so the pin \
13292 binds the new impl against every paired byte-view \
13293 and str-owned axis on the same enum plus a generic \
13294 <T: Into<Vec<u8>>>-bound consumer witness and a \
13295 std::io::Write::write_all-shape owned-byte-sink \
13296 surface witness on both owned and borrowed input \
13297 shapes to lock the whole family against a future \
13298 silent regression"
13299 )]
13300 fn restart_policy_from_into_owned_vec_bytes_routes_through_as_str_accessor() {
13301 // `<T: Into<Vec<u8>>>`-bound-consumer witness helper: a generic
13302 // owned-byte-input function accepts a [`super::RestartPolicy`]
13303 // directly through the trait bound, without the caller open-
13304 // coding the three-hop `restart.as_str().as_bytes().to_vec()`
13305 // composition. Lifted to the top of the function per
13306 // `clippy::items_after_statements`.
13307 fn generic_owned_bytes_sink<T: Into<Vec<u8>>>(t: T) -> Vec<u8> {
13308 t.into()
13309 }
13310 // `std::io::Write::write_all`-shape owned-byte-sink surface
13311 // mock: mirrors `std::io::Write::write_all` /
13312 // `bytes::BytesMut::extend_from_slice` / any per-arm audit-log
13313 // byte-sink that consumes a `Vec<u8>` payload via
13314 // `Into<Vec<u8>>`, so a future per-child per-`:restart` audit-
13315 // log emit reaches the substrate-primitive `as_str` accessor
13316 // through the byte-owned reverse-projection axis and no
13317 // other. Lifted to the top of the function per
13318 // `clippy::items_after_statements`.
13319 struct MockOwnedByteSink(Vec<u8>);
13320 impl MockOwnedByteSink {
13321 fn new() -> Self {
13322 Self(Vec::new())
13323 }
13324 fn write_all(&mut self, bytes: impl Into<Vec<u8>>) -> &mut Self {
13325 self.0.extend(bytes.into());
13326 self
13327 }
13328 fn finalize(self) -> Vec<u8> {
13329 self.0
13330 }
13331 }
13332
13333 // Fail-before-pass-after byte-parity pin on the newly lifted
13334 // `impl From<RestartPolicy> for Vec<u8>` and
13335 // `impl From<&RestartPolicy> for Vec<u8>` — asserts the trait-
13336 // idiomatic byte-owned reverse-projection standard-library
13337 // impls and the substrate-primitive
13338 // [`super::RestartPolicy::as_str`] `pub const fn` accessor's
13339 // `.as_bytes().to_vec()` byte-tail resolve to the same three-
13340 // arm PascalCase wire byte-string emit-set across every arm
13341 // the exhaustive [`super::RestartPolicy::ALL`] slice
13342 // enumerates. Closes the substrate-wide trait-idiomatic byte-
13343 // owned reverse-projection axis on the M2-OTP-shape closed-
13344 // set typed-enum pair the sibling first-mover
13345 // [`super::RestartStrategy`] `From<{Self, &Self}> for Vec<u8>`
13346 // lift (63e5dd0) opened one commit prior, matching the
13347 // trajectory the paired [`AsRef<[u8]>`] borrowed byte-view
13348 // axis campaign already tracked across the same slot pair
13349 // (cd4c4e0 → 98b08fa).
13350 for &variant in RestartPolicy::ALL {
13351 let via_owned_from: Vec<u8> = <Vec<u8> as From<RestartPolicy>>::from(variant);
13352 let via_borrowed_from: Vec<u8> = <Vec<u8> as From<&RestartPolicy>>::from(&variant);
13353 let via_method_bytes: Vec<u8> = variant.as_str().as_bytes().to_vec();
13354 assert_eq!(
13355 via_owned_from, via_method_bytes,
13356 "From<RestartPolicy> for Vec<u8> impl must byte-equal \
13357 RestartPolicy::as_str().as_bytes().to_vec() on \
13358 RestartPolicy::{variant:?} — divergence signals a \
13359 silent detour off the substrate-primitive accessor"
13360 );
13361 assert_eq!(
13362 via_borrowed_from, via_method_bytes,
13363 "From<&RestartPolicy> for Vec<u8> impl must byte-\
13364 equal RestartPolicy::as_str().as_bytes().to_vec() \
13365 on RestartPolicy::{variant:?} — divergence signals \
13366 a silent detour off the substrate-primitive accessor"
13367 );
13368 assert_eq!(
13369 via_owned_from, via_borrowed_from,
13370 "From<RestartPolicy> for Vec<u8> and \
13371 From<&RestartPolicy> for Vec<u8> must byte-equal \
13372 each other on RestartPolicy::{variant:?} — \
13373 divergence signals the owned-input and borrowed-input \
13374 paths have drifted off the same substrate-primitive \
13375 as_str accessor"
13376 );
13377 // Cross-axis witness against the paired [`AsRef<[u8]>`]
13378 // borrowed byte-view axis (98b08fa): the byte-owned
13379 // reverse-projection axis must byte-equal the paired
13380 // borrowed byte-view axis by construction — locking the
13381 // byte-view and byte-owned axes together at the substrate-
13382 // primitive accessor.
13383 let borrowed_bytes: &[u8] = <RestartPolicy as AsRef<[u8]>>::as_ref(&variant);
13384 assert_eq!(
13385 via_owned_from,
13386 borrowed_bytes.to_vec(),
13387 "From<RestartPolicy> for Vec<u8> and AsRef<[u8]> for \
13388 RestartPolicy must resolve to byte-equal byte-tails \
13389 on RestartPolicy::{variant:?} — divergence signals \
13390 the byte-owned and byte-view axes have drifted off \
13391 the same substrate-primitive as_str accessor"
13392 );
13393 // Cross-axis witness against the str-owned reverse-
13394 // projection family's `.into_bytes()` / `.as_bytes().to_vec()`
13395 // byte-tails: every one of `{String, Cow<'static, str>,
13396 // Box<str>, std::sync::Arc<str>}` allocates (or borrows)
13397 // the same PascalCase wire byte-string the substrate-
13398 // primitive accessor emits, so the byte-owned axis must
13399 // byte-equal each of their owned byte-tails by
13400 // construction.
13401 let owned_string: String = <String as From<RestartPolicy>>::from(variant);
13402 assert_eq!(
13403 via_owned_from,
13404 owned_string.into_bytes(),
13405 "From<RestartPolicy> for Vec<u8> and \
13406 String::from(policy).into_bytes() must resolve to \
13407 byte-equal byte-tails on RestartPolicy::{variant:?}"
13408 );
13409 let owned_cow: std::borrow::Cow<'static, str> =
13410 <std::borrow::Cow<'static, str> as From<RestartPolicy>>::from(variant);
13411 assert_eq!(
13412 via_owned_from,
13413 owned_cow.as_bytes().to_vec(),
13414 "From<RestartPolicy> for Vec<u8> and \
13415 From<RestartPolicy> for Cow<'static, str> must \
13416 resolve to byte-equal byte-tails on \
13417 RestartPolicy::{variant:?}"
13418 );
13419 let owned_box: Box<str> = <Box<str> as From<RestartPolicy>>::from(variant);
13420 assert_eq!(
13421 via_owned_from,
13422 owned_box.as_bytes().to_vec(),
13423 "From<RestartPolicy> for Vec<u8> and \
13424 From<RestartPolicy> for Box<str> must resolve to \
13425 byte-equal byte-tails on RestartPolicy::{variant:?}"
13426 );
13427 let owned_arc: std::sync::Arc<str> =
13428 <std::sync::Arc<str> as From<RestartPolicy>>::from(variant);
13429 assert_eq!(
13430 via_owned_from,
13431 owned_arc.as_bytes().to_vec(),
13432 "From<RestartPolicy> for Vec<u8> and \
13433 From<RestartPolicy> for std::sync::Arc<str> must \
13434 resolve to byte-equal byte-tails on \
13435 RestartPolicy::{variant:?}"
13436 );
13437 }
13438 // `<T: Into<Vec<u8>>>`-bound-consumer witness on both owned
13439 // and borrowed input shapes: the generic owned-byte-input
13440 // function `generic_owned_bytes_sink` (lifted above per
13441 // `clippy::items_after_statements`) accepts a
13442 // [`super::RestartPolicy`] and a `&RestartPolicy` directly
13443 // through the trait bound, without the caller open-coding
13444 // the three-hop `restart.as_str().as_bytes().to_vec()`
13445 // composition.
13446 for &variant in RestartPolicy::ALL {
13447 let via_generic_owned = generic_owned_bytes_sink(variant);
13448 // Bind the borrowed-input path through an explicit
13449 // `&RestartPolicy` local so the generic-consumer witness
13450 // routes through `From<&RestartPolicy> for Vec<u8>` (T
13451 // binds to `&RestartPolicy`) rather than clippy-collapsing
13452 // the borrow onto the owned-input peer.
13453 let variant_ref: &RestartPolicy = &variant;
13454 let via_generic_borrowed = generic_owned_bytes_sink(variant_ref);
13455 let via_method_bytes = variant.as_str().as_bytes().to_vec();
13456 assert_eq!(
13457 via_generic_owned, via_method_bytes,
13458 "generic `<T: Into<Vec<u8>>>`-bound consumer on \
13459 RestartPolicy::{variant:?} must yield the same byte-\
13460 tail RestartPolicy::as_str().as_bytes() returns — \
13461 divergence signals the byte-owned axis fails to bridge \
13462 a generic owned-byte-input trait bound to the \
13463 substrate-primitive accessor"
13464 );
13465 assert_eq!(
13466 via_generic_borrowed, via_method_bytes,
13467 "generic `<T: Into<Vec<u8>>>`-bound consumer on \
13468 &RestartPolicy::{variant:?} must yield the same byte-\
13469 tail RestartPolicy::as_str().as_bytes() returns — \
13470 the borrowed-input surface must resolve to the same \
13471 as_str dispatch"
13472 );
13473 }
13474 // `std::io::Write::write_all`-shape owned-byte-sink surface
13475 // witness: the `MockOwnedByteSink` (lifted above per
13476 // `clippy::items_after_statements`) mirrors
13477 // `std::io::Write::write_all` /
13478 // `bytes::BytesMut::extend_from_slice`'s `impl Into<Vec<u8>>`-
13479 // bound owned-byte input signature and accepts a
13480 // [`super::RestartPolicy`] directly on both owned and
13481 // borrowed input shapes, routing its byte-tail through the
13482 // substrate-primitive `as_str` accessor — the shape a future
13483 // per-child per-`:restart` audit-log emit composes to fold a
13484 // `:restart` discriminator byte-tag into a downstream owned-
13485 // byte-sink surface.
13486 for &variant in RestartPolicy::ALL {
13487 let mut owned_sink = MockOwnedByteSink::new();
13488 owned_sink.write_all(variant);
13489 let owned_folded = owned_sink.finalize();
13490 assert_eq!(
13491 owned_folded,
13492 variant.as_str().as_bytes(),
13493 "`sink.write_all(restart)`-shape composition on \
13494 RestartPolicy::{variant:?} must fold the same byte-\
13495 tail RestartPolicy::as_str().as_bytes() returns"
13496 );
13497 let mut borrowed_sink = MockOwnedByteSink::new();
13498 let variant_ref: &RestartPolicy = &variant;
13499 borrowed_sink.write_all(variant_ref);
13500 let borrowed_folded = borrowed_sink.finalize();
13501 assert_eq!(
13502 borrowed_folded,
13503 variant.as_str().as_bytes(),
13504 "`sink.write_all(&restart)`-shape composition on \
13505 &RestartPolicy::{variant:?} must fold the same byte-\
13506 tail RestartPolicy::as_str().as_bytes() returns — \
13507 the borrowed-input surface must resolve to the same \
13508 as_str dispatch"
13509 );
13510 }
13511 }
13512
13513 #[test]
13514 fn restart_policy_all_enumerates_every_variant_exactly_once() {
13515 // Fail-before-pass-after pin on the [`RestartPolicy::ALL`]
13516 // exhaustive-iteration surface: every variant appears exactly
13517 // once, and the slice length matches the arm count of the
13518 // closed set. Every consumer that walks the accepted-policy
13519 // set (a future `feira supervisor --restart …` CLI-side
13520 // arg-parse's "did you mean" hint, a future M4 admission-
13521 // webhook's per-child rejection body naming the accepted-
13522 // `:restart` list, the [`RestartPolicy::from_wire`] reverse-
13523 // projection consumers that iterate the accept-set for
13524 // diagnostic rendering) reads through this slice, so a future
13525 // arm addition that grows the enum but forgets to grow
13526 // [`Self::ALL`] silently truncates every downstream consumer's
13527 // accept-set at the same pre-addition boundary — this pin
13528 // fails at caixa-core build time on the pairwise-distinct +
13529 // arm-count invariants.
13530 //
13531 // Peer of the sibling [`RestartStrategy::ALL`] (4eec29c) /
13532 // [`crate::CaixaKind::ALL`] (6b1f4fb) /
13533 // [`crate::aplicacao::PlacementStrategy::ALL`] (18c7342) /
13534 // [`crate::aplicacao::RateLimitUnit::ALL`] (6bce03d) /
13535 // [`crate::dep::DepList::ALL`] (45ee563) exhaustive-iteration
13536 // pins on the peer closed-set typed-enum axes.
13537 let all: &[RestartPolicy] = RestartPolicy::ALL;
13538 assert_eq!(
13539 all.len(),
13540 3,
13541 "RestartPolicy::ALL must enumerate every variant of the \
13542 three-arm closed set (Permanent, Temporary, Transient); \
13543 got {all:?}"
13544 );
13545 for (i, a) in all.iter().enumerate() {
13546 for (j, b) in all.iter().enumerate() {
13547 if i != j {
13548 assert_ne!(
13549 a, b,
13550 "RestartPolicy::ALL must carry every variant exactly \
13551 once — got duplicate {a:?} at indices {i} and {j}"
13552 );
13553 }
13554 }
13555 }
13556 for variant in [
13557 RestartPolicy::Permanent,
13558 RestartPolicy::Temporary,
13559 RestartPolicy::Transient,
13560 ] {
13561 assert!(
13562 all.contains(&variant),
13563 "RestartPolicy::ALL must contain {variant:?} — a future arm \
13564 addition that grows the enum but forgets to grow the ALL slice \
13565 silently truncates every downstream consumer's accept-set at \
13566 the pre-addition boundary"
13567 );
13568 }
13569 }
13570
13571 #[test]
13572 fn restart_policy_wire_names_covers_every_arm() {
13573 // Load-bearing pin on the substrate-canonical
13574 // [`RestartPolicy::WIRE_NAMES`] exhaustive accept-set roster on
13575 // the `PascalCase` wire byte-string axis: every variant of the
13576 // sibling [`RestartPolicy::ALL`] exhaustive-iteration surface
13577 // must project through [`RestartPolicy::as_str`] onto an entry
13578 // the [`RestartPolicy::WIRE_NAMES`] roster carries, and the
13579 // roster's length must byte-equal `RestartPolicy::ALL.len()` so
13580 // a silent skew between the [`RestartPolicy::as_str`] match's
13581 // arm-set and the roster's arm-set trips here at caixa-core
13582 // test time rather than at a downstream M4
13583 // `mesh.pleme.io/v1alpha1/Supervisor` CR admission-webhook
13584 // rejection body's wire-form `:restart` accepted-set
13585 // enumeration miss / a `feira supervisor --restart …` "did you
13586 // mean" hint drift / a future wasm-operator per-reconcile-step
13587 // diagnostic log line's accepted-wire-form enumeration miss.
13588 // A future arm addition (an OTP-`intrinsic` fourth arm the
13589 // theory
13590 // [`ABSORPTION-ROADMAP`](https://github.com/pleme-io/theory/blob/main/ABSORPTION-ROADMAP.md)
13591 // might reach for once the three canonical OTP restart policies
13592 // stop covering the substrate's discovered load-shape) extends
13593 // [`RestartPolicy::ALL`] as a single edit and this pin sweeps
13594 // the new arm by iteration; the paired
13595 // [`RestartPolicy::WIRE_NAMES`] roster must grow in lockstep or
13596 // this assertion trips. Every entry is further pinned to open
13597 // with an ASCII uppercase byte so a silent collapse of the
13598 // wire-form axis with the peer kebab-case dispatcher-catalog
13599 // axis (an entry byte-identical to a sibling
13600 // [`RestartPolicy::discriminant`] kebab byte-string that would
13601 // let a wire-axis consumer accept the dispatcher-catalog
13602 // vocabulary) trips here rather than at a downstream K8s-CR
13603 // round-trip miss.
13604 //
13605 // Peer of the sibling
13606 // [`restart_strategy_wire_names_covers_every_arm`] (3033f45)
13607 // pin on the first M2 OTP-shape sibling-restart closed-set
13608 // typed enum, the sibling
13609 // [`crate::aplicacao::tests::placement_strategy_wire_names_covers_every_arm`]
13610 // (3e5b194) pin on the first M3 mesh-shape distribution-strategy
13611 // closed-set typed enum, the sibling
13612 // [`crate::kind::tests::caixa_kind_wire_names_covers_every_arm`]
13613 // (bd708bd) pin on the top-level typed-kind discriminator's
13614 // `PascalCase` wire byte-string axis, and the sibling
13615 // [`crate::upgrade::tests::upgrade_instruction_wire_forms_covers_every_arm`]
13616 // (cc42c0e) /
13617 // [`crate::upgrade::tests::upgrade_instruction_lisp_forms_covers_every_arm`]
13618 // (1898d77) pins on the OTP-appup discriminator's two-axis
13619 // roster split — the same closed-set exhaustive-roster coverage
13620 // discipline extended here onto the second and final M2
13621 // OTP-shape sibling-enum on the caixa surface, closing the
13622 // per-child restart-decision-policy axis paired with the peer
13623 // per-supervisor sibling-restart-strategy axis on the same M2
13624 // `:supervisor` slot.
13625 //
13626 // Fail-before-pass-after locally verified by mutating one arm
13627 // of the paired [`crate::render::SUPERVISOR_CHILD_RESTART_*`]
13628 // const family (e.g. dropping the trailing `t` from
13629 // `"Permanent"` → `"Permanen"`) — the length pin still passes
13630 // but the `contains` check fires on the mutated arm; and by
13631 // shortening the roster to two entries — the length pin fires
13632 // first.
13633 assert_eq!(
13634 RestartPolicy::WIRE_NAMES.len(),
13635 RestartPolicy::ALL.len(),
13636 "RestartPolicy::WIRE_NAMES.len() must byte-equal \
13637 RestartPolicy::ALL.len() — a mismatch means the roster \
13638 and the enum's arm-set have drifted; downstream consumers \
13639 that fan through both will silently disagree on the \
13640 accepted arm-set"
13641 );
13642 for &variant in RestartPolicy::ALL {
13643 let wire = variant.as_str();
13644 assert!(
13645 RestartPolicy::WIRE_NAMES.contains(&wire),
13646 "RestartPolicy::{variant:?}.as_str() = {wire:?} must \
13647 be a member of RestartPolicy::WIRE_NAMES — the \
13648 emitter and the roster have drifted out of lockstep"
13649 );
13650 }
13651 for tag in RestartPolicy::WIRE_NAMES {
13652 let first = tag.chars().next().unwrap_or_else(|| {
13653 panic!(
13654 "RestartPolicy::WIRE_NAMES entry {tag:?} must be \
13655 a non-empty PascalCase byte-string"
13656 )
13657 });
13658 assert!(
13659 first.is_ascii_uppercase(),
13660 "RestartPolicy::WIRE_NAMES entry {tag:?} must open \
13661 with an ASCII uppercase byte (PascalCase wire form) — \
13662 a lowercase entry would collide the wire-form axis \
13663 with the peer kebab-case dispatcher-catalog axis \
13664 [`RestartPolicy::discriminant`] serves"
13665 );
13666 }
13667 }
13668
13669 #[test]
13670 fn restart_policy_from_wire_accepts_every_lifted_constant() {
13671 // Fail-before-pass-after pin on the forward accept-set of the
13672 // [`RestartPolicy::from_wire`] reverse projection: every
13673 // canonical [`crate::render::SUPERVISOR_CHILD_RESTART_*`]
13674 // constant the [`RestartPolicy::as_str`] emitter walks parses
13675 // back to its paired variant. Any future arm addition that
13676 // grows the emitter's `as_str` match but forgets to grow the
13677 // parser's `from_wire` match silently splits the two halves of
13678 // the round-trip — the wire byte-string one non-serde consumer
13679 // parses from the one the emitter wrote — with the failure
13680 // surfacing at the operator's reconcile posture (a `:temporary`
13681 // `oneShot` child restarted on clean exit, a `:transient` child
13682 // restarted after clean completion) far from the rebrand
13683 // commit. Pinning the three-arm accept-set here catches the
13684 // drift at caixa-core build time.
13685 //
13686 // Peer of the sibling [`RestartStrategy::from_wire`] (4eec29c)
13687 // + [`crate::CaixaKind::from_wire`] (2aa6d23)
13688 // + [`crate::aplicacao::PlacementStrategy::from_wire`] (18c7342)
13689 // accept-set pins on the peer closed-set typed-enum `str → Self`
13690 // axes.
13691 for (wire, expected) in [
13692 (
13693 crate::render::SUPERVISOR_CHILD_RESTART_PERMANENT,
13694 RestartPolicy::Permanent,
13695 ),
13696 (
13697 crate::render::SUPERVISOR_CHILD_RESTART_TEMPORARY,
13698 RestartPolicy::Temporary,
13699 ),
13700 (
13701 crate::render::SUPERVISOR_CHILD_RESTART_TRANSIENT,
13702 RestartPolicy::Transient,
13703 ),
13704 ] {
13705 let parsed = RestartPolicy::from_wire(wire).unwrap_or_else(|| {
13706 panic!(
13707 "RestartPolicy::from_wire({wire:?}) must accept every \
13708 SUPERVISOR_CHILD_RESTART_* constant — got None for the \
13709 lifted canonical byte-string that RestartPolicy::{expected:?} \
13710 serializes as under SUPERVISOR_CHILD_KEY_RESTART"
13711 )
13712 });
13713 assert_eq!(
13714 parsed, expected,
13715 "RestartPolicy::from_wire({wire:?}) must return \
13716 RestartPolicy::{expected:?}; got RestartPolicy::{parsed:?}"
13717 );
13718 }
13719 }
13720
13721 #[test]
13722 fn restart_policy_from_wire_round_trips_through_as_str() {
13723 // Fail-before-pass-after pin on the closed round-trip between
13724 // the forward [`RestartPolicy::as_str`] emitter and the
13725 // reverse [`RestartPolicy::from_wire`] parser: for every
13726 // variant in [`RestartPolicy::ALL`], parsing the emitter's
13727 // output must return exactly the same variant. Any per-arm
13728 // divergence — a future arm added to `as_str` but not
13729 // `from_wire`, an accidental copy-paste flip in one but not
13730 // the other — silently splits the emit and parse halves and
13731 // the failure surfaces at consumer parse time far from the
13732 // drift site. The `ALL`-iterating shape means a future arm
13733 // addition picks up the coverage by construction.
13734 //
13735 // Peer of the sibling
13736 // [`restart_strategy_from_wire_round_trips_through_as_str`]
13737 // (4eec29c) round-trip pin on
13738 // [`RestartStrategy::from_wire`] and the M3
13739 // [`crate::aplicacao::tests::placement_strategy_from_wire_round_trips_through_as_str`]
13740 // (18c7342) round-trip pin on
13741 // [`crate::aplicacao::PlacementStrategy::from_wire`].
13742 for &variant in RestartPolicy::ALL {
13743 let wire = variant.as_str();
13744 let parsed = RestartPolicy::from_wire(wire).unwrap_or_else(|| {
13745 panic!(
13746 "RestartPolicy::from_wire(RestartPolicy::{variant:?}.as_str()) \
13747 must be Some({variant:?}) — the two halves of the round-trip \
13748 dispatch on the same lifted SUPERVISOR_CHILD_RESTART_* consts; \
13749 got None on wire byte-string {wire:?}"
13750 )
13751 });
13752 assert_eq!(
13753 parsed, variant,
13754 "RestartPolicy::from_wire(RestartPolicy::{variant:?}.as_str()) \
13755 must round-trip to the same variant; got {parsed:?}"
13756 );
13757 }
13758 }
13759
13760 #[test]
13761 fn restart_policy_from_wire_rejects_unknown_byte_strings() {
13762 // Fail-before-pass-after pin on the closed-set refusal
13763 // discipline of [`RestartPolicy::from_wire`]: every
13764 // byte-string outside the three-arm accept-set returns `None`
13765 // rather than silently collapsing onto the [`Default`]
13766 // (`Permanent`) arm or an arbitrary neighbor. The refusal set
13767 // exercised here sweeps the load-bearing drift shapes: the
13768 // empty string (a stripped serde-attribute drift), all-
13769 // whitespace strings (the canonical text-editor accidental
13770 // padding shape), the kebab-case dispatcher-catalog identities
13771 // (`"permanent"` / `"temporary"` / `"transient"` — the
13772 // [`gen_platform::FromStrKind`]-derived [`std::str::FromStr`]
13773 // accept-set, which parses the *other* axis of this enum's
13774 // two-axis split and must not leak into the `from_wire`
13775 // PascalCase-wire accept-set — a lowercase leak here would
13776 // silently accept the operator's kebab-case
13777 // dispatcher-catalog probe under the wire-axis parser and mis-
13778 // route a `:permanent` intent), the padded canonical scalar
13779 // (`" Permanent "`), the trailing-newline shapes
13780 // (`"Permanent\n"`), the uppercase-single-word forms
13781 // (`"PERMANENT"`), and neighboring-but-unknown arms
13782 // (`"Restart"` — the canonical typo direction toward the
13783 // sibling [`RestartStrategy`] enum's own wire-arm namespace).
13784 //
13785 // Peer of the sibling
13786 // [`restart_strategy_from_wire_rejects_unknown_byte_strings`]
13787 // (4eec29c) +
13788 // [`crate::kind::tests::caixa_kind_from_wire_rejects_unknown_byte_strings`]
13789 // (2aa6d23) +
13790 // [`crate::aplicacao::tests::placement_strategy_from_wire_rejects_unknown_byte_strings`]
13791 // (18c7342) refusal pins on the peer closed-set typed-enum
13792 // axes.
13793 for bad in [
13794 "",
13795 " ",
13796 "\n",
13797 "\t",
13798 "permanent",
13799 "temporary",
13800 "transient",
13801 "PERMANENT",
13802 "TEMPORARY",
13803 "TRANSIENT",
13804 "Permanents",
13805 "Permanent ",
13806 " Permanent",
13807 " Transient ",
13808 "Permanent\n",
13809 "perma",
13810 "Trans",
13811 "OneForOne",
13812 "Restart",
13813 "?",
13814 ] {
13815 assert!(
13816 RestartPolicy::from_wire(bad).is_none(),
13817 "RestartPolicy::from_wire({bad:?}) must return None — the \
13818 parser's accept-set is exactly the three RestartPolicy::as_str \
13819 outputs (Permanent, Temporary, Transient), and this \
13820 byte-string is outside that closed set"
13821 );
13822 }
13823 }
13824
13825 #[test]
13826 fn restart_policy_from_wire_matches_serialize_derive_wire_byte_string() {
13827 // Fail-before-pass-after pin on the fourth path of the four-path
13828 // convergence: `from_wire` (the reverse projection) inverts the
13829 // `Serialize` derive's wire byte-string on every variant.
13830 // Together with the pre-existing three-path convergence
13831 // (`Display` + `as_str` + `Serialize` all resolve to the same
13832 // lifted [`crate::render::SUPERVISOR_CHILD_RESTART_*`] const,
13833 // pinned by
13834 // [`restart_policy_display_matches_serialized_wire_byte_string`])
13835 // this closes the round-trip: the wire byte-string the
13836 // `Serialize` derive emits parses back to the same variant
13837 // through `from_wire`, so any future serde-attribute or variant-
13838 // rename drift on the emit half now surfaces as a matched drift
13839 // on the parse half at caixa-core build time — the two halves
13840 // migrate as a unit through the lifted consts on any future
13841 // rename, and the round-trip cannot silently split.
13842 //
13843 // Peer of the sibling
13844 // [`restart_strategy_from_wire_matches_serialize_derive_wire_byte_string`]
13845 // (4eec29c) wire-format pin on
13846 // [`RestartStrategy::from_wire`] and the M3
13847 // [`crate::aplicacao::tests::placement_strategy_from_wire_matches_serialize_derive_wire_byte_string`]
13848 // (18c7342) wire-format pin on
13849 // [`crate::aplicacao::PlacementStrategy::from_wire`].
13850 for &variant in RestartPolicy::ALL {
13851 let wire = serde_json::to_string(&variant).unwrap();
13852 let unquoted = wire
13853 .strip_prefix('"')
13854 .and_then(|s| s.strip_suffix('"'))
13855 .expect("serialized RestartPolicy is a JSON string");
13856 let parsed = RestartPolicy::from_wire(unquoted).unwrap_or_else(|| {
13857 panic!(
13858 "RestartPolicy::from_wire({unquoted:?}) must accept the \
13859 Serialize derive's wire byte-string for \
13860 RestartPolicy::{variant:?} — the four-path convergence \
13861 (Display + as_str + Serialize + from_wire) resolves through \
13862 the same lifted SUPERVISOR_CHILD_RESTART_* const; got None"
13863 )
13864 });
13865 assert_eq!(
13866 parsed, variant,
13867 "RestartPolicy::from_wire of the Serialize derive's wire \
13868 byte-string for RestartPolicy::{variant:?} must round-trip \
13869 to the same variant; got {parsed:?}"
13870 );
13871 }
13872 }
13873
13874 // ── drift-detection: ChildSpec::nome accessor pins ────────────────────
13875 //
13876 // The M2 supervisor-tree sibling of the M3 `Membro::nome` (4a32abf) pin
13877 // pair (`membro_nome_returns_caixa_byte_equal_across_permutations` +
13878 // `membro_nome_borrows_from_caixa_storage`) — extended here to the M2
13879 // per-`:children` child-caixa `:nome` axis, sibling to the first M2
13880 // slot scalar accessor `UpgradeFromEntry::prior_versao` (75d27a8) on
13881 // the peer per-`:upgrade-from :from` axis. The three pins jointly
13882 // brace the accessor against every future silent detour that would
13883 // desynchronize it from the raw `.caixa` field access every consumer
13884 // previously open-coded.
13885
13886 #[test]
13887 fn child_spec_nome_returns_caixa_byte_equal_across_permutations() {
13888 // The canonical per-`:children` child-caixa `:nome`-scalar pin:
13889 // [`ChildSpec::nome`] must return the `:children :caixa` field
13890 // byte-for-byte across every DNS-1123-label value the upstream
13891 // [`crate::render::require_valid_dns_1123_label`] gate at
13892 // `SupervisorSpec::validate` admits. Peer of the sibling
13893 // `membro_nome_returns_caixa_byte_equal_across_permutations`
13894 // (4a32abf) pin on the M3 per-`:membros` axis — same "the
13895 // substrate-primitive accessor must byte-equal the raw field
13896 // access verbatim across every author-declared value" discipline
13897 // extended to the M2 supervisor-tree per-`:children` arm. Pins
13898 // against a future silent detour that re-normalized the child
13899 // identity (an accidental `.to_lowercase()` — every `:children
13900 // :caixa` is validated as a DNS-1123 label upstream, so any
13901 // re-normalization is redundant + a drift surface between the
13902 // validator and the accessor), a namespace-prefix rewrite (an
13903 // accidental `format!("{namespace}/{caixa}")` per-CR
13904 // fully-qualified rewrite that didn't land on the peer axes), or
13905 // a per-cluster alias stamp the future wasm-operator's
13906 // hierarchical reconciliation scheduler authors on one consumer
13907 // without the others. Five values sweep the accept-set the
13908 // DNS-1123 gate upstream admits (short single-word / dashed /
13909 // v-suffixed / mixed-digit child names).
13910 for name in [
13911 "worker",
13912 "cache-server",
13913 "scratch-job",
13914 "orders-v2",
13915 "session-8080",
13916 ] {
13917 let c = ChildSpec {
13918 caixa: name.into(),
13919 versao: "^0.1".into(),
13920 restart: RestartPolicy::Permanent,
13921 };
13922 assert_eq!(
13923 c.nome(),
13924 name,
13925 "ChildSpec::nome must return :children :caixa verbatim \
13926 (got {:?}, expected {name:?})",
13927 c.nome(),
13928 );
13929 assert_eq!(
13930 c.nome(),
13931 c.caixa.as_str(),
13932 "ChildSpec::nome must byte-equal the .caixa field access",
13933 );
13934 }
13935 }
13936
13937 #[test]
13938 fn child_spec_nome_borrows_from_caixa_storage() {
13939 // The borrow-not-copy pin: [`ChildSpec::nome`] must return a
13940 // `&str` slice that borrows from the typed slot's own [`String`]
13941 // storage — same-address invariant with `c.caixa.as_str()`. Pins
13942 // against a future silent detour that allocated a fresh `String`
13943 // (`self.caixa.clone()` in the body would type-check but silently
13944 // drop the borrow, and every downstream consumer that assumed
13945 // the returned slice outlives `&self` would break on a stale-
13946 // reference use-after-free — the [`crate::render::insert_first_seen`]
13947 // dedup key at [`SupervisorSpec::validate`], the
13948 // [`validate_no_self_supervision`] equality check against the
13949 // parent's `:nome` string slice, the DNS-1123 gate's `&str`
13950 // borrow — each would silently misbehave if this accessor
13951 // produced a detached copy). Peer of the sibling
13952 // `membro_nome_borrows_from_caixa_storage` (4a32abf) pin on the
13953 // M3 per-`:membros` axis and the
13954 // `prior_versao_borrows_from_from_storage` (75d27a8) pin on the
13955 // first M2 slot scalar accessor.
13956 let c = ChildSpec {
13957 caixa: "worker".into(),
13958 versao: "^0.1".into(),
13959 restart: RestartPolicy::Permanent,
13960 };
13961 let name = c.nome();
13962 let caixa_slice = c.caixa.as_str();
13963 assert_eq!(
13964 name.as_ptr(),
13965 caixa_slice.as_ptr(),
13966 "ChildSpec::nome must borrow from the .caixa String's backing \
13967 storage — a fresh allocation here means the accessor no \
13968 longer names the substrate-primitive typed dispatch and \
13969 every downstream consumer would silently carry a detached \
13970 copy",
13971 );
13972 assert_eq!(
13973 name.len(),
13974 caixa_slice.len(),
13975 "ChildSpec::nome and .caixa.as_str() must byte-equal in length \
13976 as well as in address",
13977 );
13978 }
13979
13980 #[test]
13981 fn validate_gates_child_nome_through_lifted_accessor() {
13982 // Bilateral coherence pin: every `:children :caixa` that
13983 // [`SupervisorSpec::validate`] accepts is one
13984 // [`crate::render::require_valid_dns_1123_label`] accepts on the
13985 // accessor-projected value, and vice versa on the reject side.
13986 // This closes the "the validator reads through the accessor"
13987 // contract structurally — a future silent detour that made the
13988 // accessor return a different byte-string than the validator
13989 // gates against would surface here as a coverage mismatch, not
13990 // as an apply-time DNS-1123 rejection at
13991 // `metadata.name: Invalid value` far from the caixa.lisp source.
13992 // Peer of the M2 sibling
13993 // `validate_parses_prior_versao_through_lifted_accessor`
13994 // (75d27a8) on the per-`:upgrade-from :from` axis and the M3
13995 // `validate_membros` peer discipline.
13996 //
13997 // Accept-set sweep: five DNS-1123-label values the upstream gate
13998 // admits.
13999 for ok_name in ["a", "worker", "cache-server", "orders-v2", "svc-8080"] {
14000 let s = SupervisorSpec {
14001 children: vec![ChildSpec {
14002 caixa: ok_name.into(),
14003 versao: "^0.1".into(),
14004 restart: RestartPolicy::Permanent,
14005 }],
14006 ..SupervisorSpec::default()
14007 };
14008 s.validate().unwrap_or_else(|e| {
14009 panic!(
14010 "SupervisorSpec::validate must accept :children :caixa {ok_name:?} \
14011 (upstream DNS-1123 gate accepts it): got {e:?}",
14012 );
14013 });
14014 let c = ChildSpec {
14015 caixa: ok_name.into(),
14016 versao: "^0.1".into(),
14017 restart: RestartPolicy::Permanent,
14018 };
14019 crate::render::require_valid_dns_1123_label(c.nome(), || (), |_reason| ())
14020 .unwrap_or_else(|()| {
14021 panic!(
14022 "require_valid_dns_1123_label must accept the accessor-projected \
14023 :children :caixa {ok_name:?}",
14024 );
14025 });
14026 }
14027 // Reject-set sweep: five DNS-1123-label-violating shapes the
14028 // upstream gate refuses (empty / uppercase / underscore / dot /
14029 // leading-hyphen). Every rejection at the validator must
14030 // correspond to a rejection when the accessor's projected value
14031 // is fed back through the shared gate.
14032 for bad_name in ["", "Worker", "my_worker", "team.worker", "-worker"] {
14033 let s = SupervisorSpec {
14034 children: vec![ChildSpec {
14035 caixa: bad_name.into(),
14036 versao: "^0.1".into(),
14037 restart: RestartPolicy::Permanent,
14038 }],
14039 ..SupervisorSpec::default()
14040 };
14041 let err = s.validate().unwrap_err();
14042 assert!(
14043 matches!(
14044 err,
14045 SupervisorError::EmptyChildName | SupervisorError::ChildCaixaInvalid { .. }
14046 ),
14047 "SupervisorSpec::validate must reject :children :caixa {bad_name:?} \
14048 via the DNS-1123 gate: got {err:?}",
14049 );
14050 let c = ChildSpec {
14051 caixa: bad_name.into(),
14052 versao: "^0.1".into(),
14053 restart: RestartPolicy::Permanent,
14054 };
14055 assert!(
14056 crate::render::require_valid_dns_1123_label(c.nome(), || (), |_reason| (),)
14057 .is_err(),
14058 "require_valid_dns_1123_label must reject the accessor-projected \
14059 :children :caixa {bad_name:?}",
14060 );
14061 }
14062 }
14063
14064 // ── drift-detection: ChildSpec::versao_requirement accessor pins ──────
14065 //
14066 // Sibling of the peer per-`:membros` `membro_versao_requirement_*`
14067 // (a40b0e3) pin pair on the M3 mesh-slot surface — extended here to the
14068 // M2 supervisor-tree per-`:children` child-`:versao` axis, sibling to
14069 // the just-landed [`ChildSpec::nome`] (57c61d0) child-`:nome` pin
14070 // trio on the peer per-`:children` `String`-carry axis. The three pins
14071 // jointly brace the accessor against every future silent detour that
14072 // would desynchronize it from the raw `.versao` field access the
14073 // requirement gate + error carrier previously open-coded.
14074 //
14075 // Closes the last unlifted per-`:children` `String`-carry axis: the
14076 // pair (`nome`, `versao_requirement`) now jointly projects the
14077 // (`.caixa`, `.versao`) field pair every OTP-shape supervisor-tree
14078 // consumer that fans on per-child identity + version pin reads,
14079 // matching the peer M3 (`Membro::nome`, `Membro::versao_requirement`)
14080 // pair discipline verbatim.
14081 #[test]
14082 fn child_spec_versao_requirement_returns_versao_byte_equal_across_permutations() {
14083 // The canonical per-`:children` child-`:versao`-scalar pin:
14084 // [`ChildSpec::versao_requirement`] must return the `:children
14085 // :versao` field byte-for-byte across every Cargo-shaped semver
14086 // requirement value the upstream
14087 // [`crate::render::require_valid_versao_requirement`] gate admits.
14088 // Peer of the sibling
14089 // `membro_versao_requirement_returns_versao_byte_equal_across_permutations`
14090 // (a40b0e3) pin on the M3 per-`:membros` axis — same "the
14091 // substrate-primitive accessor must byte-equal the raw field
14092 // access verbatim across every author-declared value" discipline
14093 // extended to the M2 supervisor-tree per-`:children` arm. Pins
14094 // against a future silent detour that re-canonicalized the
14095 // requirement (an accidental `.to_string()` via
14096 // [`crate::version::parse_requirement`] → [`std::fmt::Display`]
14097 // round-trip that collapsed `"^0.1"` to `">=0.1, <0.2"` and
14098 // silently drifted the error carrier's quoted requirement away
14099 // from the source `caixa.lisp`, an accidental whitespace trim on
14100 // `"^ 0.1"` that no consumer ever produced from the field-access
14101 // side, an accidental per-cluster lacre-projected concrete-version
14102 // rewrite that didn't land on the peer requirement-gate call).
14103 // Five values sweep the accept-set the shared
14104 // [`crate::render::require_valid_versao_requirement`] gate admits
14105 // (caret / tilde / exact / wildcard / bare-major).
14106 for req in ["^0.1", "~0.1.2", "0.1.0", "*", "^1"] {
14107 let c = ChildSpec {
14108 caixa: "worker".into(),
14109 versao: req.into(),
14110 restart: RestartPolicy::Permanent,
14111 };
14112 assert_eq!(
14113 c.versao_requirement(),
14114 req,
14115 "ChildSpec::versao_requirement must return :children :versao \
14116 verbatim (got {:?}, expected {req:?})",
14117 c.versao_requirement(),
14118 );
14119 assert_eq!(
14120 c.versao_requirement(),
14121 c.versao.as_str(),
14122 "ChildSpec::versao_requirement must byte-equal the .versao \
14123 field access",
14124 );
14125 }
14126 }
14127
14128 #[test]
14129 fn child_spec_versao_requirement_borrows_from_versao_storage() {
14130 // The borrow-not-copy pin: [`ChildSpec::versao_requirement`] must
14131 // return a `&str` slice that borrows from the typed slot's own
14132 // [`String`] storage — same-address invariant with
14133 // `c.versao.as_str()`. Pins against a future silent detour that
14134 // allocated a fresh `String` (`self.versao.clone()` in the body
14135 // would type-check but silently drop the borrow, and every
14136 // downstream consumer that assumed the returned slice outlives
14137 // `&self` — the [`crate::render::require_valid_versao_requirement`]
14138 // gate's `&str` borrow, the [`SupervisorError::ChildVersaoInvalid`]
14139 // `.to_string()` carrier's byte-length assumption — would silently
14140 // misbehave if this accessor produced a detached copy). Peer of
14141 // the sibling `child_spec_nome_borrows_from_caixa_storage`
14142 // (57c61d0) pin on the per-`:children` `:nome` axis and the M3
14143 // `membro_versao_requirement_borrows_from_versao_storage` (a40b0e3)
14144 // pin on the peer per-`:membros` `:versao` axis.
14145 let c = ChildSpec {
14146 caixa: "worker".into(),
14147 versao: "^0.1".into(),
14148 restart: RestartPolicy::Permanent,
14149 };
14150 let req = c.versao_requirement();
14151 let versao_slice = c.versao.as_str();
14152 assert_eq!(
14153 req.as_ptr(),
14154 versao_slice.as_ptr(),
14155 "ChildSpec::versao_requirement must borrow from the .versao \
14156 String's backing storage — a fresh allocation here means the \
14157 accessor no longer names the substrate-primitive typed \
14158 dispatch and every downstream consumer would silently carry \
14159 a detached copy",
14160 );
14161 assert_eq!(
14162 req.len(),
14163 versao_slice.len(),
14164 "ChildSpec::versao_requirement and .versao.as_str() must \
14165 byte-equal in length as well as in address",
14166 );
14167 }
14168
14169 #[test]
14170 fn validate_gates_child_versao_through_lifted_accessor() {
14171 // Bilateral coherence pin: every `:children :versao` that
14172 // [`SupervisorSpec::validate`] accepts is one
14173 // [`crate::render::require_valid_versao_requirement`] accepts on
14174 // the accessor-projected value, and vice versa on the reject side.
14175 // This closes the "the validator reads through the accessor"
14176 // contract structurally — a future silent detour that made the
14177 // accessor return a different byte-string than the validator gates
14178 // against would surface here as a coverage mismatch, not as a
14179 // resolver-time semver-parse rejection at lacre-closure time far
14180 // from the caixa.lisp source. Peer of the sibling
14181 // `validate_gates_child_nome_through_lifted_accessor` (57c61d0) on
14182 // the per-`:children :caixa` axis and the M2
14183 // `validate_parses_prior_versao_through_lifted_accessor` (75d27a8)
14184 // on the peer per-`:upgrade-from :from` axis.
14185 //
14186 // Accept-set sweep: five Cargo-shaped semver requirement values
14187 // the upstream gate admits (caret / tilde / exact / wildcard /
14188 // bare-major).
14189 for ok_req in ["^0.1", "~0.1.2", "0.1.0", "*", "^1"] {
14190 let s = SupervisorSpec {
14191 children: vec![ChildSpec {
14192 caixa: "worker".into(),
14193 versao: ok_req.into(),
14194 restart: RestartPolicy::Permanent,
14195 }],
14196 ..SupervisorSpec::default()
14197 };
14198 s.validate().unwrap_or_else(|e| {
14199 panic!(
14200 "SupervisorSpec::validate must accept :children :versao {ok_req:?} \
14201 (upstream versao-requirement gate accepts it): got {e:?}",
14202 );
14203 });
14204 let c = ChildSpec {
14205 caixa: "worker".into(),
14206 versao: ok_req.into(),
14207 restart: RestartPolicy::Permanent,
14208 };
14209 crate::render::require_valid_versao_requirement(
14210 c.versao_requirement(),
14211 || (),
14212 |_reason| (),
14213 )
14214 .unwrap_or_else(|()| {
14215 panic!(
14216 "require_valid_versao_requirement must accept the accessor-projected \
14217 :children :versao {ok_req:?}",
14218 );
14219 });
14220 }
14221 // Reject-set sweep: five requirement-violating shapes the upstream
14222 // gate refuses. The empty string closes the empty-first arm of the
14223 // shared [`crate::render::require_valid_versao_requirement`]
14224 // cascade; the four non-empty arms exercise distinct semver-parse
14225 // failure modes the M3 peer per-`:membros` reject-set already pins
14226 // (`rejects_invalid_membro_versao_requirement` on `^bad-version`,
14227 // `rejects_membro_versao_with_double_caret_typo` on `^^0.1`,
14228 // `rejects_membro_versao_with_v_prefixed_tag` on `v0.1`) — the
14229 // shared parser routing means the same reject-set must fail
14230 // identically at the M2 supervisor-tree per-`:children` accessor
14231 // arm here. Every rejection at the validator must correspond to a
14232 // rejection when the accessor's projected value is fed back
14233 // through the shared gate.
14234 //
14235 // (Bare partial magnitudes like `"0.1"` and bare identifiers like
14236 // `"not-a-semver"` are intentionally *not* in the reject-set: the
14237 // semver crate accepts `"0.1"` as an implicit `^0.1` requirement,
14238 // and the identifier-tail arm's grammar admits some non-canonical
14239 // shapes — matching what the M3 peer test suite already documents
14240 // as the shared parser's accept-set edges.)
14241 for bad_req in ["", "v0.1.0", "^bad-version", "^^0.1", "v0.1"] {
14242 let s = SupervisorSpec {
14243 children: vec![ChildSpec {
14244 caixa: "worker".into(),
14245 versao: bad_req.into(),
14246 restart: RestartPolicy::Permanent,
14247 }],
14248 ..SupervisorSpec::default()
14249 };
14250 let err = s.validate().unwrap_err();
14251 assert!(
14252 matches!(
14253 err,
14254 SupervisorError::EmptyChildVersion { .. }
14255 | SupervisorError::ChildVersaoInvalid { .. }
14256 ),
14257 "SupervisorSpec::validate must reject :children :versao {bad_req:?} \
14258 via the versao-requirement gate: got {err:?}",
14259 );
14260 let c = ChildSpec {
14261 caixa: "worker".into(),
14262 versao: bad_req.into(),
14263 restart: RestartPolicy::Permanent,
14264 };
14265 assert!(
14266 crate::render::require_valid_versao_requirement(
14267 c.versao_requirement(),
14268 || (),
14269 |_reason| (),
14270 )
14271 .is_err(),
14272 "require_valid_versao_requirement must reject the accessor-projected \
14273 :children :versao {bad_req:?}",
14274 );
14275 }
14276 }
14277
14278 // ── per-`:children` `:restart` typed-accessor coherence pins ──────────
14279 //
14280 // The [`ChildSpec::restart`] accessor lift closes the last unlifted
14281 // per-`:children` axis (the pair `nome()` + `versao_requirement()`
14282 // already project the `String`-carry `(caixa, versao)` fields; the
14283 // `Copy`-composite-enum `restart` field is the third and final axis).
14284 // Peer of the sibling per-`:supervisor` [`SupervisorSpec::estrategia`]
14285 // (eafb619) `Copy`-return [`RestartStrategy`] sibling-restart-strategy
14286 // scalar accessor and the M3 mesh-slot [`crate::Placement::estrategia`]
14287 // (921fe1b) `Copy`-return [`crate::PlacementStrategy`] distribution-
14288 // strategy scalar accessor — same "one typed dispatch on the substrate
14289 // primitive, `Copy`-projected closed-set enum-arm discriminator" shape
14290 // extended onto the M2 supervisor-slot per-`:children` restart-decision
14291 // axis. The pin below covers the accessor's byte-equal projection
14292 // against the raw field access across every variant in the closed
14293 // accept-set (`Permanent`, `Transient`, `Temporary`).
14294
14295 #[test]
14296 fn child_spec_restart_returns_restart_verbatim_across_permutations() {
14297 // The canonical per-`:children` restart-decision-policy-scalar
14298 // pin: [`ChildSpec::restart`] must return the `:children :restart`
14299 // field verbatim as a [`RestartPolicy`], `Copy`-projected from the
14300 // typed slot's own [`RestartPolicy`] storage across every variant
14301 // in the closed accept-set (`Permanent`, `Transient`, `Temporary`).
14302 // Pins against a future silent detour that re-derived the policy
14303 // from a peer axis (an accidental fallback to
14304 // `if is_supervisor_child { Permanent } else { Temporary }` that
14305 // collapsed the child's kind axis into the restart discriminator),
14306 // a variant remap the operator authors on one consumer without the
14307 // other, or a stale-derive detour that substituted
14308 // [`RestartPolicy::default`] when the field held any explicit
14309 // variant (which would silently collapse the distinction between
14310 // "author explicitly declared `:restart Permanent`" and "author
14311 // omitted the slot and inherited the default" the future
14312 // per-cluster restart-decision override slot depends on).
14313 //
14314 // Peer of the sibling per-`:supervisor`
14315 // `supervisor_spec_estrategia_returns_estrategia_verbatim_across_permutations`
14316 // (eafb619) pin on the M2 supervisor-slot sibling-restart-strategy
14317 // axis and the M3
14318 // `placement_estrategia_returns_estrategia_verbatim_across_permutations`
14319 // (921fe1b) pin on the per-`:placement` distribution-strategy axis
14320 // — same "the substrate-primitive accessor must byte-equal the raw
14321 // field access verbatim across every author-declared value"
14322 // discipline extended onto the M2 supervisor-slot per-`:children`
14323 // restart-decision-policy axis, closing the last unlifted axis on
14324 // the per-`:children` [`ChildSpec`] type.
14325 for restart in [
14326 RestartPolicy::Permanent,
14327 RestartPolicy::Transient,
14328 RestartPolicy::Temporary,
14329 ] {
14330 let c = ChildSpec {
14331 caixa: "worker".into(),
14332 versao: "^0.1".into(),
14333 restart,
14334 };
14335 assert_eq!(
14336 c.restart(),
14337 restart,
14338 "ChildSpec::restart must return :children :restart \
14339 verbatim (got {:?}, expected {restart:?})",
14340 c.restart(),
14341 );
14342 assert_eq!(
14343 c.restart(),
14344 c.restart,
14345 "ChildSpec::restart accessor and .restart field access \
14346 must byte-equal — the accessor is the substrate-primitive \
14347 typed dispatch every downstream per-child restart-\
14348 decision consumer must route through",
14349 );
14350 }
14351 }
14352
14353 // ── per-`:supervisor` `:estrategia` typed-accessor coherence pins ─────
14354 //
14355 // The [`SupervisorSpec::estrategia`] accessor lift extends the peer M3
14356 // [`crate::Placement::estrategia`] (921fe1b) `Copy`-return
14357 // distribution-strategy accessor discipline onto the M2 supervisor-slot
14358 // per-`:supervisor` sibling-restart-strategy `Copy`-composite-enum
14359 // scalar axis. The two pins below cover (1) the accessor's byte-equal
14360 // projection against the raw field access across every variant in the
14361 // closed accept-set, and (2) the two-consumer coherence between the
14362 // [`SupervisorSpec::validate`] partition-dispatch `match` arm and the
14363 // non-`SimpleOneForOne`-arm [`SupervisorError::NoChildren`] error
14364 // carrier's `estrategia:` field — peer of the sibling M3
14365 // `placement_estrategia_returns_estrategia_verbatim_across_permutations`
14366 // / `validate_placement_reads_through_lifted_estrategia_accessor` pin
14367 // pair on the per-`:placement` distribution-strategy axis.
14368
14369 #[test]
14370 fn supervisor_spec_estrategia_returns_estrategia_verbatim_across_permutations() {
14371 // The canonical per-`:supervisor` sibling-restart-strategy-scalar
14372 // pin: [`SupervisorSpec::estrategia`] must return the
14373 // `:supervisor :estrategia` field verbatim as a
14374 // [`RestartStrategy`], `Copy`-projected from the typed slot's own
14375 // [`RestartStrategy`] storage across every variant in the closed
14376 // accept-set (`OneForOne`, `OneForAll`, `RestForOne`,
14377 // `SimpleOneForOne`). Pins against a future silent detour that
14378 // re-derived the strategy from a peer axis (an accidental
14379 // fallback to `if children.is_empty() { SimpleOneForOne } else {
14380 // OneForOne }` collapse that read the children-count axis into
14381 // the strategy discriminator), a variant remap the operator
14382 // authors on one consumer without the other, or a stale-derive
14383 // detour that substituted [`RestartStrategy::default`] when the
14384 // field held any explicit variant (which would silently collapse
14385 // the distinction between "author explicitly declared
14386 // `:estrategia OneForOne`" and "author omitted the slot and
14387 // inherited the default" the future per-cluster strategy override
14388 // slot depends on). Peer of the sibling M3
14389 // `placement_estrategia_returns_estrategia_verbatim_across_permutations`
14390 // (921fe1b) pin on the M3 mesh-slot `Copy`-composite-enum scalar
14391 // axis — same "the substrate-primitive accessor must byte-equal
14392 // the raw field access verbatim across every author-declared
14393 // value" discipline extended onto the M2 supervisor-slot
14394 // per-`:supervisor` sibling-restart-strategy axis.
14395 for &estrategia in RestartStrategy::ALL {
14396 // `SimpleOneForOne` requires `children.is_empty()`; the peer
14397 // three strategies require a non-empty static children list.
14398 // Build each shape coherently so the pin's fixture would
14399 // itself pass [`SupervisorSpec::validate`] once fed through
14400 // the sibling coherence pin below — the byte-equal projection
14401 // asserted here is a strictly weaker property (a `Copy` field
14402 // read) that does not depend on `validate` running, but
14403 // keeping the fixture validate-clean means a future extension
14404 // of the pin to exercise `validate` end-to-end does not have
14405 // to re-author the children shape.
14406 //
14407 // Route the `SimpleOneForOne ↔ non-SimpleOneForOne` fixture-
14408 // shape partition through the [`gen_platform::IsVariant`]
14409 // derive-generated
14410 // [`RestartStrategy::is_simple_one_for_one`] predicate rather
14411 // than the raw `matches!(estrategia, RestartStrategy::
14412 // SimpleOneForOne)` open-coded pattern-match — same closed-
14413 // set-typed-enum arm-discriminator dispatch discipline the
14414 // sibling [`crate::upgrade::UpgradeInstruction::is_restart`]
14415 // convergence (915a934) extended onto its two paired positive
14416 // / negated `matches!` sites and the peer
14417 // [`crate::aplicacao::PlacementStrategy`] `IsVariant`-derived
14418 // predicate convergence (766ec63) extended onto the M3 mesh-
14419 // slot per-`:placement` distribution-strategy discriminator
14420 // axis. See the sibling `round_trip_all_strategies` and the
14421 // peer `manifest::tests::
14422 // caixa_estrategia_and_supervisor_view_reads_through_lifted_estrategia_accessor`
14423 // fixture for the two peer sites the same lift closes on.
14424 let children = if estrategia.is_simple_one_for_one() {
14425 Vec::new()
14426 } else {
14427 vec![ChildSpec {
14428 caixa: "worker".into(),
14429 versao: "^0.1".into(),
14430 restart: RestartPolicy::Permanent,
14431 }]
14432 };
14433 let s = SupervisorSpec {
14434 estrategia,
14435 children,
14436 ..SupervisorSpec::default()
14437 };
14438 assert_eq!(
14439 s.estrategia(),
14440 estrategia,
14441 "SupervisorSpec::estrategia must return :supervisor :estrategia \
14442 verbatim (got {:?}, expected {estrategia:?})",
14443 s.estrategia(),
14444 );
14445 assert_eq!(
14446 s.estrategia(),
14447 s.estrategia,
14448 "SupervisorSpec::estrategia accessor and .estrategia field \
14449 access must byte-equal — the accessor is the substrate-\
14450 primitive typed dispatch every downstream sibling-restart-\
14451 strategy consumer must route through",
14452 );
14453 }
14454 }
14455
14456 #[test]
14457 fn validate_reads_through_lifted_estrategia_accessor() {
14458 // Two-consumer coherence pin: the [`SupervisorSpec::validate`]
14459 // `SimpleOneForOne ↔ non-SimpleOneForOne` `match` partition
14460 // dispatch (which reads through [`SupervisorSpec::estrategia`]
14461 // to fan across the strategy-arm shape-gate cascades) and the
14462 // non-`SimpleOneForOne`-arm [`SupervisorError::NoChildren`]
14463 // error carrier's `estrategia:` field (which reads through
14464 // [`SupervisorSpec::estrategia`] to name the strategy the empty
14465 // `:children` list was declared against) must both key off the
14466 // lifted accessor, so any future rebrand on the typed slot's
14467 // reader shape lands at exactly one place. Pins the two-site
14468 // coherence by exercising the `NoChildren` error surface end-to-
14469 // end across every non-`SimpleOneForOne` variant and asserting
14470 // the surfaced `estrategia:` field byte-equals the accessor's
14471 // return. Peer of the sibling M3
14472 // `validate_placement_reads_through_lifted_estrategia_accessor`
14473 // (921fe1b) three-consumer coherence pin on the per-`:placement`
14474 // distribution-strategy axis.
14475 for estrategia in [
14476 RestartStrategy::OneForOne,
14477 RestartStrategy::OneForAll,
14478 RestartStrategy::RestForOne,
14479 ] {
14480 let s = SupervisorSpec {
14481 estrategia,
14482 children: Vec::new(),
14483 ..SupervisorSpec::default()
14484 };
14485 let err = s.validate().unwrap_err();
14486 match err {
14487 SupervisorError::NoChildren { estrategia: e } => {
14488 assert_eq!(
14489 e,
14490 s.estrategia(),
14491 "NoChildren.estrategia must byte-equal \
14492 SupervisorSpec::estrategia() — the empty-`:children` \
14493 refusal reads through the lifted accessor",
14494 );
14495 assert_eq!(
14496 e, estrategia,
14497 "NoChildren.estrategia must carry the author-declared \
14498 :supervisor :estrategia variant verbatim (got {e:?}, \
14499 expected {estrategia:?})",
14500 );
14501 }
14502 other => panic!("expected NoChildren, got {other:?} for estrategia={estrategia:?}"),
14503 }
14504 }
14505 }
14506
14507 // ── per-`:supervisor` `:max-restarts` typed-accessor coherence pins ────
14508 //
14509 // The [`SupervisorSpec::max_restarts`] accessor lift extends the peer M3
14510 // [`crate::CircuitBreaker::max_failures`] (3a74062) `Copy`-return
14511 // required-`u32` scalar accessor discipline onto the M2 supervisor-slot
14512 // per-`:supervisor` restart-budget-count `Copy`-`u32` scalar axis.
14513 // The two pins below cover (1) the accessor's byte-equal projection
14514 // against the raw field access across every representative value in
14515 // the `u32` accept-set (`1` lower boundary, `SUPERVISOR_MAX_RESTARTS_MAX`
14516 // upper boundary, `0` past-the-guard zero sentinel, `u32::MAX`
14517 // past-the-guard cap sentinel), and (2) the [`SupervisorSpec::validate`]
14518 // zero-floor / cap composition — the validate gate and the accessor
14519 // must route through the same substrate-primitive typed dispatch, so
14520 // any future silent detour that had the accessor perform a
14521 // bounds-collapsing clamp would fail here at caixa-core build time.
14522 // Peer of the sibling M3
14523 // `circuit_breaker_max_failures_returns_max_failures_u32_byte_equal_across_permutations`
14524 // (3a74062) pin on the per-`CircuitBreaker :max-failures` axis.
14525
14526 #[test]
14527 fn supervisor_spec_max_restarts_returns_max_restarts_u32_byte_equal_across_permutations() {
14528 // The canonical per-`:supervisor` restart-budget-count scalar pin:
14529 // [`SupervisorSpec::max_restarts`] must return the `:supervisor
14530 // :max-restarts` typed `u32` verbatim, `Copy`-projected from the
14531 // typed slot's own `u32` storage, byte-equal to the raw field
14532 // access across every representative value in the accept-set —
14533 // `1` (the lower boundary of the `1..=SUPERVISOR_MAX_RESTARTS_MAX`
14534 // accept-set the surrounding [`SupervisorSpec::validate`] gate
14535 // carves out on the sibling `ZeroMaxRestarts` refusal),
14536 // `SUPERVISOR_MAX_RESTARTS_MAX` (the upper boundary the same gate
14537 // carves out on the sibling `MaxRestartsExceedsCap` refusal), `0`
14538 // (a past-the-guard sentinel that pins the accessor doesn't
14539 // perform a silent bounds-collapse into `1` on the zero arm —
14540 // validate rejects zero but the accessor must ship the raw slot
14541 // verbatim so a validate-time gate regression surfaces at the
14542 // emit boundary rather than being silently absorbed), `u32::MAX`
14543 // (a past-the-guard sentinel that pins the accessor doesn't
14544 // perform a silent bounds-collapse through
14545 // `SUPERVISOR_MAX_RESTARTS_MAX` at the return path).
14546 //
14547 // Peer of the sibling M3
14548 // `circuit_breaker_max_failures_returns_max_failures_u32_byte_equal_across_permutations`
14549 // (3a74062) pin on the M3 mesh-slot `Copy`-`u32` sub-struct
14550 // required-scalar axis — same "the substrate-primitive accessor
14551 // must byte-equal the raw field access verbatim across every
14552 // value in the `u32` accept-set" discipline extended onto the M2
14553 // supervisor-slot per-`:supervisor` restart-budget-count axis.
14554 for max_restarts in [1u32, SUPERVISOR_MAX_RESTARTS_MAX, 0, u32::MAX] {
14555 let s = SupervisorSpec {
14556 max_restarts,
14557 ..SupervisorSpec::default()
14558 };
14559 assert_eq!(
14560 s.max_restarts(),
14561 max_restarts,
14562 "SupervisorSpec::max_restarts must return :supervisor \
14563 :max-restarts verbatim (got {}, expected {max_restarts})",
14564 s.max_restarts(),
14565 );
14566 assert_eq!(
14567 s.max_restarts(),
14568 s.max_restarts,
14569 "SupervisorSpec::max_restarts accessor and .max_restarts \
14570 field access must byte-equal — the accessor is the \
14571 substrate-primitive typed dispatch every downstream \
14572 restart-budget-count consumer must route through",
14573 );
14574 }
14575 }
14576
14577 #[test]
14578 fn validate_max_restarts_zero_floor_and_cap_arms_route_through_accessor() {
14579 // Composition pin: [`SupervisorSpec::validate`]'s `:max-restarts`
14580 // zero-floor + upper-cap bracket must key off
14581 // [`SupervisorSpec::max_restarts`], not the raw `.max_restarts`
14582 // field access. Structurally: a `SupervisorSpec { max_restarts:
14583 // 0, .. }` must surface the `ZeroMaxRestarts` refusal exactly, a
14584 // `SupervisorSpec { max_restarts: SUPERVISOR_MAX_RESTARTS_MAX + 1,
14585 // .. }` must surface the `MaxRestartsExceedsCap` refusal exactly
14586 // (with the offending count carried verbatim from the accessor
14587 // return), and a `SupervisorSpec { max_restarts: 1, .. }` (the
14588 // lower boundary of the accept-set) plus a `SupervisorSpec {
14589 // max_restarts: SUPERVISOR_MAX_RESTARTS_MAX, .. }` (the upper
14590 // boundary) must pass validate. The four together jointly pin the
14591 // accessor + validate-gate composition: any future silent detour
14592 // that had the accessor return a fresh `1` on the zero arm (a
14593 // `.max_restarts().max(1)` collapse) would silently absorb the
14594 // `ZeroMaxRestarts` refusal at the accessor boundary and the
14595 // validate gate would accept a struct-literal `SupervisorSpec {
14596 // max_restarts: 0, .. }` — the composition pin catches that at
14597 // caixa-core build time.
14598 //
14599 // Peer of the sibling M3
14600 // `validate_politicas_max_failures_zero_floor_arm_routes_through_accessor`
14601 // (3a74062) pin on the sibling per-`CircuitBreaker :max-failures`
14602 // composition axis — same "the validate / shape-gate predicate
14603 // must route through the substrate-primitive typed dispatch"
14604 // discipline extended onto the peer M2 supervisor-slot
14605 // required-`u32` composition axis.
14606 let child = ChildSpec {
14607 caixa: "worker".into(),
14608 versao: "^0.1".into(),
14609 restart: RestartPolicy::Permanent,
14610 };
14611 // Zero-floor arm.
14612 let s = SupervisorSpec {
14613 max_restarts: 0,
14614 children: vec![child.clone()],
14615 ..SupervisorSpec::default()
14616 };
14617 assert_eq!(
14618 s.validate().unwrap_err(),
14619 SupervisorError::ZeroMaxRestarts,
14620 "validate must reject max_restarts == 0 with ZeroMaxRestarts \
14621 — the accessor and the validate gate must route through the \
14622 same substrate-primitive typed dispatch on the zero-floor arm",
14623 );
14624 // Cap arm — the surfaced `max_restarts:` field must byte-equal
14625 // the accessor's return so a future rebrand on the accessor
14626 // lands in the diagnostic without a coordinated rewrite.
14627 let over_cap = SUPERVISOR_MAX_RESTARTS_MAX + 1;
14628 let s = SupervisorSpec {
14629 max_restarts: over_cap,
14630 children: vec![child.clone()],
14631 ..SupervisorSpec::default()
14632 };
14633 match s.validate().unwrap_err() {
14634 SupervisorError::MaxRestartsExceedsCap { max_restarts } => {
14635 assert_eq!(
14636 max_restarts,
14637 s.max_restarts(),
14638 "MaxRestartsExceedsCap.max_restarts must byte-equal \
14639 SupervisorSpec::max_restarts() — the cap-arm refusal \
14640 reads through the lifted accessor",
14641 );
14642 assert_eq!(
14643 max_restarts, over_cap,
14644 "MaxRestartsExceedsCap.max_restarts must carry the \
14645 author-declared :supervisor :max-restarts value \
14646 verbatim (got {max_restarts}, expected {over_cap})",
14647 );
14648 }
14649 other => panic!("expected MaxRestartsExceedsCap, got {other:?}"),
14650 }
14651 // Lower + upper accept-set boundaries.
14652 for max_restarts in [1u32, SUPERVISOR_MAX_RESTARTS_MAX] {
14653 let s = SupervisorSpec {
14654 max_restarts,
14655 children: vec![child.clone()],
14656 ..SupervisorSpec::default()
14657 };
14658 assert!(
14659 s.validate().is_ok(),
14660 "validate must accept max_restarts == {max_restarts} \
14661 (an accept-set boundary of \
14662 1..=SUPERVISOR_MAX_RESTARTS_MAX)",
14663 );
14664 }
14665 }
14666
14667 // ── per-`:supervisor` `:restart-window` typed-accessor coherence pins ─
14668 //
14669 // The [`SupervisorSpec::restart_window`] accessor lift extends the peer
14670 // M2 [`crate::LimitsSpec::wall_clock`] (8cb717b) `Option<Duration>`
14671 // accessor discipline and the peer M3 [`crate::MeshPolicy::timeout`]
14672 // (7073d0f) `Option<Duration>` accessor discipline onto the M2
14673 // supervisor-slot per-`:supervisor` restart-intensity-denominator
14674 // `Option<Duration>` scalar axis — third `Copy`-return accessor on the
14675 // M2 supervisor-slot `SupervisorSpec` type, closing the last unlifted
14676 // per-`:supervisor` scalar-value axis. The three pins below cover
14677 // (1) the accessor's byte-equal projection against the raw field
14678 // access across every representative value in the `Option<Duration>`
14679 // accept-set (`None` never-reset sentinel, `Some(Duration::from_millis(1))`
14680 // lower boundary, `Some(SUPERVISOR_RESTART_WINDOW_MAX)` upper boundary,
14681 // `Some(Duration::ZERO)` past-the-guard zero sentinel, `Some(Duration::MAX)`
14682 // past-the-guard above-cap sentinel), (2) the [`SupervisorSpec::validate`]
14683 // `if let Some(w) = self.restart_window() { … }` bracket-arm
14684 // composition — the validate gate and the accessor must route through
14685 // the same substrate-primitive typed dispatch, so any future silent
14686 // detour that had the accessor perform a bounds-collapsing clamp
14687 // would fail here at caixa-core build time, and (3) the accessor's
14688 // by-copy idempotence pin — the returned `Option<Duration>` must
14689 // outlive `&self` and two successive calls must return byte-equal
14690 // values. Peer of the sibling M2
14691 // `limits_wall_clock_returns_option_duration_byte_equal_across_permutations`
14692 // (8cb717b) pin on the per-`:limits :wall-clock` axis and the sibling
14693 // M3 `mesh_policy_timeout_returns_timeout_option_byte_equal_across_permutations`
14694 // (7073d0f) pin on the per-`:politicas :timeout` axis.
14695
14696 #[test]
14697 fn supervisor_spec_restart_window_returns_option_duration_byte_equal_across_permutations() {
14698 // The canonical per-`:supervisor` restart-intensity-denominator
14699 // scalar pin: [`SupervisorSpec::restart_window`] must return the
14700 // `:supervisor :restart-window` typed [`Duration`] verbatim as an
14701 // `Option<Duration>`, `Copy`-projected from the typed slot's own
14702 // `Option<Duration>` storage, byte-equal to the raw field access
14703 // across every representative value in the accept-set — `None`
14704 // (the "never reset — every restart across the supervisor's
14705 // lifetime counts against the sibling `:max-restarts` budget"
14706 // sentinel the field's own docstring names and the peer
14707 // `validate_accepts_none_restart_window` pin locks in on the
14708 // [`SupervisorSpec::validate`] entry-side),
14709 // `Some(Duration::from_millis(1))` (the structural minimum a
14710 // validated `:restart-window` may carry, the integer-millisecond
14711 // floor [`SupervisorError::RestartWindowNotCanonical`] rejects
14712 // everything sub-ms; `Duration::ZERO` is separately rejected by
14713 // [`SupervisorError::RestartWindowZero`]),
14714 // `Some(SUPERVISOR_RESTART_WINDOW_MAX)` (the upper boundary the
14715 // surrounding [`SupervisorSpec::validate`] gate carves out on the
14716 // sibling [`SupervisorError::RestartWindowExceedsCap`] refusal),
14717 // `Some(Duration::ZERO)` (a past-the-guard sentinel that pins the
14718 // accessor doesn't perform a silent bounds-collapse into `None` on
14719 // the zero-Duration arm — validate rejects zero but the accessor
14720 // must ship the raw slot verbatim so a validate-time gate
14721 // regression surfaces at the emit boundary rather than being
14722 // silently absorbed), and `Some(Duration::MAX)` (a past-the-guard
14723 // sentinel that pins the accessor doesn't perform a silent
14724 // bounds-collapse through [`SUPERVISOR_RESTART_WINDOW_MAX`] at the
14725 // return path).
14726 //
14727 // Peer of the sibling M2
14728 // `limits_wall_clock_returns_option_duration_byte_equal_across_permutations`
14729 // (8cb717b) pin on the per-`:limits :wall-clock` axis and the
14730 // sibling M3
14731 // `mesh_policy_timeout_returns_timeout_option_byte_equal_across_permutations`
14732 // (7073d0f) pin on the per-`:politicas :timeout` axis — same "the
14733 // substrate-primitive accessor must byte-equal the raw field
14734 // access verbatim across every value in the `Option<Duration>`
14735 // accept-set" discipline extended onto the M2 supervisor-slot
14736 // per-`:supervisor` `Option<Duration>` axis. Pins against a future
14737 // silent detour that re-derived the restart-window from a peer
14738 // axis (an accidental `.max_restarts.into()` collapse that read
14739 // the restart-budget-count as a duration — the two axes serve
14740 // different halves of the `MaxIntensity / Period` restart-
14741 // intensity ratio, and confusing them silently inverts the
14742 // ratio's numerator and denominator), a `None → Some(Duration::ZERO)`
14743 // "zero means never reset" collapse (the canonical
14744 // `Option<Duration>` → `Duration` collapse footgun the
14745 // [`SupervisorError::RestartWindowZero`] validate arm guards on
14746 // the peer zero-floor axis; a zero period either trips on the
14747 // first failure or never trips depending on operator
14748 // interpretation, neither of which is the author's "never reset"
14749 // intent that `None` expresses structurally), or a per-arm
14750 // variant swap that landed on one consumer without the other.
14751 for restart_window in [
14752 None,
14753 Some(Duration::from_millis(1)),
14754 Some(SUPERVISOR_RESTART_WINDOW_MAX),
14755 Some(Duration::ZERO),
14756 Some(Duration::MAX),
14757 ] {
14758 let s = SupervisorSpec {
14759 restart_window,
14760 ..SupervisorSpec::default()
14761 };
14762 assert_eq!(
14763 s.restart_window(),
14764 restart_window,
14765 "SupervisorSpec::restart_window must return :supervisor \
14766 :restart-window verbatim (got {:?}, expected {restart_window:?})",
14767 s.restart_window(),
14768 );
14769 assert_eq!(
14770 s.restart_window(),
14771 s.restart_window,
14772 "SupervisorSpec::restart_window accessor and \
14773 .restart_window field access must byte-equal — the \
14774 accessor is the substrate-primitive typed dispatch every \
14775 downstream restart-intensity-denominator consumer must \
14776 route through",
14777 );
14778 }
14779 }
14780
14781 #[test]
14782 fn validate_restart_window_bracket_arm_routes_through_accessor() {
14783 // Composition pin: [`SupervisorSpec::validate`]'s
14784 // `:restart-window` `if let Some(w) = self.restart_window() { … }`
14785 // zero-floor + integer-millisecond canonical-form + upper-cap
14786 // bracket-arm must key off [`SupervisorSpec::restart_window`], not
14787 // the raw `.restart_window` field access. Structurally: a
14788 // `SupervisorSpec { restart_window: None, .. }` must pass the
14789 // arm gate structurally (the `if let Some(_)` shape returns
14790 // early on the `None` arm — the accessor and the validate gate
14791 // must agree on `None → skip the bracket cascade` so an authored
14792 // `:restart-window ()` structurally routes through the "never
14793 // reset" sentinel path), a `SupervisorSpec { restart_window:
14794 // Some(Duration::ZERO), .. }` must surface the `RestartWindowZero`
14795 // refusal exactly, a `SupervisorSpec { restart_window:
14796 // Some(Duration::from_micros(1500)), .. }` must surface the
14797 // `RestartWindowNotCanonical` refusal exactly (with the offending
14798 // duration carried verbatim from the accessor return), a
14799 // `SupervisorSpec { restart_window: Some(SUPERVISOR_RESTART_WINDOW_MAX
14800 // + Duration::from_millis(1)), .. }` must surface the
14801 // `RestartWindowExceedsCap` refusal exactly (with the offending
14802 // duration carried verbatim from the accessor return), and a
14803 // `SupervisorSpec { restart_window: Some(Duration::from_millis(1)),
14804 // .. }` (the lower boundary of the accept-set) plus a
14805 // `SupervisorSpec { restart_window: Some(SUPERVISOR_RESTART_WINDOW_MAX),
14806 // .. }` (the upper boundary) must pass validate. The six together
14807 // jointly pin the accessor + validate-gate composition: any future
14808 // silent detour that had the accessor return a fresh `None` on any
14809 // `Some` arm (a `.restart_window().filter(|w| !w.is_zero())`
14810 // collapse) would silently absorb the `RestartWindowZero` refusal
14811 // at the accessor boundary and the validate gate would accept a
14812 // struct-literal `SupervisorSpec { restart_window:
14813 // Some(Duration::ZERO), .. }` — the composition pin catches that
14814 // at caixa-core build time.
14815 //
14816 // Peer of the sibling M2 [`crate::LimitsSpec::wall_clock`]
14817 // (8cb717b) validate-arm-route pin on the per-`:limits :wall-clock`
14818 // axis and the peer M3 [`crate::MeshPolicy::timeout`] (7073d0f)
14819 // accessor-composition pin on the per-`:politicas :timeout` axis —
14820 // same "the validate / shape-gate predicate must route through
14821 // the substrate-primitive typed dispatch" discipline extended
14822 // onto the peer M2 supervisor-slot optional-`Duration` axis.
14823 let child = ChildSpec {
14824 caixa: "worker".into(),
14825 versao: "^0.1".into(),
14826 restart: RestartPolicy::Permanent,
14827 };
14828 // None arm — must not surface any :restart-window-shaped refusal;
14829 // the `if let Some(_)` bracket returns early on `None` structurally.
14830 let s = SupervisorSpec {
14831 restart_window: None,
14832 children: vec![child.clone()],
14833 ..SupervisorSpec::default()
14834 };
14835 assert!(
14836 s.validate().is_ok(),
14837 "validate must accept restart_window: None (the never-reset \
14838 sentinel) — the `if let Some(_)` bracket returns early on \
14839 the None arm and the accessor must agree",
14840 );
14841 // Zero-floor arm.
14842 let s = SupervisorSpec {
14843 restart_window: Some(Duration::ZERO),
14844 children: vec![child.clone()],
14845 ..SupervisorSpec::default()
14846 };
14847 assert_eq!(
14848 s.validate().unwrap_err(),
14849 SupervisorError::RestartWindowZero,
14850 "validate must reject restart_window == Some(Duration::ZERO) \
14851 with RestartWindowZero — the accessor and the validate gate \
14852 must route through the same substrate-primitive typed \
14853 dispatch on the zero-floor arm",
14854 );
14855 // Non-canonical (sub-ms) arm — the surfaced `window:` field must
14856 // byte-equal the accessor's return so a future rebrand on the
14857 // accessor lands in the diagnostic without a coordinated rewrite.
14858 let sub_ms = Duration::from_micros(1500);
14859 let s = SupervisorSpec {
14860 restart_window: Some(sub_ms),
14861 children: vec![child.clone()],
14862 ..SupervisorSpec::default()
14863 };
14864 match s.validate().unwrap_err() {
14865 SupervisorError::RestartWindowNotCanonical { window } => {
14866 assert_eq!(
14867 Some(window),
14868 s.restart_window(),
14869 "RestartWindowNotCanonical.window must byte-equal \
14870 SupervisorSpec::restart_window().unwrap() — the \
14871 non-canonical-arm refusal reads through the lifted \
14872 accessor",
14873 );
14874 assert_eq!(
14875 window, sub_ms,
14876 "RestartWindowNotCanonical.window must carry the \
14877 author-declared :supervisor :restart-window value \
14878 verbatim (got {window:?}, expected {sub_ms:?})",
14879 );
14880 }
14881 other => panic!("expected RestartWindowNotCanonical, got {other:?}"),
14882 }
14883 // Cap arm — the surfaced `window:` field must byte-equal the
14884 // accessor's return.
14885 let over_cap = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_millis(1);
14886 let s = SupervisorSpec {
14887 restart_window: Some(over_cap),
14888 children: vec![child.clone()],
14889 ..SupervisorSpec::default()
14890 };
14891 match s.validate().unwrap_err() {
14892 SupervisorError::RestartWindowExceedsCap { window } => {
14893 assert_eq!(
14894 Some(window),
14895 s.restart_window(),
14896 "RestartWindowExceedsCap.window must byte-equal \
14897 SupervisorSpec::restart_window().unwrap() — the \
14898 cap-arm refusal reads through the lifted accessor",
14899 );
14900 assert_eq!(
14901 window, over_cap,
14902 "RestartWindowExceedsCap.window must carry the \
14903 author-declared :supervisor :restart-window value \
14904 verbatim (got {window:?}, expected {over_cap:?})",
14905 );
14906 }
14907 other => panic!("expected RestartWindowExceedsCap, got {other:?}"),
14908 }
14909 // Lower + upper accept-set boundaries.
14910 for restart_window in [Duration::from_millis(1), SUPERVISOR_RESTART_WINDOW_MAX] {
14911 let s = SupervisorSpec {
14912 restart_window: Some(restart_window),
14913 children: vec![child.clone()],
14914 ..SupervisorSpec::default()
14915 };
14916 assert!(
14917 s.validate().is_ok(),
14918 "validate must accept restart_window == Some({restart_window:?}) \
14919 (an accept-set boundary of \
14920 1ms..=SUPERVISOR_RESTART_WINDOW_MAX)",
14921 );
14922 }
14923 }
14924
14925 #[test]
14926 fn supervisor_spec_restart_window_projects_option_duration_by_copy() {
14927 // The by-copy pin: [`SupervisorSpec::restart_window`] returns
14928 // `Option<Duration>` by copy — `Duration` is `Copy` (so
14929 // `Option<Duration>` is `Copy`) and the accessor must return by
14930 // value, not by reference. Peer of the sibling M2
14931 // [`crate::LimitsSpec::wall_clock`] (8cb717b) by-copy pin on the
14932 // per-`:limits :wall-clock` axis and the sibling M3
14933 // [`crate::MeshPolicy::timeout`] (7073d0f) by-copy pin on the
14934 // per-`:politicas :timeout` axis, extended onto the peer M2
14935 // supervisor-slot `Option<Duration>` copy-invariant shape — the
14936 // accessor's returned `Option<Duration>` must outlive `&self`
14937 // (multiple calls must return equal values from a dropped-`&self`
14938 // copy, since the returned Option carries no borrow), and calling
14939 // the accessor twice on the same SupervisorSpec must yield the
14940 // same `Option<Duration>` verbatim (idempotent, no side effects
14941 // on `&self`).
14942 //
14943 // Pins against a future silent detour that returned
14944 // `Option<&Duration>` (which would type-check but silently break
14945 // every downstream caller — the future wasm-operator's
14946 // per-supervisor restart-intensity counter consumes `Duration` by
14947 // value and `&Duration` would fold to a detached copy at the call
14948 // site), an accidental `Option::as_ref()` projection
14949 // (`self.restart_window.as_ref()` would also type-check but
14950 // return `Option<&Duration>`), or a one-arm-only accessor that
14951 // reads `Some(*w)` in the Some arm but reads a fresh
14952 // `Default::default()` (which would collapse to `Duration::ZERO`,
14953 // not `None`) in the None arm — a footgun the
14954 // [`SupervisorError::RestartWindowZero`] validate arm explicitly
14955 // closes since Erlang/OTP's `MaxIntensity / Period` invariant
14956 // requires `Period > 0` and `None` structurally expresses "never
14957 // reset" instead.
14958 for restart_window in [
14959 None,
14960 Some(Duration::from_millis(1)),
14961 Some(Duration::from_secs(60)),
14962 Some(SUPERVISOR_RESTART_WINDOW_MAX),
14963 ] {
14964 let s = SupervisorSpec {
14965 restart_window,
14966 ..SupervisorSpec::default()
14967 };
14968 let first = s.restart_window();
14969 let second = s.restart_window();
14970 assert_eq!(
14971 first, second,
14972 "SupervisorSpec::restart_window must be idempotent — two \
14973 successive calls on the same &self must return the \
14974 same Option<Duration>",
14975 );
14976 assert_eq!(
14977 first, restart_window,
14978 "SupervisorSpec::restart_window must return :supervisor \
14979 :restart-window verbatim by copy — got {first:?}, \
14980 expected {restart_window:?}",
14981 );
14982 }
14983 }
14984
14985 // ── per-`:supervisor` `:children` typed-accessor coherence pins ─────────
14986 //
14987 // The [`SupervisorSpec::children`] accessor lift is the seed of the
14988 // slice-return (`&[T]`) accessor discipline on the substrate — the four
14989 // peer `Vec`-carry axes ([`crate::Placement::clusters`],
14990 // [`crate::AplicacaoSpec::membros`], [`crate::AplicacaoSpec::contratos`],
14991 // [`crate::UpgradeFromEntry::instructions`]) still key off the raw field
14992 // access at the time of this seed, and inherit this pin family's
14993 // discipline as future compounding runs migrate their consumers. The
14994 // three pins below cover (1) the accessor's byte-equal projection
14995 // against the raw field access across the empty / singleton / cohort
14996 // fixtures the [`SupervisorSpec::validate`] partition-dispatch fans
14997 // between, (2) the [`SupervisorSpec::validate`] `SimpleOneForOne ↔
14998 // non-SimpleOneForOne` partition dispatch's paired `.is_empty()`
14999 // consumer routing through the accessor on both arms, and (3) the
15000 // per-child validate loop's traversal reading the same slice-view the
15001 // accessor projects. Peer of the sibling M2
15002 // [`validate_reads_through_lifted_estrategia_accessor`] (eafb619)
15003 // two-consumer coherence pin on the per-`:supervisor`
15004 // sibling-restart-strategy `Copy`-composite-enum scalar axis, extended
15005 // onto the per-`:supervisor` static-child-list `Vec`-carry axis.
15006
15007 #[test]
15008 fn supervisor_spec_children_returns_children_slice_byte_equal_across_permutations() {
15009 // The canonical per-`:supervisor` static-child-list scalar-shape
15010 // pin: [`SupervisorSpec::children`] must return the `:supervisor
15011 // :children` typed `Vec<ChildSpec>` verbatim as a `&[ChildSpec]`
15012 // slice-view over the same backing buffer the raw
15013 // `self.children.as_slice()` field access borrows from, byte-
15014 // equal across every representative fixture in the accept-set —
15015 // the empty slice (the `SimpleOneForOne`-arm sentinel),
15016 // the singleton slice (the minimal non-`SimpleOneForOne` shape),
15017 // and a two-child cohort (a peer non-`SimpleOneForOne` shape
15018 // with the peer three restart-policy variants in play).
15019 //
15020 // Pins against a future silent detour that returned
15021 // `&Vec<ChildSpec>` (which would type-check but leak the
15022 // storage-side `Vec`'s grow/push/reserve surface no consumer of
15023 // the typed view reaches for), a fresh-allocated
15024 // `Vec<ChildSpec>` copy (which would type-check via a coercion
15025 // but silently break every downstream caller that relied on the
15026 // slice sharing the backing buffer's identity), or an
15027 // out-of-order or length-drifted projection (which would silently
15028 // split the per-child validate loop's traversal input from the
15029 // paired partition-dispatch `.is_empty()` probe's input).
15030 //
15031 // Peer of the sibling
15032 // `supervisor_spec_estrategia_returns_estrategia_verbatim_across_permutations`
15033 // (eafb619) `Copy`-composite-enum byte-equal pin on the
15034 // per-`:supervisor` sibling-restart-strategy axis, extended onto
15035 // the per-`:supervisor` static-child-list `Vec`-carry axis.
15036 let fixtures: Vec<Vec<ChildSpec>> = vec![
15037 Vec::new(),
15038 vec![child("worker", "^0.1", RestartPolicy::Permanent)],
15039 vec![
15040 child("worker", "^0.1", RestartPolicy::Permanent),
15041 child("cache-server", "^0.1", RestartPolicy::Transient),
15042 ],
15043 vec![
15044 child("worker", "^0.1", RestartPolicy::Permanent),
15045 child("cache-server", "^0.1", RestartPolicy::Transient),
15046 child("scratch-job", "^0.1", RestartPolicy::Temporary),
15047 ],
15048 ];
15049 for children in fixtures {
15050 let s = SupervisorSpec {
15051 children: children.clone(),
15052 ..SupervisorSpec::default()
15053 };
15054 assert_eq!(
15055 s.children(),
15056 children.as_slice(),
15057 "SupervisorSpec::children must return :supervisor \
15058 :children verbatim (got {:?}, expected {:?})",
15059 s.children(),
15060 children.as_slice(),
15061 );
15062 assert_eq!(
15063 s.children(),
15064 s.children.as_slice(),
15065 "SupervisorSpec::children accessor and \
15066 .children.as_slice() field access must byte-equal — \
15067 the accessor is the substrate-primitive typed \
15068 dispatch every downstream static-child-list consumer \
15069 must route through",
15070 );
15071 assert_eq!(
15072 s.children().len(),
15073 s.children.len(),
15074 "SupervisorSpec::children().len() must byte-equal \
15075 self.children.len() — a length-drift would silently \
15076 split the paired partition-dispatch `.is_empty()` \
15077 probe input from the per-child validate loop's \
15078 traversal input",
15079 );
15080 }
15081 }
15082
15083 #[test]
15084 fn validate_reads_through_lifted_children_accessor() {
15085 // Three-consumer coherence pin: the [`SupervisorSpec::validate`]
15086 // `SimpleOneForOne`-arm `!self.children().is_empty()` refusal
15087 // probe (which must trip [`SupervisorError::SimpleOneForOneWithStaticChildren`]
15088 // when the accessor projects a non-empty slice under a
15089 // `SimpleOneForOne` estrategia), the peer non-`SimpleOneForOne`-arm
15090 // `self.children().is_empty()` refusal probe (which must trip
15091 // [`SupervisorError::NoChildren`] when the accessor projects the
15092 // empty slice under any peer estrategia), and the per-child
15093 // validate loop's `for child in self.children()` traversal
15094 // (which must reach every entry in the same order the accessor
15095 // projects) must all key off the lifted accessor, so any future
15096 // rebrand on the typed slot's reader shape lands at exactly one
15097 // place. Pins the three-site coherence by exercising each
15098 // production consumer end-to-end: (1) the
15099 // `SimpleOneForOneWithStaticChildren` refusal under a non-empty
15100 // slice + `SimpleOneForOne` estrategia, (2) the `NoChildren`
15101 // refusal under the empty slice + non-`SimpleOneForOne`
15102 // estrategia across every peer variant, and (3) the per-child
15103 // duplicate-detection surface fires on the second entry of a
15104 // two-child cohort that shares a `:caixa` name (which requires
15105 // the loop to reach both entries — a first-entry-only projection
15106 // would silently pass since the dedup HashSet has room for the
15107 // first insert).
15108 //
15109 // Peer of the sibling M2
15110 // [`validate_reads_through_lifted_estrategia_accessor`] (eafb619)
15111 // two-consumer coherence pin on the per-`:supervisor`
15112 // sibling-restart-strategy axis, extended onto the
15113 // per-`:supervisor` static-child-list `Vec`-carry axis.
15114
15115 // (1) `SimpleOneForOne`-arm probe: a non-empty slice under a
15116 // `SimpleOneForOne` estrategia must trip
15117 // `SimpleOneForOneWithStaticChildren`.
15118 let s = SupervisorSpec {
15119 estrategia: RestartStrategy::SimpleOneForOne,
15120 children: vec![child("worker", "^0.1", RestartPolicy::Permanent)],
15121 ..SupervisorSpec::default()
15122 };
15123 assert_eq!(
15124 s.validate().unwrap_err(),
15125 SupervisorError::SimpleOneForOneWithStaticChildren,
15126 "SimpleOneForOne + non-empty children must trip \
15127 SimpleOneForOneWithStaticChildren — the accessor projects \
15128 a non-empty slice, and the SimpleOneForOne-arm refusal \
15129 probe reads through the lifted accessor",
15130 );
15131 assert!(
15132 !s.children().is_empty(),
15133 "the SimpleOneForOne-arm refusal input must be a non-empty \
15134 slice per the accessor's projection",
15135 );
15136
15137 // (2) Peer non-`SimpleOneForOne`-arm probe: the empty slice
15138 // under any peer estrategia must trip `NoChildren`.
15139 for estrategia in [
15140 RestartStrategy::OneForOne,
15141 RestartStrategy::OneForAll,
15142 RestartStrategy::RestForOne,
15143 ] {
15144 let s = SupervisorSpec {
15145 estrategia,
15146 children: Vec::new(),
15147 ..SupervisorSpec::default()
15148 };
15149 match s.validate().unwrap_err() {
15150 SupervisorError::NoChildren { estrategia: e } => {
15151 assert_eq!(
15152 e, estrategia,
15153 "NoChildren.estrategia must carry the author-\
15154 declared :supervisor :estrategia variant \
15155 verbatim (got {e:?}, expected {estrategia:?})",
15156 );
15157 }
15158 other => panic!(
15159 "expected NoChildren, got {other:?} for \
15160 estrategia={estrategia:?}"
15161 ),
15162 }
15163 assert!(
15164 s.children().is_empty(),
15165 "the non-SimpleOneForOne-arm refusal input must be the \
15166 empty slice per the accessor's projection",
15167 );
15168 }
15169
15170 // (3) Per-child validate loop: a two-child cohort that shares a
15171 // `:caixa` name must trip `DuplicateChildCaixa` — the loop must
15172 // reach both entries through the accessor.
15173 let s = SupervisorSpec {
15174 estrategia: RestartStrategy::OneForOne,
15175 children: vec![
15176 child("worker", "^0.1", RestartPolicy::Permanent),
15177 child("worker", "^0.2", RestartPolicy::Transient),
15178 ],
15179 ..SupervisorSpec::default()
15180 };
15181 match s.validate().unwrap_err() {
15182 SupervisorError::DuplicateChildCaixa { caixa } => {
15183 assert_eq!(
15184 caixa, "worker",
15185 "DuplicateChildCaixa.caixa must carry the shared \
15186 child `:caixa` name verbatim",
15187 );
15188 }
15189 other => panic!("expected DuplicateChildCaixa, got {other:?}"),
15190 }
15191 assert_eq!(
15192 s.children().len(),
15193 2,
15194 "the per-child validate loop's traversal input must be a \
15195 two-element slice per the accessor's projection",
15196 );
15197 }
15198
15199 // Shared helper for the M2 per-`:children` per-slot-gate ≡
15200 // `validate` equivalence pins: builds an `OneForOne`-estrategia
15201 // one-cohort spec whose peer `:estrategia`↔`:children.is_empty()`
15202 // partition, `:max-restarts` zero-floor/cap, and `:restart-window`
15203 // bracket all pass cleanly so the sole failing surface is the
15204 // per-child cascade [`SupervisorSpec::validate_children`] owns, and
15205 // pins the two-altitude equivalence on the paired probe.
15206 fn assert_validate_children_matches_gate(children: Vec<ChildSpec>, expected: &SupervisorError) {
15207 let s = SupervisorSpec {
15208 estrategia: RestartStrategy::OneForOne,
15209 children,
15210 ..SupervisorSpec::default()
15211 };
15212 let via_gate = s.validate_children().unwrap_err();
15213 let via_validate = s.validate().unwrap_err();
15214 assert_eq!(&via_gate, expected, "validate_children direct dispatch",);
15215 assert_eq!(&via_validate, expected, "validate() end-to-end dispatch",);
15216 assert_eq!(
15217 via_gate, via_validate,
15218 "per-slot gate ≡ validate() must discriminate the same \
15219 refusal shape",
15220 );
15221 }
15222
15223 #[test]
15224 fn validate_children_matches_gate_on_per_axis_refusal_shapes() {
15225 // Fail-before-pass-after equivalence pin on the M2
15226 // per-`:children` per-slot gate ≡ [`SupervisorSpec::validate`]
15227 // convergence — sibling of the M3 mesh-slot
15228 // `validate_membros_*` / `validate_contratos_*` /
15229 // `validate_entrada_*` per-slot-gate ≡ `validate` pins on the
15230 // peer per-entry axes. Sweeps four of the five refusal shapes
15231 // the per-slot gate owns: (1) `EmptyChildName` on an empty-
15232 // `:caixa` child, (2) `ChildCaixaInvalid` on a structurally
15233 // invalid `:caixa` DNS-1123 label, (3) `EmptyChildVersion` on
15234 // an empty-`:versao` child, (4) `DuplicateChildCaixa` on a
15235 // duplicate-`:caixa` fan-out. Companion pin
15236 // `validate_children_matches_gate_on_versao_invalid_and_clean_pass`
15237 // covers `ChildVersaoInvalid` (whose parser-owned reason string
15238 // needs pattern-matching, not equality) and the clean-pass
15239 // canonical fixture; together the two pins guarantee the
15240 // per-slot gate and `validate` discriminate the same set on
15241 // every per-child-covered input.
15242 assert_validate_children_matches_gate(
15243 vec![child("", "^0.1", RestartPolicy::Permanent)],
15244 &SupervisorError::EmptyChildName,
15245 );
15246 assert_validate_children_matches_gate(
15247 vec![child("Worker", "^0.1", RestartPolicy::Permanent)],
15248 &SupervisorError::ChildCaixaInvalid {
15249 caixa: "Worker".into(),
15250 reason: "contains uppercase character 'W' (K8s DNS-1123 label names are lowercase-only; use \"worker\")".into(),
15251 },
15252 );
15253 assert_validate_children_matches_gate(
15254 vec![child("worker", "", RestartPolicy::Permanent)],
15255 &SupervisorError::EmptyChildVersion {
15256 caixa: "worker".into(),
15257 },
15258 );
15259 assert_validate_children_matches_gate(
15260 vec![
15261 child("worker", "^0.1", RestartPolicy::Permanent),
15262 child("worker", "^0.2", RestartPolicy::Transient),
15263 ],
15264 &SupervisorError::DuplicateChildCaixa {
15265 caixa: "worker".into(),
15266 },
15267 );
15268 }
15269
15270 #[test]
15271 fn validate_children_matches_gate_on_versao_invalid_and_clean_pass() {
15272 // Second half of the two-altitude equivalence pin — covers the
15273 // one refusal shape whose reason string is parser-owned
15274 // (`ChildVersaoInvalid`, whose reason comes from the shared
15275 // [`crate::version::parse_requirement`] impl and may drift) and
15276 // the clean-pass canonical fixture. Sibling pin
15277 // `validate_children_matches_gate_on_per_axis_refusal_shapes`
15278 // covers the four equality-comparable refusal shapes.
15279 let s_bad_versao = SupervisorSpec {
15280 estrategia: RestartStrategy::OneForOne,
15281 children: vec![child("worker", "not-a-req", RestartPolicy::Permanent)],
15282 ..SupervisorSpec::default()
15283 };
15284 let via_gate = s_bad_versao.validate_children().unwrap_err();
15285 let via_validate = s_bad_versao.validate().unwrap_err();
15286 match (&via_gate, &via_validate) {
15287 (
15288 SupervisorError::ChildVersaoInvalid {
15289 caixa: cg,
15290 versao: vg,
15291 ..
15292 },
15293 SupervisorError::ChildVersaoInvalid {
15294 caixa: cv,
15295 versao: vv,
15296 ..
15297 },
15298 ) => {
15299 assert_eq!(cg, "worker", "per-slot gate :caixa carrier");
15300 assert_eq!(vg, "not-a-req", "per-slot gate :versao carrier");
15301 assert_eq!(cv, "worker", "validate() :caixa carrier");
15302 assert_eq!(vv, "not-a-req", "validate() :versao carrier");
15303 }
15304 other => panic!("expected ChildVersaoInvalid on both altitudes, got {other:?}"),
15305 }
15306 assert_eq!(
15307 via_gate, via_validate,
15308 "per-slot gate ≡ validate() on ChildVersaoInvalid full envelope",
15309 );
15310
15311 let s_ok = SupervisorSpec {
15312 estrategia: RestartStrategy::OneForOne,
15313 children: vec![
15314 child("worker-a", "^0.1", RestartPolicy::Permanent),
15315 child("worker-b", "~0.2.3", RestartPolicy::Transient),
15316 child("collector", "*", RestartPolicy::Temporary),
15317 ],
15318 ..SupervisorSpec::default()
15319 };
15320 s_ok.validate_children()
15321 .expect("per-slot gate must accept the clean-pass fixture");
15322 s_ok.validate()
15323 .expect("validate() must accept the clean-pass fixture");
15324 }
15325
15326 #[test]
15327 fn validate_children_is_self_contained_on_children_slot() {
15328 // Self-containment pin: [`SupervisorSpec::validate_children`]
15329 // resolves the per-child cascade against `&self` alone, without
15330 // depending on the peer `:estrategia`/`:max-restarts`/
15331 // `:restart-window` gates having run first — same posture the M3
15332 // peer per-slot gates carry (`validate_membros`,
15333 // `validate_contratos`, `validate_entrada`, `validate_placement`,
15334 // routing through their own oracles rather than borrowing state
15335 // threaded down from `validate`). A future consumer that reaches
15336 // the per-slot gate directly on a spec whose peer slots would
15337 // fail `validate` still surfaces the per-child refusal, not the
15338 // peer refusal.
15339 //
15340 // Construct a spec whose `:max-restarts` is `0` (which would
15341 // trip [`SupervisorError::ZeroMaxRestarts`] at `validate` after
15342 // the partition-dispatch) and whose `:children` carries a
15343 // `DuplicateChildCaixa` shape: the per-slot gate called directly
15344 // must surface `DuplicateChildCaixa`, proving it does not depend
15345 // on the peer `:max-restarts` gate running first.
15346 let s = SupervisorSpec {
15347 estrategia: RestartStrategy::OneForOne,
15348 max_restarts: 0,
15349 restart_window: Some(Duration::from_secs(60)),
15350 children: vec![
15351 child("worker", "^0.1", RestartPolicy::Permanent),
15352 child("worker", "^0.2", RestartPolicy::Transient),
15353 ],
15354 };
15355 assert_eq!(
15356 s.validate_children().unwrap_err(),
15357 SupervisorError::DuplicateChildCaixa {
15358 caixa: "worker".into(),
15359 },
15360 "per-slot gate must resolve per-child refusal directly against \
15361 `&self` — a dependency on the peer `:max-restarts` gate \
15362 running first would surface ZeroMaxRestarts here instead",
15363 );
15364 // The peer gate is still the surface `validate` reaches — pin
15365 // the ordering to establish that `validate_children` truly runs
15366 // last in `validate`'s dispatch, so a direct call bypasses the
15367 // peer gates on any spec whose per-child cascade would fail.
15368 assert_eq!(
15369 s.validate().unwrap_err(),
15370 SupervisorError::ZeroMaxRestarts,
15371 "validate() must surface the peer `:max-restarts` gate before \
15372 reaching the per-child cascade — this pins the dispatch \
15373 ordering the per-slot gate's self-containment complements",
15374 );
15375 }
15376
15377 #[test]
15378 fn child_spec_restart_accessor_is_const_fn() {
15379 // The [`ChildSpec::restart`] per-`:children` restart-decision-
15380 // policy `Copy`-return scalar accessor is declared
15381 // `#[must_use] pub const fn` — matching the sibling M2
15382 // per-`:supervisor` [`SupervisorSpec::estrategia`] (pinned by
15383 // [`supervisor_spec_estrategia_accessor_is_const_fn`] below,
15384 // both converted in this commit), the sibling M2
15385 // per-`:supervisor` [`SupervisorSpec::max_restarts`] (b698ec0)
15386 // `Copy`-`u32` accessor already `pub const fn`, and the peer M3
15387 // mesh-slot per-`:entrada` [`crate::Entrada::port`] (bafa004) /
15388 // per-`:placement` [`crate::Placement::estrategia`] (bafa004)
15389 // `Copy`-return `pub const fn` scalar accessors on the sibling
15390 // M3 surface. Pin the `const`-eval posture here so a future
15391 // accidental downgrade to non-`const` (an added runtime helper
15392 // reachable only from a non-`const` context, an
15393 // `Option<RestartPolicy>`-shape migration on the per-child
15394 // restart-decision axis once heterogeneous per-cluster
15395 // restart-policy overlays land that would silently drop the
15396 // `const` qualifier, a manual hand-rolled shadow) trips at
15397 // caixa-core build time rather than surfacing as a downstream
15398 // `const`-context regression far from the declaration.
15399 //
15400 // Same shape as the sibling M3
15401 // [`crate::aplicacao::tests::placement_estrategia_accessor_is_const_fn`]
15402 // and [`crate::aplicacao::tests::entrada_port_accessor_is_const_fn`]
15403 // (bafa004) pins on the peer M3 mesh-slot `Copy`-return scalar
15404 // accessor axis — the load-bearing witness lives in the
15405 // module-scope `const fn` wrapper `restart_via_const_fn` below:
15406 // a body that calls [`ChildSpec::restart`] under a `const fn`
15407 // signature is well-formed only when the callee is itself
15408 // `const fn`, so any future accidental downgrade of
15409 // [`ChildSpec::restart`] to non-`const` fails at caixa-core
15410 // build time (const-eval E0015 `cannot call non-const method`),
15411 // strictly stronger than a runtime `assert!(CONST)` and
15412 // side-stepping the destructor-in-const restriction that
15413 // blocks direct `const _: RestartPolicy = FIXTURE.restart()`
15414 // items on `ChildSpec`'s `String` carriers.
15415 //
15416 // The runtime body sweeps every closed-set [`RestartPolicy`]
15417 // arm and asserts the wrapped and direct dispatches agree.
15418 const fn restart_via_const_fn(c: &ChildSpec) -> RestartPolicy {
15419 c.restart()
15420 }
15421 for restart in [
15422 RestartPolicy::Permanent,
15423 RestartPolicy::Transient,
15424 RestartPolicy::Temporary,
15425 ] {
15426 let c = ChildSpec {
15427 caixa: "worker".into(),
15428 versao: "^0.1".into(),
15429 restart,
15430 };
15431 assert_eq!(
15432 restart_via_const_fn(&c),
15433 c.restart(),
15434 "const-fn-wrapped and direct dispatch on \
15435 ChildSpec::restart must agree for {restart:?}",
15436 );
15437 assert_eq!(
15438 c.restart(),
15439 restart,
15440 "ChildSpec::restart must return the storage-side \
15441 RestartPolicy verbatim for {restart:?} (a violation \
15442 means the accessor stopped being a raw field-return \
15443 copy)",
15444 );
15445 }
15446 }
15447
15448 #[test]
15449 fn supervisor_spec_estrategia_accessor_is_const_fn() {
15450 // The [`SupervisorSpec::estrategia`] per-`:supervisor`
15451 // sibling-restart-strategy `Copy`-return scalar accessor is
15452 // declared `#[must_use] pub const fn` — matching the sibling M2
15453 // per-`:children` [`ChildSpec::restart`] (pinned by
15454 // [`child_spec_restart_accessor_is_const_fn`] above, both
15455 // converted in this commit), the sibling M2 per-`:supervisor`
15456 // [`SupervisorSpec::max_restarts`] (b698ec0) `Copy`-`u32`
15457 // accessor already `pub const fn`, and mirroring the peer M3
15458 // mesh-slot per-`:placement`
15459 // [`crate::Placement::estrategia`] (bafa004) `Copy`-return
15460 // `pub const fn` scalar accessor whose method-name discipline
15461 // the [`SupervisorSpec::estrategia`] method was authored to
15462 // match. Pin the `const`-eval posture here so a future
15463 // accidental downgrade to non-`const` (an added runtime helper
15464 // reachable only from a non-`const` context, an
15465 // `Option<RestartStrategy>`-shape migration once the substrate
15466 // grows per-cluster strategy overlays that would silently drop
15467 // the `const` qualifier, a manual hand-rolled shadow) trips at
15468 // caixa-core build time rather than surfacing as a downstream
15469 // `const`-context regression far from the declaration.
15470 //
15471 // Same shape as the sibling
15472 // [`child_spec_restart_accessor_is_const_fn`] pin above — the
15473 // load-bearing witness lives in the module-scope `const fn`
15474 // wrapper `estrategia_via_const_fn` below: a body that calls
15475 // [`SupervisorSpec::estrategia`] under a `const fn` signature
15476 // is well-formed only when the callee is itself `const fn`,
15477 // side-stepping the destructor-in-const restriction that would
15478 // otherwise block a direct
15479 // `const _: RestartStrategy = FIXTURE.estrategia()` item on
15480 // `SupervisorSpec`'s `Vec<ChildSpec>` / `Option<Duration>`
15481 // carriers.
15482 //
15483 // The runtime body sweeps every closed-set [`RestartStrategy`]
15484 // arm via [`RestartStrategy::ALL`] and asserts the wrapped and
15485 // direct dispatches agree.
15486 const fn estrategia_via_const_fn(s: &SupervisorSpec) -> RestartStrategy {
15487 s.estrategia()
15488 }
15489 for &estrategia in RestartStrategy::ALL {
15490 let s = SupervisorSpec {
15491 estrategia,
15492 max_restarts: 5,
15493 restart_window: Some(Duration::from_secs(60)),
15494 children: Vec::new(),
15495 };
15496 assert_eq!(
15497 estrategia_via_const_fn(&s),
15498 s.estrategia(),
15499 "const-fn-wrapped and direct dispatch on \
15500 SupervisorSpec::estrategia must agree for {estrategia:?}",
15501 );
15502 assert_eq!(
15503 s.estrategia(),
15504 estrategia,
15505 "SupervisorSpec::estrategia must return the storage-side \
15506 RestartStrategy verbatim for {estrategia:?} (a violation \
15507 means the accessor stopped being a raw field-return \
15508 copy)",
15509 );
15510 }
15511 }
15512
15513 // Per-variant equivalence pins for the [`supervisor_caixa_only_ctors!`]
15514 // macro definition (see the paired doc-block above the macro
15515 // definition) — every generated `<ctor>(caixa: &str) -> Self`
15516 // constructor folds the uniform `Self::<Variant> { caixa:
15517 // caixa.to_string() }` one-field struct-literal onto one substrate
15518 // primitive. The three per-variant equivalence pins below
15519 // (fail-before-pass-after by construction — a byte-mismatched macro
15520 // arm would trip its equivalence pin first) lock each generated
15521 // constructor to its struct-literal peer under `PartialEq`, so
15522 // every wire-up in [`SupervisorSpec::validate_children`] and
15523 // [`validate_no_self_supervision`] on that variant produces a
15524 // byte-equal `SupervisorError` to the pre-lift open-coded
15525 // struct-literal. The cross-axis pin that follows (non-default
15526 // caixa name) routes the sole constructor input axis through
15527 // `.to_string()`, so the fold does not silently collapse onto a
15528 // fixed name.
15529 //
15530 // Peer of the sibling `<slot>_ctor_matches_tuple_literal_wrap` /
15531 // `<slot>_violation_ctor_matches_struct_literal_wrap` /
15532 // `<slot>_slots_on_non_<owner>_ctor_matches_struct_literal_wrap` /
15533 // `missing_entry_ctor_matches_struct_literal_wrap` /
15534 // `entrada_host_invalid_ctor_matches_struct_literal_wrap` /
15535 // `contrato_wrong_target_ctor_matches_struct_literal_wrap` /
15536 // `contrato_missing_target_ctor_matches_struct_literal_wrap` /
15537 // `<variant>_ctor_matches_struct_literal_wrap` equivalence pins
15538 // on the six sibling ctor families the recent trajectory closed
15539 // on the peer `LayoutError` / `AplicacaoError` envelopes.
15540
15541 #[test]
15542 fn empty_child_version_ctor_matches_struct_literal_wrap() {
15543 assert_eq!(
15544 SupervisorError::empty_child_version("worker"),
15545 SupervisorError::EmptyChildVersion {
15546 caixa: "worker".to_string(),
15547 },
15548 "generated empty_child_version ctor must produce byte-equal \
15549 SupervisorError to the open-coded struct-literal wrap on the \
15550 same &str fixture",
15551 );
15552 }
15553
15554 #[test]
15555 fn duplicate_child_caixa_ctor_matches_struct_literal_wrap() {
15556 assert_eq!(
15557 SupervisorError::duplicate_child_caixa("worker"),
15558 SupervisorError::DuplicateChildCaixa {
15559 caixa: "worker".to_string(),
15560 },
15561 "generated duplicate_child_caixa ctor must produce byte-equal \
15562 SupervisorError to the open-coded struct-literal wrap on the \
15563 same &str fixture",
15564 );
15565 }
15566
15567 #[test]
15568 fn child_supervises_self_ctor_matches_struct_literal_wrap() {
15569 assert_eq!(
15570 SupervisorError::child_supervises_self("orquestra"),
15571 SupervisorError::ChildSupervisesSelf {
15572 caixa: "orquestra".to_string(),
15573 },
15574 "generated child_supervises_self ctor must produce byte-equal \
15575 SupervisorError to the open-coded struct-literal wrap on the \
15576 same &str fixture",
15577 );
15578 }
15579
15580 // Per-variant equivalence pins for the two lifted
15581 // [`SupervisorError::child_caixa_invalid`] /
15582 // [`SupervisorError::child_versao_invalid`] inherent constructors
15583 // (fail-before-pass-after by construction — a byte-mismatched ctor body
15584 // would trip its equivalence pin first). Each pins the ctor output to
15585 // its pre-lift struct-literal peer under `PartialEq`, so every wire-up
15586 // in [`SupervisorSpec::validate_children`] on the two variants
15587 // produces a byte-equal `SupervisorError` to the pre-lift open-coded
15588 // struct-literal on the same scalar fixtures. Peers of the sibling
15589 // `membro_caixa_invalid_ctor_matches_struct_literal_wrap` /
15590 // `entrada_para_invalid_ctor_matches_struct_literal_wrap` / … pins on
15591 // the peer `AplicacaoError` envelope's
15592 // [`crate::aplicacao::aplicacao_field_reason_ctors!`] fold.
15593
15594 #[test]
15595 fn child_caixa_invalid_ctor_matches_struct_literal_wrap() {
15596 let caixa = "Worker";
15597 let reason = "sample reason text";
15598 assert_eq!(
15599 SupervisorError::child_caixa_invalid(caixa, reason),
15600 SupervisorError::ChildCaixaInvalid {
15601 caixa: caixa.to_string(),
15602 reason: reason.to_string(),
15603 },
15604 "lifted child_caixa_invalid ctor must produce byte-equal \
15605 SupervisorError to the open-coded struct-literal wrap on the \
15606 same (&str, reason) fixture",
15607 );
15608 }
15609
15610 #[test]
15611 fn child_versao_invalid_ctor_matches_struct_literal_wrap() {
15612 let caixa = "worker";
15613 let versao = "not-a-req";
15614 let reason = "sample reason text";
15615 assert_eq!(
15616 SupervisorError::child_versao_invalid(caixa, versao, reason),
15617 SupervisorError::ChildVersaoInvalid {
15618 caixa: caixa.to_string(),
15619 versao: versao.to_string(),
15620 reason: reason.to_string(),
15621 },
15622 "lifted child_versao_invalid ctor must produce byte-equal \
15623 SupervisorError to the open-coded struct-literal wrap on the \
15624 same (&str, &str, reason) fixture",
15625 );
15626 }
15627
15628 #[test]
15629 fn supervisor_child_reason_ctors_route_reason_through_into_uniformly() {
15630 // Cross-axis pin: sweep the two lifted `{ …, reason }` ctors
15631 // against a `&str`-literal vs. `format!(…)` reason input to pin
15632 // both constructors accept the `impl Into<String>` bound
15633 // uniformly, so neither wire-up site drifts under a per-arm
15634 // wrapper transformation on the caller-side `reason` axis. Peer
15635 // of the sibling
15636 // `aplicacao_field_reason_ctors_route_reason_through_into_uniformly`
15637 // sweep on the peer `AplicacaoError` envelope.
15638 let via_literal = "literal reason text";
15639 let via_format = format!("{} reason text", "literal");
15640 assert_eq!(
15641 SupervisorError::child_caixa_invalid("Worker", via_literal),
15642 SupervisorError::child_caixa_invalid("Worker", via_format.clone()),
15643 );
15644 assert_eq!(
15645 SupervisorError::child_versao_invalid("worker", "not-a-req", via_literal),
15646 SupervisorError::child_versao_invalid("worker", "not-a-req", via_format),
15647 );
15648 }
15649
15650 #[test]
15651 fn supervisor_caixa_only_ctors_route_caixa_through_to_string() {
15652 // Cross-axis pin: sweep the sole constructor input axis (`caixa:
15653 // &str`) through a non-default fixture name against every
15654 // generated arm in the [`supervisor_caixa_only_ctors!`] macro,
15655 // so any wrapper-side lowercase / trim / truncate / re-order on
15656 // the `caixa.to_string()` sole-field construction surfaces
15657 // here rather than at a downstream diagnostic-shape mismatch.
15658 // Peer of the sibling `nome_only_ctor_routes_caixa_through_
15659 // nome_accessor` / `entrada_host_invalid_ctor_routes_host_
15660 // through_to_string` / `contrato_target_ctors_route_edge_
15661 // triple_through_verbatim` / `contrato_empty_pair_ctors_
15662 // route_edge_pair_through_verbatim` cross-axis routing pins on
15663 // the peer `LayoutError` / `AplicacaoError` envelopes; extended
15664 // here onto the `SupervisorError` `{ caixa: String }` envelope
15665 // so every substrate-primitive ctor family in caixa-core
15666 // guarantees the sole-field construction routes the caller's
15667 // `&str` through `.to_string()` verbatim.
15668 let name = "cache-v2";
15669 assert_eq!(
15670 SupervisorError::empty_child_version(name),
15671 SupervisorError::EmptyChildVersion {
15672 caixa: name.to_string(),
15673 },
15674 );
15675 assert_eq!(
15676 SupervisorError::duplicate_child_caixa(name),
15677 SupervisorError::DuplicateChildCaixa {
15678 caixa: name.to_string(),
15679 },
15680 );
15681 assert_eq!(
15682 SupervisorError::child_supervises_self(name),
15683 SupervisorError::ChildSupervisesSelf {
15684 caixa: name.to_string(),
15685 },
15686 );
15687 }
15688
15689 // ── supervisor_scalar_ctors! per-variant + cross-axis pins ──────────────
15690 //
15691 // Per-variant byte-equality pins guaranteeing every generated ctor arm in
15692 // the [`supervisor_scalar_ctors!`] macro produces a `SupervisorError`
15693 // structurally identical to the pre-lift `Self::<variant> { <field>: <val> }`
15694 // one-line struct-literal on the same `Copy`-`RestartStrategy | u32 |
15695 // Duration` fixture, plus one cross-axis sweep that routes each per-variant
15696 // `<field>: <ty>` scalar through the sole `$field:ident: $ty:ty` axis the
15697 // macro exposes so any wrapper-side truncation / re-order / silent `.into()`
15698 // / silent constant-substitution on any one variant surfaces here rather
15699 // than at a downstream per-`:supervisor` diagnostic-shape drift. Peer of the
15700 // sibling per-variant pins on `aplicacao_policy_scalar_ctors!` (7ef425e,
15701 // the 8-variant `AplicacaoError` `{ <field>: Duration | u32 }` fold on the
15702 // per-`:politicas` per-axis cap / canonical-form arms), plus the sibling
15703 // `supervisor_caixa_only_ctors!` (db09650), `SupervisorError::
15704 // {child_caixa_invalid,child_versao_invalid}` (d2ef2ec), and the peer
15705 // `DepError` / `AplicacaoError` / `LayoutError` / `LimitsError` /
15706 // `BehaviorError` / `UpgradeError` per-envelope ctor-macro pins.
15707 #[test]
15708 fn no_children_ctor_matches_struct_literal_wrap() {
15709 let estrategia = RestartStrategy::OneForAll;
15710 assert_eq!(
15711 SupervisorError::no_children(estrategia),
15712 SupervisorError::NoChildren { estrategia },
15713 "generated no_children ctor must produce byte-equal \
15714 `SupervisorError::NoChildren` to the pre-lift struct-literal wrap \
15715 on the same `Copy`-`RestartStrategy` fixture",
15716 );
15717 }
15718
15719 #[test]
15720 fn max_restarts_exceeds_cap_ctor_matches_struct_literal_wrap() {
15721 let max_restarts = SUPERVISOR_MAX_RESTARTS_MAX + 1;
15722 assert_eq!(
15723 SupervisorError::max_restarts_exceeds_cap(max_restarts),
15724 SupervisorError::MaxRestartsExceedsCap { max_restarts },
15725 "generated max_restarts_exceeds_cap ctor must produce byte-equal \
15726 `SupervisorError::MaxRestartsExceedsCap` to the pre-lift \
15727 struct-literal wrap on the same `Copy`-`u32` fixture",
15728 );
15729 }
15730
15731 #[test]
15732 fn restart_window_not_canonical_ctor_matches_struct_literal_wrap() {
15733 let window = Duration::from_micros(1_500);
15734 assert_eq!(
15735 SupervisorError::restart_window_not_canonical(window),
15736 SupervisorError::RestartWindowNotCanonical { window },
15737 "generated restart_window_not_canonical ctor must produce \
15738 byte-equal `SupervisorError::RestartWindowNotCanonical` to the \
15739 pre-lift struct-literal wrap on the same `Copy`-`Duration` fixture",
15740 );
15741 }
15742
15743 #[test]
15744 fn restart_window_exceeds_cap_ctor_matches_struct_literal_wrap() {
15745 let window = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_millis(1);
15746 assert_eq!(
15747 SupervisorError::restart_window_exceeds_cap(window),
15748 SupervisorError::RestartWindowExceedsCap { window },
15749 "generated restart_window_exceeds_cap ctor must produce \
15750 byte-equal `SupervisorError::RestartWindowExceedsCap` to the \
15751 pre-lift struct-literal wrap on the same `Copy`-`Duration` fixture",
15752 );
15753 }
15754
15755 #[test]
15756 fn supervisor_scalar_ctors_route_field_through_copy_uniformly() {
15757 // Cross-axis routing pin: sweep each generated `<field>: <ty>`
15758 // constructor input axis through a non-default `Copy` fixture against
15759 // every arm in the [`supervisor_scalar_ctors!`] macro, so any wrapper-
15760 // side silent `.into()` / silent constant-substitution / silent field
15761 // re-name away from the canonical `estrategia | max_restarts | window`
15762 // axes on any one variant, or a `RestartStrategy | u32 | Duration`
15763 // axis silently rerouted through some other `Copy` coercion, surfaces
15764 // here rather than at a downstream per-`:supervisor` diagnostic-shape
15765 // drift. Peer of the sibling
15766 // `aplicacao_policy_scalar_ctors_route_field_through_copy_uniformly`
15767 // (7ef425e) cross-axis routing pin on the peer `AplicacaoError`
15768 // envelope's per-`:politicas` per-axis ctor family, extended here onto
15769 // the last M2 per-`:supervisor` `Copy`-scalar `SupervisorError`
15770 // variant family folded onto a substrate primitive.
15771 //
15772 // Fixtures picked out of each variant's accept-set boundary rather
15773 // than the default value so a silent constant-substitution to a per-
15774 // variant sentinel surfaces here on the structural-equality assertion.
15775 // The `RestartStrategy` fixture picks `RestForOne` (a non-default arm
15776 // that isn't the `OneForOne` [`SUPERVISOR_ESTRATEGIA_DEFAULT`] and
15777 // isn't the `SimpleOneForOne` arm the sibling
15778 // `SimpleOneForOneWithStaticChildren` unit variant intercepts). The
15779 // `max_restarts` fixture picks an above-cap magnitude the cap arm
15780 // rejects; the two `Duration` fixtures pick the sub-millisecond and
15781 // above-cap ends of the `:restart-window` canonical-form + cap
15782 // bracket respectively.
15783 let estrategia = RestartStrategy::RestForOne;
15784 let above_cap_restarts = SUPERVISOR_MAX_RESTARTS_MAX + 137;
15785 let sub_ms = Duration::from_micros(1_500);
15786 let above_hour = SUPERVISOR_RESTART_WINDOW_MAX + Duration::from_secs(1);
15787 assert_eq!(
15788 SupervisorError::no_children(estrategia),
15789 SupervisorError::NoChildren { estrategia },
15790 );
15791 assert_eq!(
15792 SupervisorError::max_restarts_exceeds_cap(above_cap_restarts),
15793 SupervisorError::MaxRestartsExceedsCap {
15794 max_restarts: above_cap_restarts,
15795 },
15796 );
15797 assert_eq!(
15798 SupervisorError::restart_window_not_canonical(sub_ms),
15799 SupervisorError::RestartWindowNotCanonical { window: sub_ms },
15800 );
15801 assert_eq!(
15802 SupervisorError::restart_window_exceeds_cap(above_hour),
15803 SupervisorError::RestartWindowExceedsCap { window: above_hour },
15804 );
15805 }
15806
15807 #[test]
15808 fn restart_strategy_try_from_bytes_routes_through_from_wire_accessor() {
15809 // Fail-before-pass-after byte-parity pin on the newly lifted
15810 // `impl TryFrom<&[u8]> for RestartStrategy` — asserts the trait-
15811 // idiomatic byte-view reverse-projection standard-library impl
15812 // and the substrate-primitive [`RestartStrategy::from_wire`]
15813 // `Option<Self>` accessor resolve to the same four-arm
15814 // `PascalCase` wire accept-set across every arm the exhaustive
15815 // [`RestartStrategy::ALL`] slice enumerates. Extends the
15816 // substrate-wide trait-idiomatic byte-view reverse-projection
15817 // axis onto the first M2-OTP-shape supervisor-slot closed-set
15818 // fieldless typed enum peer — mirror of the paired
15819 // [`TryFrom<&str> for RestartStrategy`] str-view reverse-
15820 // projection axis on the same enum, and the byte-view companion
15821 // of the pre-existing byte-owned reverse-projection family
15822 // ([`AsRef<[u8]>`], [`From<RestartStrategy> for Vec<u8>`],
15823 // [`From<&RestartStrategy> for Vec<u8>`]) on this same enum.
15824 // Peer of the sibling
15825 // [`crate::kind::tests::caixa_kind_try_from_bytes_routes_through_from_wire_accessor`]
15826 // (18d1940),
15827 // [`crate::dialeto::tests::caixa_dialeto_try_from_bytes_routes_through_from_wire_accessor`]
15828 // (d102cb8), and
15829 // [`crate::dep::tests::dep_list_try_from_bytes_routes_through_from_wire_accessor`]
15830 // (b8f25d5) — tracks the "route through `from_wire` via
15831 // `std::str::from_utf8`" discipline the first-mover established.
15832 //
15833 // Rust's standard library carries no blanket
15834 // `impl<T: for<'a> TryFrom<&'a str>> TryFrom<&[u8]> for T`, so
15835 // a two-hop composition through [`std::str::from_utf8`] + the
15836 // paired [`TryFrom<&str>`] axis is reachable through the pre-
15837 // existing str-view reverse-projection axis alone. But that
15838 // two-hop shape has no compile-time link back to the byte-view
15839 // reverse-projection axis, forces every downstream
15840 // `<T: for<'a> TryFrom<&'a [u8]>>`-bound consumer to open-code
15841 // the composition at every call site, and admits a silent split
15842 // whenever a future call site takes a sibling byte-projection
15843 // axis whose parse arm-set carries no compile-time byte-view
15844 // surface. This impl closes the byte-view reverse-projection
15845 // axis at the substrate-primitive [`RestartStrategy::from_wire`]
15846 // accessor so every future `<T: for<'a> TryFrom<&'a [u8]>>`-
15847 // bound consumer reaches the same four-arm `PascalCase` wire
15848 // accept-set through one trait dispatch.
15849 for &variant in RestartStrategy::ALL {
15850 let wire_bytes: &[u8] = variant.as_str().as_bytes();
15851 assert_eq!(
15852 <RestartStrategy as TryFrom<&[u8]>>::try_from(wire_bytes),
15853 Ok(variant),
15854 "TryFrom<&[u8]> impl on RestartStrategy must round-trip \
15855 RestartStrategy::{variant:?}.as_str().as_bytes() back to \
15856 Ok(RestartStrategy::{variant:?}) — divergence from \
15857 RestartStrategy::from_wire signals a silent detour off \
15858 the substrate-primitive accessor"
15859 );
15860 assert_eq!(
15861 <RestartStrategy as TryFrom<&[u8]>>::try_from(wire_bytes).ok(),
15862 RestartStrategy::from_wire(variant.as_str()),
15863 "TryFrom<&[u8]> ok()-projection on \
15864 RestartStrategy::{variant:?}.as_str().as_bytes() must \
15865 byte-equal RestartStrategy::from_wire on the paired \
15866 &str input"
15867 );
15868 // Cross-axis witness: the byte-view reverse-projection axis
15869 // must agree with the paired str-view reverse-projection
15870 // axis ([`TryFrom<&str>`]) on every accepted arm — the two
15871 // reverse paths share one `PascalCase` accept-set through
15872 // the substrate-primitive `from_wire` accessor.
15873 let via_str: Result<RestartStrategy, ()> =
15874 <RestartStrategy as TryFrom<&str>>::try_from(variant.as_str());
15875 let via_bytes: Result<RestartStrategy, ()> =
15876 <RestartStrategy as TryFrom<&[u8]>>::try_from(wire_bytes);
15877 assert_eq!(
15878 via_bytes, via_str,
15879 "TryFrom<&[u8]> and TryFrom<&str> reverse-projection \
15880 axes on RestartStrategy must agree on \
15881 RestartStrategy::{variant:?} — divergence signals the \
15882 byte-view and str-view reverse paths have drifted off \
15883 the same substrate-primitive from_wire accessor"
15884 );
15885 // Forward/reverse byte-view cross-axis witness: feed the
15886 // paired [`AsRef<[u8]>`] byte-tail back through the new
15887 // impl and assert it round-trips to the originating arm.
15888 let via_asref: &[u8] = <RestartStrategy as AsRef<[u8]>>::as_ref(&variant);
15889 assert_eq!(
15890 <RestartStrategy as TryFrom<&[u8]>>::try_from(via_asref),
15891 Ok(variant),
15892 "TryFrom<&[u8]> ∘ AsRef<[u8]> must round-trip \
15893 RestartStrategy::{variant:?} — divergence signals the \
15894 forward and reverse byte-view axes have drifted off \
15895 the same substrate-primitive as_str/from_wire pair"
15896 );
15897 }
15898 }
15899
15900 #[test]
15901 fn restart_strategy_try_from_bytes_rejects_unknown_and_non_utf8_bytes() {
15902 // Rejection witness on the `impl TryFrom<&[u8]> for
15903 // RestartStrategy` — sweeps two rejection paths the byte-view
15904 // reverse-projection axis collapses onto the single unit-error
15905 // `Err(())` return: the invalid-UTF-8 rejection path
15906 // ([`std::str::from_utf8`] returns `Err` before
15907 // [`RestartStrategy::from_wire`] runs) and the valid-UTF-8-but-
15908 // unknown-wire rejection path ([`RestartStrategy::from_wire`]
15909 // returns `None` on a byte-string outside the four-arm
15910 // `PascalCase` accept-set). Both must reject, so a future
15911 // accidental widening of the trait impl's accept-set (a case-
15912 // fold path, a silent acceptance of the kebab-case dispatcher-
15913 // catalog byte-strings on this axis — which would collide the
15914 // two-axis wire/catalog split the sibling
15915 // [`RestartStrategy::from_wire`] doc block makes load-bearing —
15916 // a `#[serde(rename_all = "…")]` attribute drift that widens
15917 // the parse arm-set silently, a stray fallback that maps
15918 // invalid UTF-8 onto a default arm rather than the trait-
15919 // idiomatic `Err(())`) trips at caixa-core test time. Peer of
15920 // the sibling
15921 // [`crate::kind::tests::caixa_kind_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
15922 // (18d1940),
15923 // [`crate::dialeto::tests::caixa_dialeto_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
15924 // (d102cb8), and
15925 // [`crate::dep::tests::dep_list_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
15926 // (b8f25d5) rejection witnesses.
15927 //
15928 // Non-UTF-8 candidates:
15929 // - a lone 0xFF byte (never valid as a UTF-8 leading byte)
15930 // - a lone 0x80 continuation byte with no leading byte
15931 // - a truncated multi-byte sequence (0xC3 without its continuation)
15932 // - a UTF-16 BOM-style byte pair the UTF-8 validator rejects
15933 // - a UTF-16 surrogate half rejected by UTF-8
15934 let non_utf8_rejected: &[&[u8]] = &[
15935 &[0xFF],
15936 &[0x80],
15937 &[0xC3],
15938 &[0xFF, 0xFE],
15939 &[0xED, 0xA0, 0x80],
15940 ];
15941 for &input in non_utf8_rejected {
15942 assert_eq!(
15943 <RestartStrategy as TryFrom<&[u8]>>::try_from(input),
15944 Err(()),
15945 "TryFrom<&[u8]> impl on RestartStrategy must reject the \
15946 non-UTF-8 byte-sequence {input:?} with Err(()) — \
15947 silent acceptance signals the UTF-8 validation path \
15948 collapsed onto a default arm rather than the trait-\
15949 idiomatic unit-error"
15950 );
15951 }
15952 // Valid-UTF-8-but-unknown-wire candidates mirror the corpus
15953 // the sibling `restart_strategy_try_from_str_rejects_unknown_byte_strings`
15954 // (5b828ed) str-view rejection witness already pins on the
15955 // paired [`TryFrom<&str>`] axis: the empty byte-string,
15956 // whitespace-only padding, the kebab-case dispatcher-catalog
15957 // byte-strings on the sibling axis the pre-existing
15958 // [`std::str::FromStr`] impl the [`gen_platform::FromStrKind`]
15959 // derive installs parses onto (a caller who confuses the two
15960 // axes trips here rather than at a downstream K8s-CR round-
15961 // trip miss), lowercase / uppercase / mixed-case folds of each
15962 // `PascalCase` arm, whitespace-padded / trailing-newline /
15963 // quote-wrapped forms, and plausible-but-wrong English rebrand
15964 // candidates.
15965 let unknown_wire_rejected: &[&[u8]] = &[
15966 b"",
15967 b" ",
15968 b"\n",
15969 b"\t",
15970 b"one-for-one",
15971 b"one-for-all",
15972 b"rest-for-one",
15973 b"simple-one-for-one",
15974 b"oneforone",
15975 b"one_for_one",
15976 b"OneForOnes",
15977 b"ONEFORONE",
15978 b"oneforall",
15979 b"restforone",
15980 b"simpleoneforone",
15981 b"OneForOne ",
15982 b" OneForOne",
15983 b" OneForAll ",
15984 b"OneForOne\n",
15985 b"RestForOne\t",
15986 b"OneForEach",
15987 b"AllForOne",
15988 b"one for one",
15989 b"\"OneForOne\"",
15990 b"?",
15991 ];
15992 for &input in unknown_wire_rejected {
15993 assert_eq!(
15994 <RestartStrategy as TryFrom<&[u8]>>::try_from(input),
15995 Err(()),
15996 "TryFrom<&[u8]> impl on RestartStrategy must reject the \
15997 valid-UTF-8-but-unknown-wire byte-string {input:?} \
15998 with Err(()) — silent acceptance signals an accept-\
15999 set widening off the paired RestartStrategy::from_wire \
16000 resolver"
16001 );
16002 // Cross-axis witness: on a byte-string that is valid UTF-8,
16003 // the byte-view reverse-projection axis must agree with the
16004 // paired str-view reverse-projection axis
16005 // ([`TryFrom<&str>`]) — both route through the same
16006 // [`RestartStrategy::from_wire`] resolver, so the two
16007 // rejection paths align by construction.
16008 if let Ok(s) = std::str::from_utf8(input) {
16009 assert_eq!(
16010 <RestartStrategy as TryFrom<&[u8]>>::try_from(input),
16011 <RestartStrategy as TryFrom<&str>>::try_from(s),
16012 "TryFrom<&[u8]> and TryFrom<&str> reverse-\
16013 projection axes on RestartStrategy must agree on \
16014 the valid-UTF-8 input {input:?} — divergence \
16015 signals the two reverse paths have drifted off \
16016 the same substrate-primitive from_wire accessor"
16017 );
16018 }
16019 }
16020 }
16021
16022 #[test]
16023 fn restart_policy_try_from_bytes_routes_through_from_wire_accessor() {
16024 // Fail-before-pass-after byte-parity pin on the newly lifted
16025 // `impl TryFrom<&[u8]> for RestartPolicy` — asserts the trait-
16026 // idiomatic byte-view reverse-projection standard-library impl
16027 // and the substrate-primitive [`RestartPolicy::from_wire`]
16028 // `Option<Self>` accessor resolve to the same three-arm
16029 // `PascalCase` wire accept-set across every arm the exhaustive
16030 // [`RestartPolicy::ALL`] slice enumerates. Closes the substrate-
16031 // wide trait-idiomatic byte-view reverse-projection axis on the
16032 // M2-OTP-shape `:supervisor :estrategia` + `:children :restart`
16033 // slot pair the sibling [`RestartStrategy`] first-mover
16034 // (c699a83) opened one commit prior — mirror of the paired
16035 // [`TryFrom<&str> for RestartPolicy`] str-view reverse-
16036 // projection axis on the same enum, and the byte-view companion
16037 // of the pre-existing byte-owned reverse-projection family
16038 // ([`AsRef<[u8]>`], [`From<RestartPolicy> for Vec<u8>`],
16039 // [`From<&RestartPolicy> for Vec<u8>`]) on this same enum. Peer
16040 // of the sibling
16041 // [`restart_strategy_try_from_bytes_routes_through_from_wire_accessor`]
16042 // (c699a83),
16043 // [`crate::kind::tests::caixa_kind_try_from_bytes_routes_through_from_wire_accessor`]
16044 // (18d1940),
16045 // [`crate::dialeto::tests::caixa_dialeto_try_from_bytes_routes_through_from_wire_accessor`]
16046 // (d102cb8), and
16047 // [`crate::dep::tests::dep_list_try_from_bytes_routes_through_from_wire_accessor`]
16048 // (b8f25d5) — tracks the "route through `from_wire` via
16049 // `std::str::from_utf8`" discipline the first-mover established.
16050 //
16051 // Rust's standard library carries no blanket
16052 // `impl<T: for<'a> TryFrom<&'a str>> TryFrom<&[u8]> for T`, so a
16053 // two-hop composition through [`std::str::from_utf8`] + the
16054 // paired [`TryFrom<&str>`] axis is reachable through the pre-
16055 // existing str-view reverse-projection axis alone. But that
16056 // two-hop shape has no compile-time link back to the byte-view
16057 // reverse-projection axis, forces every downstream
16058 // `<T: for<'a> TryFrom<&'a [u8]>>`-bound consumer to open-code
16059 // the composition at every call site, and admits a silent split
16060 // whenever a future call site takes a sibling byte-projection
16061 // axis whose parse arm-set carries no compile-time byte-view
16062 // surface. This impl closes the byte-view reverse-projection
16063 // axis at the substrate-primitive [`RestartPolicy::from_wire`]
16064 // accessor so every future `<T: for<'a> TryFrom<&'a [u8]>>`-
16065 // bound consumer reaches the same three-arm `PascalCase` wire
16066 // accept-set through one trait dispatch.
16067 for &variant in RestartPolicy::ALL {
16068 let wire_bytes: &[u8] = variant.as_str().as_bytes();
16069 assert_eq!(
16070 <RestartPolicy as TryFrom<&[u8]>>::try_from(wire_bytes),
16071 Ok(variant),
16072 "TryFrom<&[u8]> impl on RestartPolicy must round-trip \
16073 RestartPolicy::{variant:?}.as_str().as_bytes() back to \
16074 Ok(RestartPolicy::{variant:?}) — divergence from \
16075 RestartPolicy::from_wire signals a silent detour off \
16076 the substrate-primitive accessor"
16077 );
16078 assert_eq!(
16079 <RestartPolicy as TryFrom<&[u8]>>::try_from(wire_bytes).ok(),
16080 RestartPolicy::from_wire(variant.as_str()),
16081 "TryFrom<&[u8]> ok()-projection on \
16082 RestartPolicy::{variant:?}.as_str().as_bytes() must \
16083 byte-equal RestartPolicy::from_wire on the paired \
16084 &str input"
16085 );
16086 // Cross-axis witness: the byte-view reverse-projection axis
16087 // must agree with the paired str-view reverse-projection
16088 // axis ([`TryFrom<&str>`]) on every accepted arm — the two
16089 // reverse paths share one `PascalCase` accept-set through
16090 // the substrate-primitive `from_wire` accessor.
16091 let via_str: Result<RestartPolicy, ()> =
16092 <RestartPolicy as TryFrom<&str>>::try_from(variant.as_str());
16093 let via_bytes: Result<RestartPolicy, ()> =
16094 <RestartPolicy as TryFrom<&[u8]>>::try_from(wire_bytes);
16095 assert_eq!(
16096 via_bytes, via_str,
16097 "TryFrom<&[u8]> and TryFrom<&str> reverse-projection \
16098 axes on RestartPolicy must agree on \
16099 RestartPolicy::{variant:?} — divergence signals the \
16100 byte-view and str-view reverse paths have drifted off \
16101 the same substrate-primitive from_wire accessor"
16102 );
16103 // Forward/reverse byte-view cross-axis witness: feed the
16104 // paired [`AsRef<[u8]>`] byte-tail back through the new
16105 // impl and assert it round-trips to the originating arm.
16106 let via_asref: &[u8] = <RestartPolicy as AsRef<[u8]>>::as_ref(&variant);
16107 assert_eq!(
16108 <RestartPolicy as TryFrom<&[u8]>>::try_from(via_asref),
16109 Ok(variant),
16110 "TryFrom<&[u8]> ∘ AsRef<[u8]> must round-trip \
16111 RestartPolicy::{variant:?} — divergence signals the \
16112 forward and reverse byte-view axes have drifted off \
16113 the same substrate-primitive as_str/from_wire pair"
16114 );
16115 }
16116 }
16117
16118 #[test]
16119 fn restart_policy_try_from_bytes_rejects_unknown_and_non_utf8_bytes() {
16120 // Rejection witness on the `impl TryFrom<&[u8]> for RestartPolicy`
16121 // — sweeps two rejection paths the byte-view reverse-projection
16122 // axis collapses onto the single unit-error `Err(())` return: the
16123 // invalid-UTF-8 rejection path ([`std::str::from_utf8`] returns
16124 // `Err` before [`RestartPolicy::from_wire`] runs) and the
16125 // valid-UTF-8-but-unknown-wire rejection path
16126 // ([`RestartPolicy::from_wire`] returns `None` on a byte-string
16127 // outside the three-arm `PascalCase` accept-set). Both must
16128 // reject, so a future accidental widening of the trait impl's
16129 // accept-set (a case-fold path, a silent acceptance of the
16130 // kebab-case dispatcher-catalog byte-strings on this axis — which
16131 // would collide the two-axis wire/catalog split the sibling
16132 // [`RestartPolicy::from_wire`] doc block makes load-bearing — a
16133 // `#[serde(rename_all = "…")]` attribute drift that widens the
16134 // parse arm-set silently, a stray fallback that maps invalid
16135 // UTF-8 onto a default arm rather than the trait-idiomatic
16136 // `Err(())`) trips at caixa-core test time. Peer of the sibling
16137 // [`restart_strategy_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
16138 // (c699a83),
16139 // [`crate::kind::tests::caixa_kind_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
16140 // (18d1940),
16141 // [`crate::dialeto::tests::caixa_dialeto_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
16142 // (d102cb8), and
16143 // [`crate::dep::tests::dep_list_try_from_bytes_rejects_unknown_and_non_utf8_bytes`]
16144 // (b8f25d5) rejection witnesses.
16145 //
16146 // Non-UTF-8 candidates:
16147 // - a lone 0xFF byte (never valid as a UTF-8 leading byte)
16148 // - a lone 0x80 continuation byte with no leading byte
16149 // - a truncated multi-byte sequence (0xC3 without its continuation)
16150 // - a UTF-16 BOM-style byte pair the UTF-8 validator rejects
16151 // - a UTF-16 surrogate half rejected by UTF-8
16152 let non_utf8_rejected: &[&[u8]] = &[
16153 &[0xFF],
16154 &[0x80],
16155 &[0xC3],
16156 &[0xFF, 0xFE],
16157 &[0xED, 0xA0, 0x80],
16158 ];
16159 for &input in non_utf8_rejected {
16160 assert_eq!(
16161 <RestartPolicy as TryFrom<&[u8]>>::try_from(input),
16162 Err(()),
16163 "TryFrom<&[u8]> impl on RestartPolicy must reject the \
16164 non-UTF-8 byte-sequence {input:?} with Err(()) — \
16165 silent acceptance signals the UTF-8 validation path \
16166 collapsed onto a default arm rather than the trait-\
16167 idiomatic unit-error"
16168 );
16169 }
16170 // Valid-UTF-8-but-unknown-wire candidates mirror the corpus the
16171 // sibling `restart_policy_try_from_str_rejects_unknown_byte_strings`
16172 // str-view rejection witness already pins on the paired
16173 // [`TryFrom<&str>`] axis: the empty byte-string, whitespace-only
16174 // padding, the kebab-case dispatcher-catalog byte-strings on the
16175 // sibling axis the pre-existing [`std::str::FromStr`] impl the
16176 // [`gen_platform::FromStrKind`] derive installs parses onto (a
16177 // caller who confuses the two axes trips here rather than at a
16178 // downstream K8s-CR round-trip miss), lowercase / uppercase /
16179 // mixed-case folds of each `PascalCase` arm, whitespace-padded /
16180 // trailing-newline / quote-wrapped forms, and plausible-but-wrong
16181 // English rebrand candidates (`Ephemeral`, `Always`, `Never`,
16182 // `OnAbnormalExit`, `intrinsic`).
16183 let unknown_wire_rejected: &[&[u8]] = &[
16184 b"",
16185 b" ",
16186 b"\n",
16187 b"\t",
16188 b"permanent",
16189 b"temporary",
16190 b"transient",
16191 b"PERMANENT",
16192 b"TEMPORARY",
16193 b"TRANSIENT",
16194 b"Permanents",
16195 b"Permanent ",
16196 b" Permanent",
16197 b" Temporary ",
16198 b"Permanent\n",
16199 b"Transient\t",
16200 b"\"Permanent\"",
16201 b"Ephemeral",
16202 b"Always",
16203 b"Never",
16204 b"OnAbnormalExit",
16205 b"intrinsic",
16206 b"?",
16207 ];
16208 for &input in unknown_wire_rejected {
16209 assert_eq!(
16210 <RestartPolicy as TryFrom<&[u8]>>::try_from(input),
16211 Err(()),
16212 "TryFrom<&[u8]> impl on RestartPolicy must reject the \
16213 valid-UTF-8-but-unknown-wire byte-string {input:?} \
16214 with Err(()) — silent acceptance signals an accept-\
16215 set widening off the paired RestartPolicy::from_wire \
16216 resolver"
16217 );
16218 // Cross-axis witness: on a byte-string that is valid UTF-8,
16219 // the byte-view reverse-projection axis must agree with the
16220 // paired str-view reverse-projection axis
16221 // ([`TryFrom<&str>`]) — both route through the same
16222 // [`RestartPolicy::from_wire`] resolver, so the two
16223 // rejection paths align by construction.
16224 if let Ok(s) = std::str::from_utf8(input) {
16225 assert_eq!(
16226 <RestartPolicy as TryFrom<&[u8]>>::try_from(input),
16227 <RestartPolicy as TryFrom<&str>>::try_from(s),
16228 "TryFrom<&[u8]> and TryFrom<&str> reverse-\
16229 projection axes on RestartPolicy must agree on \
16230 the valid-UTF-8 input {input:?} — divergence \
16231 signals the two reverse paths have drifted off \
16232 the same substrate-primitive from_wire accessor"
16233 );
16234 }
16235 }
16236 }
16237
16238 #[test]
16239 fn supervisor_scalar_ctors_are_const_zero_runtime_work() {
16240 // Const-eval pin: the [`supervisor_scalar_ctors!`] macro spells every
16241 // generated ctor `const fn` so a caller can pin a `SupervisorError`
16242 // at compile time — the same zero-runtime-work property the pre-lift
16243 // `|<slot>| SupervisorError::<Variant> { <slot> }` closure carried on
16244 // its `Copy`-pass-through construction path (no `.to_string()` /
16245 // `.into()` allocation, no branching). If any future edit silently
16246 // drops the `const` qualifier from the macro body the per-arm `const`
16247 // bindings below fail to compile, which surfaces the regression at
16248 // the substrate-primitive definition rather than at some downstream
16249 // consumer that had come to rely on the `const`-constructibility.
16250 // Peer of the sibling
16251 // `aplicacao_policy_scalar_ctors_are_const_zero_runtime_work`
16252 // (7ef425e) const-eval pin on the peer `AplicacaoError` envelope's
16253 // per-`:politicas` per-axis ctor family.
16254 const NO_CHILDREN: SupervisorError =
16255 SupervisorError::no_children(RestartStrategy::OneForAll);
16256 const MAX_RESTARTS_CAP: SupervisorError = SupervisorError::max_restarts_exceeds_cap(1_337);
16257 const WINDOW_NC: SupervisorError =
16258 SupervisorError::restart_window_not_canonical(Duration::from_micros(1));
16259 const WINDOW_CAP: SupervisorError =
16260 SupervisorError::restart_window_exceeds_cap(Duration::from_secs(3_601));
16261 assert!(matches!(NO_CHILDREN, SupervisorError::NoChildren { .. }));
16262 assert!(matches!(
16263 MAX_RESTARTS_CAP,
16264 SupervisorError::MaxRestartsExceedsCap { .. }
16265 ));
16266 assert!(matches!(
16267 WINDOW_NC,
16268 SupervisorError::RestartWindowNotCanonical { .. }
16269 ));
16270 assert!(matches!(
16271 WINDOW_CAP,
16272 SupervisorError::RestartWindowExceedsCap { .. }
16273 ));
16274 }
16275}