Skip to main content

caixa_core/
version.rs

1use std::fmt;
2
3use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6/// A caixa's pinned version — a thin typed wrapper over a String that parses
7/// as [`semver::Version`] on demand.
8///
9/// Stored as a String at rest so authoring a `caixa.lisp` stays a single
10/// quoted literal. The typed form is reached through [`Self::parse`].
11#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
12#[serde(transparent)]
13pub struct CaixaVersion(pub String);
14
15impl CaixaVersion {
16    /// Parse and validate the wrapped string as semver.
17    pub fn parse(&self) -> Result<semver::Version, VersionError> {
18        semver::Version::parse(&self.0)
19            .map_err(|e| VersionError::semver(self.0.clone(), e.to_string()))
20    }
21
22    /// Borrow the string form.
23    #[must_use]
24    pub const fn as_str(&self) -> &str {
25        self.0.as_str()
26    }
27}
28
29impl fmt::Display for CaixaVersion {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        f.write_str(&self.0)
32    }
33}
34
35impl From<String> for CaixaVersion {
36    fn from(s: String) -> Self {
37        Self(s)
38    }
39}
40
41impl From<&str> for CaixaVersion {
42    fn from(s: &str) -> Self {
43        Self(s.to_string())
44    }
45}
46
47/// Substrate-canonical stdlib [`std::str::FromStr`] parse-set entry point on
48/// the [`CaixaVersion`] newtype primitive — closes the canonical
49/// `str::parse::<CaixaVersion>()` axis on the paired [`From<&str> for
50/// CaixaVersion`] / [`From<String> for CaixaVersion`] infallible
51/// forward-projection constructors. Delegates byte-for-byte through the
52/// paired borrowed-input `impl From<&str> for CaixaVersion` immediately
53/// above (which wraps `s.to_string()` into the newtype's inner `String`
54/// slot), so every consumer that reaches [`CaixaVersion`] through the
55/// stdlib `T: FromStr`-bounded parse surface (`str::parse::<CaixaVersion>`,
56/// a `clap::Parser`-derived `#[arg(value_parser)]` on a future `feira
57/// publish --versao <ver>` arg-parse, a `serde_with::DisplayFromStr`
58/// wrapper on the [`crate::Caixa::versao`] field in a downstream typed-YAML
59/// derive, or any generic `fn parse_versao<T: FromStr>(s: &str) -> Result<T,
60/// T::Err>` receiver) routes through the same [`String::to_string`]-shaped
61/// wrap the paired `From<&str>` constructor already exercises. `type Err =
62/// std::convert::Infallible` because the paired `From<&str>` constructor is
63/// total — [`CaixaVersion`] stores the wrapped string raw at rest (the
64/// author surface's single-quoted `:versao "…"` literal round-trips
65/// byte-for-byte) and defers semver validation to the paired
66/// [`CaixaVersion::parse`] `Result<semver::Version, VersionError>`
67/// accessor, so no byte-string the standard-library parse-set entry point
68/// receives can fail construction on this axis (any `&str` is a valid
69/// `CaixaVersion` body at rest; only `.parse::<semver::Version>()` on the
70/// wrapped body can reject a shape the semver grammar refuses). Peer of
71/// the paired `impl FromStr for String` stdlib impl on the standard-library
72/// `String` newtype (whose `Err = Infallible` covers the same "any `&str` is
73/// a valid `String` body" total-wrap discipline the [`CaixaVersion`]
74/// newtype installs on the caixa-core surface). The first standard-library
75/// stdlib-parse-set entry point on the [`CaixaVersion`] newtype beyond the
76/// paired forward-projection [`From<&str>`] / [`From<String>`]
77/// constructors and the sibling [`fmt::Display`] / [`AsRef<str>`] /
78/// [`std::borrow::Borrow<str>`] projections the newtype already carries.
79///
80/// # Compounding
81///
82/// The stdlib parse-set entry point is the canonical Rust-idiomatic axis
83/// generic bounds compose against: `str::parse::<T>()` is a `T: FromStr`-
84/// bounded generic (not a `T: for<'a> TryFrom<&'a str>`-bounded one), so
85/// lifting the axis onto [`CaixaVersion`] unlocks the `.parse::<CaixaVersion>()`
86/// short-form on every future stdlib-shaped consumer without forcing the
87/// caller to spell the paired `From<&str>` constructor at the wire-up site.
88/// A future `clap::Args`-derived `feira publish --versao <ver>` arg-parse
89/// composes `arg.parse::<CaixaVersion>()` directly through the
90/// `#[arg(value_parser = clap::value_parser!(CaixaVersion))]` short-form
91/// (which resolves through the `T: FromStr` bound `clap::value_parser!`
92/// installs on any type carrying the trait), a `serde_with::DisplayFromStr`
93/// wrapper on a future typed-YAML [`crate::Caixa::versao`] field routes
94/// through the same `T: FromStr` bound `serde_with` keys off, and any
95/// generic per-authored-string coalescer over a mixed newtype family
96/// (`Result<T, T::Err>` on a `T: FromStr` bound) picks up
97/// [`CaixaVersion`] as one of its arms by construction.
98///
99/// # Round-trip discipline
100///
101/// The `Err = Infallible` shape witnesses the round-trip discipline the
102/// paired forward-projection [`fmt::Display`] impl closes at compile time:
103/// `s.parse::<CaixaVersion>().unwrap().to_string() == s` for every `&str`
104/// (the fail-before-pass-after pin
105/// [`caixa_version_from_str_round_trips_through_display_on_every_input`]
106/// witnesses this against the sibling `caret_matches_minor_range` /
107/// `star_is_any` / `caixa_version_as_str_accessor_is_const_fn` fixture
108/// bodies covering the semver-shape, prerelease-shape, empty-body,
109/// requirement-shape, and non-semver-junk corners). Any future accidental
110/// narrowing (a stray `parse_semver_first` validation gate slipping onto
111/// the wrap path, a normalization step that would drop whitespace or
112/// canonicalize a prerelease tag) trips the pin at caixa-core build time
113/// under the byte-equality assertion, refusing the divergent shape ahead
114/// of the downstream materializer's admit cycle.
115impl std::str::FromStr for CaixaVersion {
116    type Err = std::convert::Infallible;
117
118    fn from_str(s: &str) -> Result<Self, Self::Err> {
119        // Delegate byte-for-byte through the paired borrowed-input
120        // `impl From<&str> for CaixaVersion` constructor above — the
121        // total-wrap axis every stdlib `T: FromStr`-bounded consumer
122        // reaches [`CaixaVersion`] through resolves to the same
123        // [`String::to_string`]-shaped body the sibling forward-
124        // projection constructor already installs. `type Err =
125        // Infallible` because the paired constructor is total; `Ok`
126        // is the only reachable arm on this axis.
127        Ok(<Self as From<&str>>::from(s))
128    }
129}
130
131/// Substrate-canonical [`AsRef<str>`] projection on the [`CaixaVersion`]
132/// typed newtype — routes through the same [`CaixaVersion::as_str`]
133/// `pub const fn` scalar accessor the sibling [`fmt::Display`] impl
134/// and every downstream `&str`-shaped consumer already keys off, so
135/// any future consumer that binds a [`CaixaVersion`] through the
136/// standard-library `impl AsRef<str>` bound (a `Path`-shaped file-
137/// system reader on the operator side that accepts the version body
138/// as one segment of a per-caixa `versao/<v>/...` on-disk cache path,
139/// a builder-shaped API on the future `feira publish` writer verb
140/// that composes `<prefix><versao>` through a git-tag builder crate's
141/// `impl AsRef<str>` join step, a `HashMap<CaixaVersion, _>` lookup
142/// through the `map.get::<str>(v.as_ref())` shape a future
143/// version-keyed dispatch table lands on) reaches the wrapped
144/// [`String`] through one substrate-primitive dispatch rather than
145/// through the pre-lift `.as_str()` open-coded projection at every
146/// wire-up.
147///
148/// Peer of the sibling [`fmt::Display`] impl on the same primitive —
149/// both delegate to the shared [`CaixaVersion::as_str`] `pub const
150/// fn` accessor, so [`format!("{v}")`], `v.as_str()`, and
151/// `<CaixaVersion as AsRef<str>>::as_ref(&v)` resolve to the same
152/// byte-string per instance by construction. A future rebrand of the
153/// wrapped storage (a hypothetical widening to a typed [`semver::Version`]
154/// slot the roadmap acknowledges once eager parse-on-construct
155/// discipline lands, an internal normalization step that trims
156/// leading zeroes off pre-release identifiers, a per-cluster overlay
157/// the operator pins through a future `:versao-overrides` slot) that
158/// changes what [`CaixaVersion::as_str`] returns migrates every
159/// consumer of every one of the three paths in lockstep.
160///
161/// Same "route the trait impl through the substrate-primitive
162/// accessor" discipline the sibling [`fmt::Display`] impl on this
163/// type already carries — extends it onto the standard-library
164/// [`AsRef<str>`] projection axis every third-party API that takes
165/// `impl AsRef<str>` (the [`std::path::Path::new`] / [`std::fs`]
166/// interop surface, [`std::process::Command::arg`], the peer
167/// `tracing::field::Value` recorder's `Str`-arm, every `clap`-side
168/// `value_parser!` fold that accepts an owned newtype through
169/// `impl AsRef<str>`) already binds through. Rust-side newtype
170/// convention pairs `AsRef<str>` and [`fmt::Display`] on the same
171/// primitive so a caller who has one has both; before this lift,
172/// [`CaixaVersion`] carried [`fmt::Display`] but not the paired
173/// [`AsRef<str>`] impl the convention names.
174///
175/// The first standard-library trait added to [`CaixaVersion`] beyond
176/// the pre-existing [`serde::Serialize`] / [`serde::Deserialize`] /
177/// [`Debug`] / [`Clone`] / [`PartialEq`] / [`Eq`] / [`Hash`] derives
178/// and the paired [`fmt::Display`] / [`From<String>`] / [`From<&str>`]
179/// hand-written impls. Pinned load-bearing by
180/// [`tests::caixa_version_as_ref_str_routes_through_as_str_accessor`]
181/// (byte-parity pin against [`CaixaVersion::as_str`]) — any future
182/// silent detour that routes the impl through a divergent projection
183/// (a `Cow<'_, str>` intermediate, a stray `.to_lowercase()`
184/// normalization, a swap onto a per-arm inline `&self.0.as_str()`
185/// re-inlining) trips at caixa-core test time under `assert_eq!`
186/// rather than at a downstream `impl AsRef<str>`-bound consumer's
187/// silent split.
188impl AsRef<str> for CaixaVersion {
189    fn as_ref(&self) -> &str {
190        self.as_str()
191    }
192}
193
194/// Trait-idiomatic *HashMap-key-shaped* borrow projection on the
195/// [`CaixaVersion`] newtype primitive — the standard-library
196/// [`std::borrow::Borrow<str>`] companion to the paired sibling
197/// [`AsRef<str>`] impl (a086 lift) on the same borrow-projection axis of
198/// this primitive. Routes byte-for-byte through the substrate-primitive
199/// [`CaixaVersion::as_str`] `pub const fn` accessor — the same accessor
200/// the paired [`AsRef<str>`] and [`fmt::Display`] impls already delegate
201/// through — so every consumer that binds a [`CaixaVersion`] through the
202/// standard-library `Borrow<str>` bound reaches the wrapped byte-string
203/// through one substrate-primitive dispatch rather than through a
204/// pre-lift `.as_str()` open-coded projection at every wire-up.
205///
206/// A future consumer that wants to key a map or set by
207/// [`CaixaVersion`] and look up entries by a borrowed [`&str`] — a
208/// per-`:versao` compatibility matrix `HashMap<CaixaVersion, PolicyRow>`
209/// where the reconciliation loop's per-cycle `.get(current_versao_str)`
210/// probes the map with the raw `&str` view of the current cluster
211/// snapshot's version body (the `HashMap::get<Q: ?Sized>` signature is
212/// `where K: Borrow<Q>, Q: Hash + Eq`; without this impl the caller must
213/// wrap the borrowed `&str` in a fresh [`CaixaVersion`] allocation on
214/// every probe), a future `BTreeMap<CaixaVersion, _>::range(..)` sweep
215/// over a per-versao index that accepts a borrowed `&str` range bound
216/// through the same `Borrow<str>` bound, a
217/// `HashSet<CaixaVersion>::contains(&str)` membership probe on a
218/// per-versao denylist keyed by owned [`CaixaVersion`] but queried by
219/// the borrowed view — reaches the wrapped byte-string through this one
220/// dispatch on the substrate primitive, without the pre-lift
221/// `CaixaVersion::from(<&str>)` per-probe allocation the paired forward
222/// [`From<&str> for CaixaVersion`] constructor would otherwise force at
223/// every lookup site.
224///
225/// Peer of the sibling [`AsRef<str>`] impl on the same borrow-projection
226/// axis — both project a borrowed `&self` binding onto a borrowed `&str`
227/// via the shared substrate-primitive [`CaixaVersion::as_str`] accessor.
228/// Rust's standard library deliberately splits the two trait axes on the
229/// two bounds they carry: [`AsRef<str>`] is the *conversion* bound used
230/// by APIs that accept `impl AsRef<str>` and view the input as a `&str`
231/// projection (the [`std::path::Path::new`] / [`std::fs`] interop
232/// surface, [`std::process::Command::arg`], [`clap`]-side
233/// `value_parser!` folds), while [`std::borrow::Borrow<str>`] is the
234/// stricter *identity* bound the collection APIs
235/// ([`std::collections::HashMap`], [`std::collections::BTreeMap`],
236/// [`std::collections::HashSet`], [`std::collections::BTreeSet`]) key
237/// their lookup surfaces off — [`std::borrow::Borrow`] additionally
238/// promises that a borrowed view produced through [`Borrow::borrow`]
239/// hashes and compares byte-identically to the owned form, which is the
240/// contract [`std::collections::HashMap::get`] relies on when it hashes
241/// the query key through `Q` (`str`) and matches against slot keys
242/// hashed through `K` ([`CaixaVersion`]). The [`CaixaVersion`] newtype
243/// meets that contract by construction: the derived [`Hash`] impl hashes
244/// the wrapped [`String`] field, which (through the standard-library
245/// `impl Hash for String { fn hash(...) { (**self).hash(...) } }`
246/// pass-through) dispatches to [`str::hash`] on the raw bytes — the same
247/// dispatch a direct `.hash()` on the `&str` returned by
248/// [`Self::borrow`] would take. The derived [`PartialEq`] and [`Eq`]
249/// impls compare field-wise (byte-equal on the wrapped [`String`]), so
250/// `cv1 == cv2` reduces to `cv1.borrow() == cv2.borrow()` at the
251/// `&str`-projection axis. Both invariants — hash-agrees and
252/// eq-agrees — hold structurally, so this impl is sound under the
253/// [`std::borrow::Borrow`] documented safety contract.
254///
255/// Same "one substrate-primitive dispatch, one shared accessor" discipline
256/// the paired [`AsRef<str>`] impl on this primitive already carries —
257/// extends it onto the [`std::borrow::Borrow<str>`] projection axis the
258/// standard-library collection APIs key their `.get::<Q>` /
259/// `.contains::<Q>` / `.range::<R, T>` / `.remove::<Q>` lookup surfaces
260/// off. Rust's standard library mirrors this exact pairing on its own
261/// [`String`] primitive (`impl AsRef<str> for String` +
262/// `impl Borrow<str> for String`), so a newtype that carries one axis
263/// but not the other splits off the convention that lets every
264/// [`String`]-shaped consumer swap the newtype in without re-shaping
265/// its bounds.
266///
267/// Pinned load-bearing by
268/// [`tests::caixa_version_borrow_str_routes_through_as_str_accessor`]
269/// (byte-parity pin against [`CaixaVersion::as_str`] on the same
270/// instance),
271/// [`tests::caixa_version_borrow_str_and_as_ref_str_agree_on_every_shape`]
272/// (cross-axis partition pin against the paired [`AsRef<str>`] impl,
273/// closing the "borrow-axis two-corner split" bifurcation on the same
274/// wrapped body), and
275/// [`tests::caixa_version_borrow_str_enables_hashmap_lookup_by_borrowed_key`]
276/// (contract-witness pin routing a [`std::collections::HashMap::get`]
277/// probe against a `&str` key through the `Borrow<str>` bound on a map
278/// keyed by owned [`CaixaVersion`], asserting the collection APIs reach
279/// the same slot the borrowed and owned forms compose the same hash for).
280impl std::borrow::Borrow<str> for CaixaVersion {
281    fn borrow(&self) -> &str {
282        self.as_str()
283    }
284}
285
286/// Trait-idiomatic *owned-`String`* reverse projection on the
287/// [`CaixaVersion`] newtype primitive — the owned-heap-string inverse
288/// of the pre-existing [`From<String> for CaixaVersion`] /
289/// [`From<&str> for CaixaVersion`] forward-projection pair on this
290/// primitive. Returns the wrapped [`String`] verbatim ([`Self::0`],
291/// a move of the pre-existing heap allocation — no re-copy of the
292/// per-instance version body's bytes), so every consumer that binds a
293/// [`CaixaVersion`] through the standard-library `.into()` /
294/// [`From<Self> for String`] (equivalently [`Into<String>`]) axis
295/// reaches the wrapped byte-string through one substrate-primitive
296/// dispatch rather than through a `.as_str().to_owned()` /
297/// `.to_string()` allocating detour whose bounds have no compile-time
298/// link back to the newtype's storage.
299///
300/// A future consumer that wants to unwrap a [`CaixaVersion`] into an
301/// owned [`String`] — a `serde_json::Value::String(versao.into())`
302/// structured-payload composer where the `Value::String` arm typing
303/// demands an owned [`String`] and the sibling
304/// [`AsRef<str>`]-borrowed axis forces an explicit `.to_owned()`
305/// restatement at every call site, a future
306/// `HashMap::<String, _>::from_iter([(versao.into(), _)])` per-versao
307/// lookup where the map's key type is owned [`String`] rather than
308/// [`&str`] borrowed from a stashed [`CaixaVersion`], a future
309/// `Cow::<'static, str>::Owned(versao.into())` composer where the
310/// owned arm typing rules out the borrowed [`AsRef<str>`] return —
311/// reaches the wrapped [`String`] through this one dispatch, avoiding
312/// the pre-lift double-allocation (`.as_str().to_owned()` on the owned
313/// path would allocate a fresh [`String`] rather than reuse the
314/// wrapper's own heap allocation).
315///
316/// Opens the trait-idiomatic *owned-`String`* reverse-projection axis
317/// on the substrate's core String-wrapper newtype primitive
318/// [`CaixaVersion`], mirroring the paired owned-`String` forward-
319/// projection family the sibling closed-set fieldless typed enums
320/// ([`crate::supervisor::RestartStrategy`] (7baa18a, first-mover),
321/// [`crate::supervisor::RestartPolicy`] (7851725),
322/// [`crate::CaixaKind`] (per its own doc block, third peer), plus the
323/// remaining twelve closed-set enums) already carry — Rust's standard
324/// library does not derive `From<Self> for String` from `From<String>
325/// for Self`, so every newtype that carries a forward `From<String>`
326/// constructor but not the paired reverse-unwrap axis forces every
327/// call site through a `.to_string()` / `.as_str().to_owned()` detour
328/// that allocates fresh bytes rather than moving the wrapper's own
329/// heap allocation.
330///
331/// Preserves the two-path split on the wrapped byte-string: the paired
332/// [`AsRef<str>`] and [`fmt::Display`] impls stay reachable for the
333/// borrowed `&str` and formatter-output paths, this impl closes the
334/// owned-`String` reverse axis. Same "one dispatch on the substrate
335/// primitive" discipline the peer forward `From<String> for
336/// CaixaVersion` / `From<&str> for CaixaVersion` constructors carry,
337/// now extended onto the owned-heap-string reverse projection.
338///
339/// Pinned load-bearing by
340/// [`tests::caixa_version_from_into_owned_string_returns_wrapped_body`]
341/// (byte-parity pin against [`CaixaVersion::as_str`] on the same
342/// instance) and
343/// [`tests::caixa_version_from_into_owned_string_and_as_str_agree_on_every_shape`]
344/// (cross-axis partition pin against the paired borrowed
345/// [`AsRef<str>`] impl and the sibling [`fmt::Display`]-routed
346/// [`ToString::to_string`] surface, plus a round-trip witness through
347/// the paired forward [`From<String> for CaixaVersion`] constructor
348/// closing the two-way `Self → String → Self` cycle by construction).
349impl From<CaixaVersion> for String {
350    fn from(v: CaixaVersion) -> String {
351        v.0
352    }
353}
354
355/// Trait-idiomatic *borrowed-input, owned-`String` output* reverse
356/// projection on the [`CaixaVersion`] newtype primitive — the
357/// borrowed-input companion to the paired owned-input
358/// [`From<CaixaVersion> for String`] impl immediately above. Routes
359/// byte-for-byte through the substrate-primitive
360/// [`CaixaVersion::as_str`] `pub const fn` accessor (via
361/// [`str::to_owned`]) so every consumer that holds a
362/// borrowed [`&CaixaVersion`] and needs an owned [`String`] — a
363/// `[…].iter().map(String::from).collect::<Vec<_>>()` per-instance
364/// materializer over `&[CaixaVersion]` (whose iterator yields
365/// `&CaixaVersion`, not `CaixaVersion`, so the owned-input
366/// [`From<CaixaVersion> for String`] axis alone forces every call site
367/// through an explicit `.clone()` / dereference restatement), a future
368/// `HashMap::<String, _>::from_iter` that keys off a borrowed-
369/// iteration axis where cloning the wrapper would allocate one
370/// [`String`] beyond the map entry's own, a future
371/// `serde_json::Value::String(String::from(&caixa.versao))`
372/// structured-payload composer that owns the emit-path without moving
373/// out of a borrowed field — reaches the wrapped byte-string through
374/// this one dispatch on the substrate primitive.
375///
376/// Second corner on the `{Self, &Self} → String` reverse-projection
377/// family opened on the paired owned-input
378/// [`From<CaixaVersion> for String`] impl immediately above. Rust's
379/// `From` trait does not derive the `From<&Self>` sibling from a
380/// `From<Self>` impl (the blanket
381/// `impl<T, U> From<&T> for U where T: Clone, U: From<T>` does not
382/// exist in `core`), so every newtype that carries the owned-input
383/// reverse axis but not the borrowed-input axis forces every borrowed
384/// call site through a `.clone()` / `<String>::from(v.clone())` detour
385/// whose type bounds have no compile-time link back to the newtype.
386///
387/// Pinned load-bearing by
388/// [`tests::caixa_version_from_borrowed_into_owned_string_routes_through_as_str_accessor`]
389/// (byte-parity pin against [`CaixaVersion::as_str`] via a borrowed
390/// input) and
391/// [`tests::caixa_version_from_owned_and_borrowed_into_string_agree_on_every_shape`]
392/// (cross-axis partition pin against the paired owned-input
393/// [`From<CaixaVersion> for String`] impl on the same instance,
394/// closing the "owned-input move vs. borrowed-input clone" bifurcation
395/// on the same wrapped body).
396impl From<&CaixaVersion> for String {
397    fn from(v: &CaixaVersion) -> String {
398        v.as_str().to_owned()
399    }
400}
401
402/// Trait-idiomatic *owned-input, [`std::borrow::Cow<'static, str>`]
403/// output* reverse projection on the [`CaixaVersion`] newtype
404/// primitive — the [`Cow<'static, str>`] companion to the paired
405/// owned-input [`From<CaixaVersion> for String`] impl (999a310) on
406/// the same primitive. Routes through
407/// [`std::borrow::Cow::Owned`]`(v.0)`, moving the wrapper's own heap
408/// allocation through verbatim (no re-copy of the per-instance version
409/// body's bytes, no allocating detour through
410/// [`CaixaVersion::as_str`] + [`str::to_owned`]) — so every consumer
411/// that binds a [`CaixaVersion`] through the standard-library `.into()`
412/// / [`From<Self> for Cow<'static, str>`] axis reaches the wrapped
413/// byte-string through one substrate-primitive dispatch on the exact
414/// same heap allocation the manifest-parse forward
415/// [`From<String> for CaixaVersion`] constructor accepted.
416///
417/// A future consumer that wants a [`Cow<'static, str>`]-typed handle
418/// on a [`CaixaVersion`] — a
419/// `metric_label: Cow<'static, str> = versao.into()` structured-log
420/// key on a future per-caixa `caixa-operator` reconciliation counter
421/// (whose emit surface types metric keys as `Cow<'static, str>` so
422/// static compile-time literals and dynamic version bodies share the
423/// same key-slot without an unconditional heap allocation on the
424/// literal path), a future
425/// `HashMap::<Cow<'static, str>, _>::from_iter([(versao.into(), _)])`
426/// per-versao lookup where the map's key type is
427/// [`Cow<'static, str>`] rather than owned [`String`] so
428/// literal-lifetime keys can share the same map without wrapping in an
429/// extra [`String`] allocation, a future M4 admission-webhook
430/// rejection body whose per-arm error message composes through
431/// `format!("{}", Cow::<'static, str>::from(caixa.versao))` where the
432/// [`Cow<'static, str>`] intermediate is what the sibling error-frame
433/// composer accepts — reaches the wrapped byte-string through this
434/// one dispatch, without the pre-lift `.to_string().into()` /
435/// `Cow::Owned(String::from(v))` double-hop that would allocate a
436/// fresh intermediary [`String`] on the way to the same
437/// [`Cow::Owned`] arm.
438///
439/// Deliberately returns [`std::borrow::Cow::Owned`] rather than
440/// [`std::borrow::Cow::Borrowed`] — the substrate-primitive
441/// [`CaixaVersion::as_str`] accessor's return does not carry the
442/// `&'static str` lifetime by construction (the wrapped [`String`]
443/// storage is a runtime heap allocation, not a compile-time literal),
444/// so the [`Cow<'static, str>`] output shape rules out the borrowed
445/// arm and the owned arm is the type-correct projection. Peer of the
446/// paired owned-input [`From<CaixaVersion> for String`] impl on the
447/// same primitive — both route through the wrapper's own heap
448/// allocation via a move on `v.0`, preserving the zero-copy
449/// discipline the substrate opens on its String-wrapper newtype
450/// primitive.
451///
452/// Opens the trait-idiomatic *owned-input, [`Cow<'static, str>`]*
453/// reverse-projection axis on the substrate's core String-wrapper
454/// newtype primitive [`CaixaVersion`], mirroring the paired
455/// [`Cow<'static, str>`] *forward*-projection family the sibling
456/// closed-set fieldless typed enums (via
457/// [`crate::supervisor::RestartStrategy`],
458/// [`crate::supervisor::RestartPolicy`], and the remaining twelve
459/// closed-set enums) already carry — on the enum peers, the paired
460/// axis returns [`Cow::Borrowed`] because the accessor returns
461/// `&'static str`; on this newtype the paired axis returns
462/// [`Cow::Owned`] because the wrapped storage is runtime-allocated.
463/// Rust's standard library does not derive `From<Self> for
464/// Cow<'static, str>` from `From<Self> for String` (nor derive
465/// `From<&Self>` from `From<Self>`), so every newtype that carries a
466/// reverse `From<Self> for String` unwrap axis but not the paired
467/// [`Cow<'static, str>`] axis forces every
468/// [`Cow<'static, str>`]-typed call site through a `.to_string().into()`
469/// double-allocation detour that heap-allocates a fresh intermediary
470/// [`String`] between the wrapper and the [`Cow::Owned`] arm.
471///
472/// Pinned load-bearing by
473/// [`tests::caixa_version_from_into_owned_cow_str_returns_owned_wrapped_body`]
474/// (byte-parity + [`Cow::Owned`]-arm pin against
475/// [`CaixaVersion::as_str`] on the same instance, plus a round-trip
476/// witness through the paired [`From<String> for CaixaVersion`]
477/// constructor) and
478/// [`tests::caixa_version_from_into_owned_cow_str_and_string_agree_on_every_shape`]
479/// (cross-axis partition pin against the paired owned-input
480/// [`From<CaixaVersion> for String`] impl on the same instance,
481/// closing the "owned-input into [`String`] vs. owned-input into
482/// [`Cow<'static, str>`]" bifurcation on the same wrapped body).
483impl From<CaixaVersion> for std::borrow::Cow<'static, str> {
484    fn from(v: CaixaVersion) -> std::borrow::Cow<'static, str> {
485        std::borrow::Cow::Owned(v.0)
486    }
487}
488
489/// Trait-idiomatic *borrowed-input, [`std::borrow::Cow<'static, str>`]
490/// output* reverse projection on the [`CaixaVersion`] newtype
491/// primitive — the borrowed-input companion to the paired owned-input
492/// [`From<CaixaVersion> for std::borrow::Cow<'static, str>`] impl
493/// immediately above. Routes byte-for-byte through the
494/// substrate-primitive [`CaixaVersion::as_str`] `pub const fn`
495/// accessor (via [`str::to_owned`] wrapped in
496/// [`std::borrow::Cow::Owned`]) so every consumer that holds a
497/// borrowed [`&CaixaVersion`] and needs a [`Cow<'static, str>`] —
498/// a `[…].iter().map(Cow::<'static, str>::from).collect::<Vec<_>>()`
499/// per-instance materializer over `&[CaixaVersion]` (whose iterator
500/// yields `&CaixaVersion`, not `CaixaVersion`, so the paired
501/// owned-input [`From<CaixaVersion> for Cow<'static, str>`] axis
502/// alone forces every call site through an explicit `.clone()` /
503/// dereference restatement), a future
504/// `HashMap::<Cow<'static, str>, _>::from_iter` that keys off a
505/// borrowed-iteration axis where cloning the wrapper would allocate
506/// one [`String`] beyond the eventual [`Cow::Owned`] arm's own, a
507/// future generic
508/// `<T: for<'a> Into<Cow<'static, str>>>`-bound emitter on a
509/// per-caixa diagnostic column that walks the
510/// `iter().map(Into::into)` shape verbatim — reaches the wrapped
511/// byte-string through this one dispatch on the substrate primitive.
512///
513/// Deliberately returns [`std::borrow::Cow::Owned`] rather than
514/// [`std::borrow::Cow::Borrowed`] — the substrate-primitive
515/// [`CaixaVersion::as_str`] accessor's return does not carry the
516/// `&'static str` lifetime by construction, so the
517/// [`Cow<'static, str>`] output shape rules out the borrowed arm and
518/// the owned arm is the type-correct projection (mirroring the paired
519/// owned-input impl's own [`Cow::Owned`] discipline). Second corner
520/// on the `{Self, &Self} → Cow<'static, str>` reverse-projection
521/// family opened on the paired owned-input impl immediately above.
522/// Rust's `From` trait does not derive the `From<&Self>` sibling from
523/// a `From<Self>` impl (the blanket
524/// `impl<T, U> From<&T> for U where T: Clone, U: From<T>` does not
525/// exist in `core`), so every newtype that carries the owned-input
526/// reverse [`Cow<'static, str>`] axis but not the borrowed-input axis
527/// forces every borrowed call site through a `.clone()` /
528/// `<Cow<'static, str>>::from(v.clone())` detour whose type bounds
529/// have no compile-time link back to the newtype.
530///
531/// Pinned load-bearing by
532/// [`tests::caixa_version_from_borrowed_into_owned_cow_str_routes_through_as_str_accessor`]
533/// (byte-parity + [`Cow::Owned`]-arm pin against
534/// [`CaixaVersion::as_str`] via a borrowed input, plus a
535/// source-survival witness against silent move-out) and
536/// [`tests::caixa_version_from_owned_and_borrowed_into_cow_str_agree_on_every_shape`]
537/// (cross-axis partition pin against the paired owned-input impl on
538/// the same instance, closing the "owned-input move vs. borrowed-input
539/// clone" bifurcation on the same wrapped body through the
540/// [`Cow<'static, str>`] axis).
541impl From<&CaixaVersion> for std::borrow::Cow<'static, str> {
542    fn from(v: &CaixaVersion) -> std::borrow::Cow<'static, str> {
543        std::borrow::Cow::Owned(v.as_str().to_owned())
544    }
545}
546
547/// Trait-idiomatic *owned-input, [`Box<str>`] output* reverse projection
548/// on the [`CaixaVersion`] newtype primitive — the [`Box<str>`] companion
549/// to the paired owned-input [`From<CaixaVersion> for String`] (999a310)
550/// and [`From<CaixaVersion> for std::borrow::Cow<'static, str>`] (55532e5)
551/// impls on the same primitive. Routes through
552/// [`String::into_boxed_str`]`(v.0)`, shrinking the wrapper's own heap
553/// allocation to a fit-to-length boxed slice — no re-copy of the
554/// per-instance version body's bytes on the fixed-capacity path
555/// (`String::into_boxed_str` reuses the underlying `Vec<u8>` buffer
556/// verbatim when the length matches its capacity; when the [`String`]
557/// carries slack it reallocates once to shrink), so every consumer that
558/// binds a [`CaixaVersion`] through the standard-library `.into()` /
559/// [`From<Self> for Box<str>`] axis reaches the wrapped byte-string
560/// through one substrate-primitive dispatch on the same underlying heap
561/// storage the manifest-parse forward [`From<String> for CaixaVersion`]
562/// constructor accepted.
563///
564/// A future consumer that wants a [`Box<str>`]-typed handle on a
565/// [`CaixaVersion`] — a per-caixa struct field typed `Box<str>` rather
566/// than [`String`] to trim the sixteen-byte length + capacity header
567/// down to eight bytes on the pointer + length pair (a shape the
568/// substrate acknowledges as the natural fixed-length storage for
569/// once-written-never-mutated version strings held across the whole
570/// operator reconciliation cycle), a future
571/// `HashMap::<Box<str>, _>::from_iter([(versao.into(), _)])` per-versao
572/// lookup where the map's key type is [`Box<str>`] rather than owned
573/// [`String`] so the map's per-entry key-slot carries the sixteen-byte
574/// [`Box<str>`] header instead of the twenty-four-byte [`String`]
575/// header, a future M4 admission-webhook rejection body whose per-arm
576/// error-frame composer accepts a [`Box<str>`] intermediate for the
577/// same reason — reaches the wrapped byte-string through this one
578/// dispatch, without the pre-lift `.to_string().into_boxed_str()`
579/// double-hop that would allocate a fresh intermediary [`String`] on
580/// the way to the same [`Box<str>`] slot.
581///
582/// Peer of the paired owned-input [`From<CaixaVersion> for String`]
583/// (999a310) and [`From<CaixaVersion> for Cow<'static, str>`] (55532e5)
584/// impls on the same primitive — all three route through `v.0`
585/// (the [`String`] axis returns the wrapped buffer verbatim; the
586/// [`Cow<'static, str>`] axis wraps it in [`Cow::Owned`]; this axis
587/// shrinks it to a fit-to-length boxed slice via [`String::into_boxed_str`]),
588/// preserving the zero-copy discipline the substrate opens on its
589/// String-wrapper newtype primitive across the three reverse-projection
590/// axes. Rust's standard library does not derive `From<Self> for
591/// Box<str>` from `From<Self> for String` (nor from `From<Self> for
592/// Cow<'static, str>`), so every newtype that carries the paired
593/// reverse `From<Self> for String` axis but not the paired
594/// [`Box<str>`] axis forces every [`Box<str>`]-typed call site through
595/// a `.to_string().into_boxed_str()` double-allocation detour that
596/// heap-allocates a fresh intermediary [`String`] between the wrapper
597/// and the [`Box<str>`] slot.
598///
599/// Opens the trait-idiomatic *owned-input, [`Box<str>`]*
600/// reverse-projection axis on the substrate's core String-wrapper
601/// newtype primitive [`CaixaVersion`], extending the reverse-projection
602/// matrix from the two axes already opened on this primitive (999a310
603/// on the [`String`] axis, 55532e5 on the [`Cow<'static, str>`] axis)
604/// onto the third. The fourth and final axis on the matrix
605/// ([`std::sync::Arc<str>`]) is closed by the sibling paired
606/// [`From<CaixaVersion> for std::sync::Arc<str>`] +
607/// [`From<&CaixaVersion> for std::sync::Arc<str>`] impls immediately below.
608///
609/// Pinned load-bearing by
610/// [`tests::caixa_version_from_into_owned_box_str_returns_wrapped_body`]
611/// (byte-parity pin against [`CaixaVersion::as_str`] on the same
612/// instance, plus a round-trip witness through the paired
613/// [`From<String> for CaixaVersion`] constructor closing the two-way
614/// `Self → Box<str> → Self` cycle by construction) and
615/// [`tests::caixa_version_from_into_owned_box_str_and_string_agree_on_every_shape`]
616/// (cross-axis partition pin against the paired owned-input
617/// [`From<CaixaVersion> for String`] and
618/// [`From<CaixaVersion> for Cow<'static, str>`] impls on the same
619/// instance, closing the "owned-input into [`String`] vs. owned-input
620/// into [`Cow<'static, str>`] vs. owned-input into [`Box<str>`]"
621/// three-corner bifurcation on the same wrapped body).
622impl From<CaixaVersion> for Box<str> {
623    fn from(v: CaixaVersion) -> Box<str> {
624        v.0.into_boxed_str()
625    }
626}
627
628/// Trait-idiomatic *borrowed-input, [`Box<str>`] output* reverse
629/// projection on the [`CaixaVersion`] newtype primitive — the
630/// borrowed-input companion to the paired owned-input
631/// [`From<CaixaVersion> for Box<str>`] impl immediately above. Routes
632/// byte-for-byte through the substrate-primitive
633/// [`CaixaVersion::as_str`] `pub const fn` accessor (via
634/// [`Box::<str>::from`]`(&str)`, which allocates a fit-to-length boxed
635/// slice from the borrowed `&str` in one heap allocation without an
636/// intermediary [`String`]) so every consumer that holds a borrowed
637/// [`&CaixaVersion`] and needs a [`Box<str>`] — a
638/// `[…].iter().map(Box::<str>::from).collect::<Vec<_>>()` per-instance
639/// materializer over `&[CaixaVersion]` (whose iterator yields
640/// `&CaixaVersion`, not `CaixaVersion`, so the paired owned-input
641/// [`From<CaixaVersion> for Box<str>`] axis alone forces every call
642/// site through an explicit `.clone()` / dereference restatement), a
643/// future `HashMap::<Box<str>, _>::from_iter` that keys off a
644/// borrowed-iteration axis, a future generic
645/// `<T: for<'a> Into<Box<str>>>`-bound emitter on a per-caixa
646/// diagnostic column that walks the `iter().map(Into::into)` shape
647/// verbatim — reaches the wrapped byte-string through this one dispatch
648/// on the substrate primitive.
649///
650/// Second corner on the `{Self, &Self} → Box<str>` reverse-projection
651/// family opened on the paired owned-input impl immediately above.
652/// Rust's `From` trait does not derive the `From<&Self>` sibling from
653/// a `From<Self>` impl (the blanket
654/// `impl<T, U> From<&T> for U where T: Clone, U: From<T>` does not
655/// exist in `core`), so every newtype that carries the owned-input
656/// reverse [`Box<str>`] axis but not the borrowed-input axis forces
657/// every borrowed call site through a `.clone()` /
658/// `<Box<str>>::from(v.clone())` detour whose type bounds have no
659/// compile-time link back to the newtype.
660///
661/// Pinned load-bearing by
662/// [`tests::caixa_version_from_borrowed_into_owned_box_str_routes_through_as_str_accessor`]
663/// (byte-parity pin against [`CaixaVersion::as_str`] via a borrowed
664/// input, plus a source-survival witness against silent move-out) and
665/// [`tests::caixa_version_from_owned_and_borrowed_into_box_str_agree_on_every_shape`]
666/// (cross-corner partition pin between owned-input move and
667/// borrowed-input clone on the same wrapped body through the
668/// [`Box<str>`] axis).
669impl From<&CaixaVersion> for Box<str> {
670    fn from(v: &CaixaVersion) -> Box<str> {
671        Box::<str>::from(v.as_str())
672    }
673}
674
675/// Trait-idiomatic *owned-input, [`std::sync::Arc<str>`] output* reverse
676/// projection on the [`CaixaVersion`] newtype primitive — the
677/// [`std::sync::Arc<str>`] companion to the paired owned-input
678/// [`From<CaixaVersion> for String`] (999a310),
679/// [`From<CaixaVersion> for std::borrow::Cow<'static, str>`] (55532e5),
680/// and [`From<CaixaVersion> for Box<str>`] (32d861a) impls on the same
681/// primitive. Routes through [`std::sync::Arc::<str>::from`]`(v.0)`,
682/// which allocates a fresh atomically-refcounted heap slab whose data
683/// slot byte-equals the wrapper's own [`String`] storage — the wrapped
684/// bytes move through by value into the `Arc<str>` layout in one heap
685/// allocation (the [`std::sync::Arc<str>`] layout carries a strong
686/// count + weak count header ahead of the byte slice, so a copy is
687/// required regardless of the input axis; no intermediary [`String`]
688/// or [`Box<str>`] is materialized on the owned-input path).
689///
690/// A future consumer that wants a [`std::sync::Arc<str>`]-typed handle
691/// on a [`CaixaVersion`] — a share-through-clone version body held
692/// across a per-caixa `caixa-operator` reconcile task where every
693/// spawn point wants a cheap `.clone()` on the version handle without
694/// each task re-allocating its own [`String`] copy (the
695/// [`std::sync::Arc::clone`] path bumps the atomic refcount in place
696/// and returns a pointer-width handle), a future
697/// `HashMap::<std::sync::Arc<str>, _>::from_iter` per-versao lookup
698/// where the map's key type is [`std::sync::Arc<str>`] so the same
699/// version-body pointer can key both the map and the payload without a
700/// second heap allocation, a future M4 admission-webhook decoder that
701/// materializes decoded version strings as [`std::sync::Arc<str>`]
702/// slices so downstream verdict-composer tasks running on separate
703/// worker threads can share the immutable body without a
704/// per-consumer [`String::clone`] — reaches the wrapped byte-string
705/// through this one dispatch, without the pre-lift
706/// `.to_string().into::<std::sync::Arc<str>>()` double-hop that would
707/// still allocate the same [`Arc<str>`] slab plus one intermediary
708/// [`String`] between the wrapper and the [`std::sync::Arc<str>`] slot.
709///
710/// Peer of the paired owned-input [`From<CaixaVersion> for String`]
711/// (999a310), [`From<CaixaVersion> for Cow<'static, str>`] (55532e5),
712/// and [`From<CaixaVersion> for Box<str>`] (32d861a) impls on the same
713/// primitive — all four route through `v.0` (the [`String`] axis
714/// returns the wrapped buffer verbatim; the [`Cow<'static, str>`] axis
715/// wraps it in [`Cow::Owned`]; the [`Box<str>`] axis shrinks it to a
716/// fit-to-length boxed slice; this axis copies the bytes into a fresh
717/// atomically-refcounted slab whose header carries the atomic strong +
718/// weak counters the [`std::sync::Arc<str>`] layout requires),
719/// preserving the substrate's single-dispatch reverse-projection
720/// discipline across the four axes. Rust's standard library does not
721/// derive `From<Self> for Arc<str>` from `From<Self> for String` (nor
722/// from `From<Self> for Box<str>` or `From<Self> for Cow<'static, str>`),
723/// so every newtype that carries the paired reverse `From<Self> for
724/// String` / `Box<str>` / `Cow<'static, str>` axes but not the paired
725/// [`std::sync::Arc<str>`] axis forces every
726/// [`std::sync::Arc<str>`]-typed call site through a
727/// `.to_string().into()` / `Arc::<str>::from(v.to_string())`
728/// double-allocation detour that heap-allocates a fresh intermediary
729/// [`String`] between the wrapper and the [`std::sync::Arc<str>`] slot.
730///
731/// Closes the trait-idiomatic *owned-input, [`std::sync::Arc<str>`]*
732/// reverse-projection axis on the substrate's core String-wrapper
733/// newtype primitive [`CaixaVersion`], completing the reverse-projection
734/// matrix on this primitive across the full `{String, Cow<'static, str>,
735/// Box<str>, Arc<str>}` roster — the fourth and final axis (999a310 on
736/// the [`String`] axis, 55532e5 on the [`Cow<'static, str>`] axis,
737/// 32d861a on the [`Box<str>`] axis, this axis on the
738/// [`std::sync::Arc<str>`] axis).
739///
740/// Pinned load-bearing by
741/// [`tests::caixa_version_from_into_owned_arc_str_returns_wrapped_body`]
742/// (byte-parity pin against [`CaixaVersion::as_str`] on the same
743/// instance, plus a round-trip witness through the paired
744/// [`From<String> for CaixaVersion`] constructor closing the two-way
745/// `Self → Arc<str> → Self` cycle by construction) and
746/// [`tests::caixa_version_from_into_owned_arc_str_and_string_agree_on_every_shape`]
747/// (cross-axis partition pin against the paired owned-input
748/// [`From<CaixaVersion> for String`], [`From<CaixaVersion> for Cow<'static, str>`],
749/// and [`From<CaixaVersion> for Box<str>`] impls on the same instance,
750/// closing the four-corner "owned-input into `String` vs. `Cow<'static, str>`
751/// vs. `Box<str>` vs. `Arc<str>`" partition on the same wrapped body).
752impl From<CaixaVersion> for std::sync::Arc<str> {
753    fn from(v: CaixaVersion) -> std::sync::Arc<str> {
754        std::sync::Arc::<str>::from(v.0)
755    }
756}
757
758/// Trait-idiomatic *borrowed-input, [`std::sync::Arc<str>`] output*
759/// reverse projection on the [`CaixaVersion`] newtype primitive — the
760/// borrowed-input companion to the paired owned-input
761/// [`From<CaixaVersion> for std::sync::Arc<str>`] impl immediately
762/// above. Routes byte-for-byte through the substrate-primitive
763/// [`CaixaVersion::as_str`] `pub const fn` accessor (via
764/// [`std::sync::Arc::<str>::from`]`(&str)`, which allocates a fresh
765/// atomically-refcounted heap slab from the borrowed `&str` in one
766/// heap allocation without an intermediary [`String`] or [`Box<str>`])
767/// so every consumer that holds a borrowed [`&CaixaVersion`] and needs
768/// a [`std::sync::Arc<str>`] — a
769/// `[…].iter().map(std::sync::Arc::<str>::from).collect::<Vec<_>>()`
770/// per-instance materializer over `&[CaixaVersion]` (whose iterator
771/// yields `&CaixaVersion`, not `CaixaVersion`, so the paired
772/// owned-input [`From<CaixaVersion> for std::sync::Arc<str>`] axis
773/// alone forces every call site through an explicit `.clone()` /
774/// dereference restatement), a future
775/// `HashMap::<std::sync::Arc<str>, _>::from_iter` that keys off a
776/// borrowed-iteration axis, a future generic
777/// `<T: for<'a> Into<std::sync::Arc<str>>>`-bound emitter on a
778/// per-caixa diagnostic column that walks the
779/// `iter().map(Into::into)` shape verbatim — reaches the wrapped
780/// byte-string through this one dispatch on the substrate primitive.
781///
782/// Second corner on the `{Self, &Self} → std::sync::Arc<str>`
783/// reverse-projection family opened on the paired owned-input impl
784/// immediately above. Rust's `From` trait does not derive the
785/// `From<&Self>` sibling from a `From<Self>` impl (the blanket
786/// `impl<T, U> From<&T> for U where T: Clone, U: From<T>` does not
787/// exist in `core`), so every newtype that carries the owned-input
788/// reverse [`std::sync::Arc<str>`] axis but not the borrowed-input
789/// axis forces every borrowed call site through a `.clone()` /
790/// `<std::sync::Arc<str>>::from(v.clone())` detour whose type bounds
791/// have no compile-time link back to the newtype.
792///
793/// Pinned load-bearing by
794/// [`tests::caixa_version_from_borrowed_into_owned_arc_str_routes_through_as_str_accessor`]
795/// (byte-parity pin against [`CaixaVersion::as_str`] via a borrowed
796/// input, plus a source-survival witness against silent move-out) and
797/// [`tests::caixa_version_from_owned_and_borrowed_into_arc_str_agree_on_every_shape`]
798/// (cross-corner partition pin between owned-input move and
799/// borrowed-input clone on the same wrapped body through the
800/// [`std::sync::Arc<str>`] axis).
801impl From<&CaixaVersion> for std::sync::Arc<str> {
802    fn from(v: &CaixaVersion) -> std::sync::Arc<str> {
803        std::sync::Arc::<str>::from(v.as_str())
804    }
805}
806
807/// Trait-idiomatic *owned-input, [`std::rc::Rc<str>`] output* reverse
808/// projection on the [`CaixaVersion`] newtype primitive — the owned-heap-
809/// string, single-threaded-reference-counted inverse of the pre-existing
810/// [`From<String> for CaixaVersion`] / [`From<&str> for CaixaVersion`]
811/// forward-projection pair on this primitive. Consumes the owned wrapper
812/// by value, moves the wrapped [`String`] into the [`std::rc::Rc<str>`]
813/// layout in one heap allocation (the [`std::rc::Rc<str>`] layout carries
814/// a strong count + weak count header ahead of the byte slice, so the copy
815/// is required regardless of the input axis; no intermediary [`String`] or
816/// [`Box<str>`] is materialized on the owned-input path) — the exact
817/// single-threaded mirror of the paired
818/// [`From<CaixaVersion> for std::sync::Arc<str>`] impl (3e67756) on the
819/// atomically-refcounted axis.
820///
821/// A future consumer that wants a [`std::rc::Rc<str>`]-typed handle on a
822/// [`CaixaVersion`] — a per-`feira` verb's single-threaded diagnostic
823/// composer that clones the version body across a chain of Nord-themed
824/// column emitters without paying either the [`String::clone`]
825/// full-allocation cost (every step re-allocates its own buffer) or the
826/// atomic-refcount overhead the paired [`std::sync::Arc<str>`] axis
827/// forces (the [`std::rc::Rc::clone`] path bumps a non-atomic refcount in
828/// place and returns a pointer-width handle, cheaper than the paired
829/// atomic increment on the sibling [`std::sync::Arc<str>`] axis by a
830/// measurable margin on hot single-threaded call sites), a future single-
831/// threaded `HashMap::<std::rc::Rc<str>, _>::from_iter` per-versao lookup
832/// where the map's key type is [`std::rc::Rc<str>`] so the same version-
833/// body pointer can key both the map and the payload without a second heap
834/// allocation, a future `feira lint` per-caixa diagnostic table whose
835/// per-column `Cell<std::rc::Rc<str>>` payload carries the version body
836/// across the row-composer + column-composer + wrapper phases through the
837/// pointer-width handle rather than a [`String`] per phase — reaches the
838/// wrapped byte-string through this one dispatch, without the pre-lift
839/// `.to_string().into::<std::rc::Rc<str>>()` double-hop that would still
840/// allocate the same [`Rc<str>`] slab plus one intermediary [`String`]
841/// between the wrapper and the [`std::rc::Rc<str>`] slot.
842///
843/// Peer of the paired owned-input [`From<CaixaVersion> for String`]
844/// (999a310), [`From<CaixaVersion> for Cow<'static, str>`] (55532e5),
845/// [`From<CaixaVersion> for Box<str>`] (32d861a), and
846/// [`From<CaixaVersion> for std::sync::Arc<str>`] (3e67756) impls on the
847/// same primitive — all five route through `v.0` (the [`String`] axis
848/// returns the wrapped buffer verbatim; the [`Cow<'static, str>`] axis
849/// wraps it in [`Cow::Owned`]; the [`Box<str>`] axis shrinks it to a
850/// fit-to-length boxed slice; the [`Arc<str>`] axis copies the bytes into
851/// a fresh atomically-refcounted slab; this axis copies the bytes into a
852/// fresh single-threaded-refcounted slab whose header carries the non-
853/// atomic strong + weak counters the [`std::rc::Rc<str>`] layout
854/// requires), preserving the substrate's single-dispatch reverse-
855/// projection discipline across the five axes. Rust's standard library
856/// does not derive `From<Self> for Rc<str>` from `From<Self> for Arc<str>`
857/// (the [`std::sync::Arc<str>`] and [`std::rc::Rc<str>`] layouts share the
858/// same on-disk shape but the trait tables are disjoint, and no blanket
859/// `impl<T> From<T> for Rc<str> where Arc<str>: From<T>` exists in
860/// `core`), so every newtype that carries the paired
861/// [`std::sync::Arc<str>`] axis but not the paired [`std::rc::Rc<str>`]
862/// axis forces every single-threaded [`std::rc::Rc<str>`]-typed call site
863/// through a `.to_string().into()` / `Rc::<str>::from(v.to_string())`
864/// double-allocation detour that heap-allocates a fresh intermediary
865/// [`String`] between the wrapper and the [`std::rc::Rc<str>`] slot.
866///
867/// Extends the trait-idiomatic *owned-input* reverse-projection matrix on
868/// the substrate's core String-wrapper newtype primitive [`CaixaVersion`]
869/// onto the single-threaded reference-counted axis — the fifth axis
870/// (999a310 on [`String`], 55532e5 on [`Cow<'static, str>`], 32d861a on
871/// [`Box<str>`], 3e67756 on [`std::sync::Arc<str>`], this axis on
872/// [`std::rc::Rc<str>`]).
873///
874/// Pinned load-bearing by
875/// [`tests::caixa_version_from_into_owned_rc_str_returns_wrapped_body`]
876/// (byte-parity pin against [`CaixaVersion::as_str`] on the same instance,
877/// plus a round-trip witness through the paired [`From<String> for
878/// CaixaVersion`] constructor closing the two-way `Self → Rc<str> → Self`
879/// cycle by construction) and
880/// [`tests::caixa_version_from_into_owned_rc_str_and_arc_str_agree_on_every_shape`]
881/// (cross-axis partition pin against the paired owned-input
882/// [`From<CaixaVersion> for String`],
883/// [`From<CaixaVersion> for Cow<'static, str>`],
884/// [`From<CaixaVersion> for Box<str>`], and
885/// [`From<CaixaVersion> for std::sync::Arc<str>`] impls on the same
886/// instance, closing the five-corner "owned-input into `String` vs.
887/// `Cow<'static, str>` vs. `Box<str>` vs. `Arc<str>` vs. `Rc<str>`"
888/// partition on the same wrapped body).
889impl From<CaixaVersion> for std::rc::Rc<str> {
890    fn from(v: CaixaVersion) -> std::rc::Rc<str> {
891        std::rc::Rc::<str>::from(v.0)
892    }
893}
894
895/// Trait-idiomatic *borrowed-input, [`std::rc::Rc<str>`] output* reverse
896/// projection on the [`CaixaVersion`] newtype primitive — the borrowed-
897/// input companion to the paired owned-input
898/// [`From<CaixaVersion> for std::rc::Rc<str>`] impl immediately above.
899/// Routes byte-for-byte through the substrate-primitive
900/// [`CaixaVersion::as_str`] `pub const fn` accessor (via
901/// [`std::rc::Rc::<str>::from`]`(&str)`, which allocates a fresh
902/// single-threaded-refcounted heap slab from the borrowed `&str` in one
903/// heap allocation without an intermediary [`String`] or [`Box<str>`]) so
904/// every consumer that holds a borrowed [`&CaixaVersion`] and needs a
905/// [`std::rc::Rc<str>`] — a
906/// `[…].iter().map(std::rc::Rc::<str>::from).collect::<Vec<_>>()`
907/// per-instance materializer over `&[CaixaVersion]` (whose iterator yields
908/// `&CaixaVersion`, not `CaixaVersion`, so the paired owned-input
909/// [`From<CaixaVersion> for std::rc::Rc<str>`] axis alone forces every
910/// call site through an explicit `.clone()` / dereference restatement), a
911/// future single-threaded `HashMap::<std::rc::Rc<str>, _>::from_iter` that
912/// keys off a borrowed-iteration axis, a future generic
913/// `<T: for<'a> Into<std::rc::Rc<str>>>`-bound emitter on a per-caixa
914/// diagnostic column that walks the `iter().map(Into::into)` shape
915/// verbatim — reaches the wrapped byte-string through this one dispatch on
916/// the substrate primitive.
917///
918/// Second corner on the `{Self, &Self} → std::rc::Rc<str>` reverse-
919/// projection family opened on the paired owned-input impl immediately
920/// above. Rust's `From` trait does not derive the `From<&Self>` sibling
921/// from a `From<Self>` impl (the blanket `impl<T, U> From<&T> for U where
922/// T: Clone, U: From<T>` does not exist in `core`), so every newtype that
923/// carries the owned-input reverse [`std::rc::Rc<str>`] axis but not the
924/// borrowed-input axis forces every borrowed call site through a
925/// `.clone()` / `<std::rc::Rc<str>>::from(v.clone())` detour whose type
926/// bounds have no compile-time link back to the newtype.
927///
928/// Pinned load-bearing by
929/// [`tests::caixa_version_from_borrowed_into_owned_rc_str_routes_through_as_str_accessor`]
930/// (byte-parity pin against [`CaixaVersion::as_str`] via a borrowed input,
931/// plus a source-survival witness against silent move-out) and
932/// [`tests::caixa_version_from_owned_and_borrowed_into_rc_str_agree_on_every_shape`]
933/// (cross-corner partition pin between owned-input move and borrowed-
934/// input clone on the same wrapped body through the [`std::rc::Rc<str>`]
935/// axis).
936impl From<&CaixaVersion> for std::rc::Rc<str> {
937    fn from(v: &CaixaVersion) -> std::rc::Rc<str> {
938        std::rc::Rc::<str>::from(v.as_str())
939    }
940}
941
942/// Canonical Zig-style git-tag prefix every `feira publish` run writes
943/// and every downstream consumer of a published caixa reads. A caixa
944/// published at `:versao "0.1.0"` lands as a git tag `v0.1.0` on the
945/// source repo's `origin` remote — the [`crate::CaixaVersion`] value
946/// gates the version body, this constant gates the prefix the body
947/// composes under.
948///
949/// Two production-code consumers carry this prefix on the same git
950/// remote axis:
951///
952/// 1. [`caixa-feira`]'s `feira publish` verb (caixa-feira/src/cmd/publish.rs)
953///    — the writer. Its `--prefix` clap flag defaults to this string
954///    and the verb computes the tag as `format!("{prefix}{versao}")`
955///    before `git tag -a <tag>` + `git push origin <tag>`.
956/// 2. [`caixa-flux`]'s [`caixa-flux::cluster_bundle`] renderer
957///    (caixa-flux/src/lib.rs) — the reader. Its
958///    `ClusterBundleOpts::for_caixa` constructor defaults
959///    `git_ref: GitRefSpec::Tag(...)` to `<prefix><versao>` so the
960///    rendered `gitrepository.yaml` carries `ref: { tag: v<versao> }`
961///    pointing `FluxCD`'s `GitRepository` reconciler at the exact tag
962///    the publisher just wrote.
963///
964/// Until this lift landed both consumers carried the bare `"v"` byte
965/// inline — `caixa-feira/src/cmd/publish.rs:22`'s clap
966/// `default_value = "v"` and `caixa-flux/src/lib.rs:335`'s
967/// `format!("v{}", caixa.versao)` literal. A future Zig-style-tag
968/// convention rebrand (the substrate moving to plain `<versao>` tags
969/// once the GitHub releases UI normalizes around the bare form, to
970/// `release/<versao>` once a sibling forge convention adopts the
971/// `<type>/<value>` slash-namespaced shape, or to a per-edition
972/// override the operator pins through a future `:placement
973/// :tag-prefix` slot) without a coordinated edit on both sides would
974/// silently emit a `feira publish`-side tag at one shape (e.g.
975/// `release/0.1.0`) and a `cluster_bundle`-side `ref: { tag: v0.1.0 }`
976/// pointing at the prior shape — Flux's `GitRepository` reconciler
977/// would loop forever looking for an upstream `v0.1.0` ref the publish
978/// remote no longer carries, the dependent `HelmRelease`'s `chart:
979/// sourceRef` would never resolve, every per-Servico apply would
980/// silently come up with the prior reconciled state, and the failure
981/// would surface at `kubectl describe gitrepository` time (the
982/// `Status: Stalled` / `Reason: Failed` arm) far from the rebrand
983/// commit's source.
984///
985/// Lifting the literal to one `&'static str` constant closes the drift
986/// footgun structurally — both consumers read from the same memory,
987/// so any future rebrand reaches both sites by construction and a CI
988/// build that re-introduces a sibling inline `"v"` literal trips the
989/// peer pinning tests
990/// ([`caixa-feira`]'s `publish_prefix_default_pins_lifted_caixa_core_constant`,
991/// [`caixa-flux`]'s `cluster_bundle_default_git_tag_uses_lifted_caixa_core_prefix`)
992/// at the build-time fail-before-deploy posture every prior
993/// load-bearing-string lift on this surface
994/// ([`crate::DEFAULT_NAMESPACE`] a085b26,
995/// [`crate::DEFAULT_LIBRARY_NAME`] 41438dc,
996/// [`crate::DEFAULT_SERVICO_PORT`] 1e22add) establishes.
997///
998/// Authoring-side `:versao` gates already refuse the `"v"`-prefixed
999/// publish tag shape leaking back into a version body — every typed
1000/// `:versao` surface (top-level `:versao`, `:upgrade-from :from`,
1001/// `:deps :versao`, `:deps-dev :versao`, `:membros :versao`,
1002/// `:children :versao`) routes through `semver::Version::parse` /
1003/// [`parse_requirement`], both of which reject the `v`-prefix as
1004/// invalid `SemVer`. The split — bare `SemVer` at the `:versao` slot,
1005/// `v<versao>` at the published git-tag axis — is the convention this
1006/// constant pins.
1007pub const DEFAULT_PUBLISH_TAG_PREFIX: &str = "v";
1008
1009/// Canonical git remote name every `feira` writer-side verb pushes to —
1010/// the destination handle the operator-out-of-the-loop publish + deploy
1011/// chain (`feira publish`, `feira deploy --apply`, `feira app deploy
1012/// --apply`) names when it invokes `git push <remote> <ref>` against
1013/// the local clone of the source / k8s GitOps repo.
1014///
1015/// Three production-code consumers carry this remote name on the same
1016/// `git push` axis:
1017///
1018/// 1. [`caixa-feira`]'s `feira publish` verb (caixa-feira/src/cmd/publish.rs)
1019///    — the writer-side publish path. Its `--remote` clap flag defaults
1020///    to this string and the verb runs `git push <remote> <tag>` to push
1021///    the freshly written `v<versao>` tag upstream.
1022/// 2. [`caixa-feira`]'s `feira deploy --apply` verb
1023///    (caixa-feira/src/cmd/deploy.rs) — the writer-side Servico cluster-
1024///    deploy path. Its `push_origin` helper runs `git push origin HEAD`
1025///    against the k8s GitOps repo's working tree after upserting the
1026///    Servico's entry into the cluster's lareira-fleet-programs
1027///    HelmRelease values.
1028/// 3. [`caixa-feira`]'s `feira app deploy --apply` verb
1029///    (caixa-feira/src/cmd/app.rs) — the writer-side Aplicacao
1030///    cluster-deploy path. Its `push_origin` helper runs the same
1031///    `git push origin HEAD` against the k8s GitOps repo after writing
1032///    the rendered multi-doc YAML (programs.yaml entries + Cilium
1033///    NetworkPolicies + Gateway/HTTPRoute) to the cluster's tree.
1034///
1035/// Until this lift landed all three consumers carried the bare
1036/// `"origin"` byte inline — `publish.rs`'s clap `default_value = "origin"`,
1037/// `deploy.rs`'s `git(repo, ["push", "origin", "HEAD"])`, and
1038/// `app.rs`'s `git(repo, ["push", "origin", "HEAD"])`. A future
1039/// remote-naming-convention rebrand on any one side (the substrate
1040/// moving to `upstream` for forge-mirror clusters, to a per-tenant
1041/// remote naming convention once the operator-flux pipeline grows the
1042/// `:placement :remote` slot, or to the canonical multi-remote
1043/// `release` + `mirror` split every Erlang/OTP `release_handler` /
1044/// `relup` shop converges on once their git surface grows past one
1045/// upstream) without a coordinated edit on the other two would have
1046/// silently emitted a `git push` against a remote that doesn't exist
1047/// on the operator's clone (`fatal: '<remote>' does not appear to be
1048/// a git repository`) on one writer verb while the other two still
1049/// pushed to the old remote — operator-observed symptom: the publish
1050/// landed but the deploy didn't, or vice-versa, with the failure
1051/// surfacing as a partial-state rollout far from the rebrand commit's
1052/// source.
1053///
1054/// Lifting the literal to one `&'static str` constant closes the drift
1055/// footgun structurally — all three consumers read from the same
1056/// memory, so any future remote-naming rebrand reaches every writer
1057/// verb by construction and a CI build that re-introduces a sibling
1058/// inline `"origin"` literal trips the peer pinning tests
1059/// ([`caixa-feira`]'s `publish_remote_default_pins_lifted_caixa_core_constant`
1060/// on the clap-default axis, the sibling structural pins on the two
1061/// `push_origin` helpers) at the build-time fail-before-deploy
1062/// posture every prior load-bearing-string lift on this surface
1063/// ([`crate::DEFAULT_NAMESPACE`] a085b26, [`crate::DEFAULT_LIBRARY_NAME`]
1064/// 41438dc, [`crate::DEFAULT_SERVICO_PORT`] 1e22add,
1065/// [`crate::DEFAULT_PUBLISH_TAG_PREFIX`] 0a6a602,
1066/// [`crate::DEFAULT_FLUX_SYSTEM_NAMESPACE`] 7197d38) establishes.
1067///
1068/// Pairs with [`DEFAULT_PUBLISH_TAG_PREFIX`] on the same git remote
1069/// axis — `feira publish` runs `git push <DEFAULT_GIT_REMOTE>
1070/// <DEFAULT_PUBLISH_TAG_PREFIX><versao>` to push the typed `:versao`
1071/// body composed under the canonical prefix to the canonical remote.
1072/// Both halves of the publish-side convention now live in one place.
1073pub const DEFAULT_GIT_REMOTE: &str = "origin";
1074
1075/// Canonical GitHub org name the pleme-io substrate defaults every un-
1076/// pinned caixa's source repo to — the org handle the two substrate-side
1077/// "no `:repositorio` / no `:fonte` declared, fall back to the canonical
1078/// org" paths compose their `github:<org>/<nome>` shorthand + full
1079/// `https://github.com/<org>/<nome>` URL under.
1080///
1081/// Two production-code consumers carry this org name on the same
1082/// canonical-substrate-default-git-org axis:
1083///
1084/// 1. [`caixa-feira`]'s `feira lock` verb's `resolve_stub` (caixa-feira/src/cmd/lock.rs)
1085///    — the resolver-side default. When a declared dep has no
1086///    `:fonte` block the stub resolver composes
1087///    `caixa_core::DepSource::default_github(<org>, &dep.nome)` to fill
1088///    the shorthand `github:<org>/<nome>` fallback the phase 1.B
1089///    `feira resolve` walker will resolve against upstream.
1090/// 2. [`caixa-flux`]'s [`caixa-flux::cluster_bundle`] renderer
1091///    (caixa-flux/src/lib.rs) — the renderer-side default. Its
1092///    `ClusterBundleOpts::for_caixa` constructor defaults
1093///    `git_url` to `format!("https://github.com/{org}/{}", caixa.nome)`
1094///    when the caixa carries no `:repositorio`, so the rendered
1095///    `gitrepository.yaml` points `FluxCD`'s `GitRepository`
1096///    reconciler at the substrate's canonical git host for un-pinned
1097///    caixas.
1098///
1099/// Until this lift landed both consumers carried the bare `"pleme-io"`
1100/// byte inline — `caixa-feira/src/cmd/lock.rs:61`'s
1101/// `default_github("pleme-io", …)` call and `caixa-flux/src/lib.rs`'s
1102/// `format!("https://github.com/pleme-io/{}", …)` literal. A future
1103/// substrate-side git-org migration (the pleme-io org renaming to a
1104/// short form, forking to a per-tenant `<org>-<tenant>` shape once the
1105/// operator-flux pipeline grows a `:placement :org` slot, or moving to
1106/// a self-hosted forge under a wholly-owned org name once the
1107/// substrate's forge-gen roadmap graduates past GitHub) without a
1108/// coordinated edit on both sides would silently emit a `feira lock`-
1109/// side `github:<old-org>/<nome>` fallback shorthand while the
1110/// `cluster_bundle`-side `gitrepository.yaml` pointed at the new org's
1111/// `<nome>` — the phase 1.B `feira resolve` walker would probe the
1112/// prior org's git host for a repo that migrated with the org, or vice-
1113/// versa: Flux's `GitRepository` reconciler would loop forever looking
1114/// for an upstream repo the old org handle no longer maps to, the
1115/// dependent `HelmRelease`'s `chart: sourceRef` would never resolve,
1116/// every per-Servico apply would silently come up with the prior
1117/// reconciled state, and the failure would surface at `kubectl describe
1118/// gitrepository` time (the `Status: Stalled` / `Reason: Failed` arm)
1119/// far from the org-migration commit's source.
1120///
1121/// Lifting the literal to one `&'static str` constant closes the drift
1122/// footgun structurally — both consumers read from the same memory, so
1123/// any future org migration reaches both sites by construction and a CI
1124/// build that re-introduces a sibling inline `"pleme-io"` literal trips
1125/// the peer pinning tests at the build-time fail-before-deploy posture
1126/// every prior load-bearing-string lift on this surface
1127/// ([`crate::DEFAULT_NAMESPACE`] a085b26,
1128/// [`crate::DEFAULT_LIBRARY_NAME`] 41438dc,
1129/// [`crate::DEFAULT_SERVICO_PORT`] 1e22add,
1130/// [`DEFAULT_PUBLISH_TAG_PREFIX`] 0a6a602,
1131/// [`DEFAULT_GIT_REMOTE`],
1132/// [`crate::DEFAULT_FLUX_SYSTEM_NAMESPACE`] 7197d38) establishes.
1133///
1134/// Distinct from the [`crate::PLEME_LABEL_PREFIX`] canonical pleme-io
1135/// label-namespace prefix (`"pleme.pleme.io"`, the K8s label-namespace
1136/// axis every substrate-emitted cluster object's `LABEL_APLICACAO` /
1137/// `LABEL_PROGRAM` / `LABEL_CONTRATO` axis shares) — these constants
1138/// sit on separate schema-contract surfaces (the git-host org handle
1139/// vs. the K8s label-namespace prefix) governed by independent rebrand
1140/// cycles, so a git-org rename must not couple the K8s label-namespace
1141/// axis to the git-host axis (or vice-versa). Splitting the two lets
1142/// each schema's future rebrand land independently at its canonical
1143/// const definition without silently coupling the surfaces — same
1144/// "byte-distinct, semantically distinct" discipline the
1145/// [`crate::PLEME_LABEL_PREFIX`] / [`crate::LABEL_APLICACAO`] /
1146/// [`crate::LABEL_PROGRAM`] / [`crate::LABEL_CONTRATO`] set establishes
1147/// on the peer per-K8s-label-namespace canonical-string surface.
1148pub const DEFAULT_PLEME_GIT_ORG: &str = "pleme-io";
1149
1150/// Parse a dep's `:versao` string as a [`semver::VersionReq`].
1151///
1152/// Treats the literal `"*"` as "any version" (semver's wildcard).
1153pub fn parse_requirement(s: &str) -> Result<semver::VersionReq, VersionError> {
1154    if s == "*" {
1155        return Ok(semver::VersionReq::STAR);
1156    }
1157    semver::VersionReq::parse(s).map_err(|e| VersionError::requirement(s, e.to_string()))
1158}
1159
1160#[derive(Debug, Error, PartialEq, Eq)]
1161pub enum VersionError {
1162    #[error("invalid version '{0}': {1}")]
1163    Semver(String, String),
1164    #[error("invalid version requirement '{0}': {1}")]
1165    Requirement(String, String),
1166}
1167
1168// Fold the sole `VersionError::Semver(<into-String-expr>, <into-String-expr>)`
1169// wire-up site on [`CaixaVersion::parse`]'s [`semver::Version::parse`]
1170// `map_err` arm onto one substrate primitive — the paired
1171// `(String, String)` two-slot tuple-newtype [`VersionError::Semver`] on
1172// the [`CaixaVersion`] parser surface, the first of the two variants on
1173// the [`VersionError`] envelope's paired `(String, String)` tuple-newtype
1174// codec-magnitude family (its peer is [`VersionError::Requirement`] on
1175// the sibling [`parse_requirement`] surface). Same discipline the peer
1176// per-variant lifts on [`AplicacaoError`] / [`SupervisorError`] /
1177// [`UpgradeError`] / [`LayoutError`] / [`DepError`] / [`ManifestError`]
1178// / [`LimitsError`] / [`BehaviorError`] / [`DialetoError`] have
1179// converged through the "one substrate primitive per emit-site variant"
1180// ratchet: the sole wire-up site opens the identical
1181// `VersionError::Semver(<into-String-expr>, <into-String-expr>)` block
1182// against the parser-scoped `String` binding (`self.0.clone()`) and the
1183// derived `String` binding (`e.to_string()`) on the failing
1184// [`semver::Version::parse`] arm, so the fold routes the site through
1185// one dispatch on a uniform pair of `impl Into<String>` params,
1186// byte-equal to the pre-lift tuple-newtype construction on the same
1187// arguments. The `impl Into<String>` bound covers both the pre-lift
1188// `String` bindings and any future `&str` binding a downstream consumer
1189// might carry without forcing the caller to spell the `.into()`
1190// conversion at the wire-up site — the same shape the peer
1191// [`LimitsError::empty_byte_size`] / [`LimitsError::empty_duration`] /
1192// [`DialetoError::leitura`] folds carry on the single-slot `(String)`
1193// tuple-newtype cousins of the same tuple-newtype error-envelope family
1194// on the sibling parser surfaces. `#[must_use]` fires a compile warning
1195// at any wire-up that mistakenly discards the constructed error. The
1196// added [`PartialEq`] / [`Eq`] derives on the envelope (peer with the
1197// sibling [`LimitsError`] / [`DialetoError`] / [`DepError`] envelopes
1198// on the same axis) let the fail-before-pass-after byte-equality pins
1199// below trip a de-lift regression at caixa-core test time under
1200// `PartialEq` rather than at a downstream diagnostic shape drift.
1201//
1202// Every future consumer that wants to construct this variant outside
1203// [`CaixaVersion::parse`] (a deferred `feira lint --canonical-versao`
1204// per-caixa admission verb probing each authored top-level `:versao`
1205// value against the same [`semver::Version::parse`] gate, an M4 typed
1206// `mesh.pleme.io/v1alpha1/Servico` CR materializer's per-manifest
1207// admission validator re-checking one edited `:versao` slot against
1208// the [`CaixaVersion::parse`] semver floor, a per-`caixa.lisp` value-
1209// shape pre-emitter probing each declared `:versao` magnitude ahead of
1210// the operator's admit-cycle) now reaches the variant through one call
1211// rather than re-inlining the two-slot tuple-newtype block in lockstep.
1212impl VersionError {
1213    /// Construct a [`VersionError::Semver`] carrying the offending
1214    /// authoring string `value` and the underlying [`semver::Version::parse`]
1215    /// `reason` verbatim in the variant's two-slot tuple-newtype payload.
1216    /// Folds the uniform `Self::Semver(value.into(), reason.into())`
1217    /// tuple-newtype construction onto one substrate primitive so every
1218    /// wire-up on the variant reads through one dispatch rather than the
1219    /// pre-lift open-coded
1220    /// `VersionError::Semver(<into-String-expr>, <into-String-expr>)`
1221    /// block. The paired `impl Into<String>` bounds cover the pre-lift
1222    /// `String` wire-up shape on [`CaixaVersion::parse`]
1223    /// (`self.0.clone()` on the parser-scoped `String` field, `e.to_string()`
1224    /// on the derived `String` from the failing
1225    /// [`semver::Version::parse`] arm) without forcing the caller to
1226    /// spell the conversion at the wire-up site. Peer to the sibling
1227    /// [`VersionError::Requirement`] variant on the [`parse_requirement`]
1228    /// surface — the same `(String, String)` two-slot tuple-newtype axis
1229    /// of the paired [`VersionError`] envelope, but on the `SemVer`
1230    /// version-body parser surface rather than the version-requirement
1231    /// parser surface.
1232    #[must_use]
1233    pub fn semver(value: impl Into<String>, reason: impl Into<String>) -> Self {
1234        Self::Semver(value.into(), reason.into())
1235    }
1236
1237    /// Construct a [`VersionError::Requirement`] carrying the offending
1238    /// authoring string `value` and the underlying
1239    /// [`semver::VersionReq::parse`] `reason` verbatim in the variant's
1240    /// two-slot tuple-newtype payload. Folds the uniform
1241    /// `Self::Requirement(value.into(), reason.into())` tuple-newtype
1242    /// construction onto one substrate primitive so every wire-up on the
1243    /// variant reads through one dispatch rather than the pre-lift open-
1244    /// coded `VersionError::Requirement(<into-String-expr>,
1245    /// <into-String-expr>)` block. Peer to the sibling
1246    /// [`VersionError::semver`] ctor on the [`CaixaVersion::parse`]
1247    /// surface — the same `(String, String)` two-slot tuple-newtype axis
1248    /// of the paired [`VersionError`] envelope, but on the version-
1249    /// requirement parser surface rather than the semver-version-body
1250    /// parser surface. Closes the last un-lifted variant on the
1251    /// [`VersionError`] envelope: every arm now reaches its emit site
1252    /// through one substrate-primitive dispatch, matching the "one
1253    /// substrate primitive per emit-site variant" ratchet the peer per-
1254    /// variant lifts on [`crate::AplicacaoError`] /
1255    /// [`crate::SupervisorError`] / [`crate::UpgradeError`] /
1256    /// [`crate::LayoutError`] / [`crate::DepError`] /
1257    /// [`crate::ManifestError`] / [`crate::LimitsError`] /
1258    /// [`crate::BehaviorError`] / [`crate::DialetoError`] have converged
1259    /// onto.
1260    #[must_use]
1261    pub fn requirement(value: impl Into<String>, reason: impl Into<String>) -> Self {
1262        Self::Requirement(value.into(), reason.into())
1263    }
1264}
1265
1266#[cfg(test)]
1267mod tests {
1268    use super::*;
1269
1270    #[test]
1271    fn version_round_trip() {
1272        let v: CaixaVersion = "1.2.3".into();
1273        assert_eq!(v.as_str(), "1.2.3");
1274        assert_eq!(v.parse().unwrap().to_string(), "1.2.3");
1275    }
1276
1277    #[test]
1278    fn caixa_version_as_str_accessor_is_const_fn() {
1279        // Fail-before-pass-after pin on [`CaixaVersion::as_str`]'s
1280        // `const`-eval-surface posture. The accessor projects the typed
1281        // newtype's inner [`String`] through the `pub const fn`
1282        // [`String::as_str`] (const-stable since Rust 1.87, well within
1283        // the workspace MSRV) — any future accidental downgrade to
1284        // non-`const` fails `as_str_via_const_fn` at caixa-core build
1285        // time with E0015 (`cannot call non-const method`), strictly
1286        // stronger than a runtime `assert!`. Sibling of the peer
1287        // per-M2/M3/universal-axis `String → &str` scalar-accessor
1288        // family pins on the sibling `const`-eval-surface passes
1289        // ([`crate::Caixa::nome`] / [`crate::Caixa::versao`] at the
1290        // top-level manifest, [`crate::aplicacao::Membro::nome`] /
1291        // [`crate::aplicacao::Membro::versao_requirement`] at the M3
1292        // membership axis, [`crate::aplicacao::Entrada::hostname`] /
1293        // [`crate::aplicacao::Entrada::destination`] at the M3 ingress
1294        // axis, [`crate::supervisor::ChildSpec::nome`] /
1295        // [`crate::supervisor::ChildSpec::versao_requirement`] at the
1296        // M2 supervisor-tree axis,
1297        // [`crate::upgrade::UpgradeFromEntry::prior_versao`] at the M2
1298        // upgrade axis, [`crate::dep::Dep::nome`] /
1299        // [`crate::dep::Dep::versao_requirement`] at the dep-graph
1300        // axis, and the peer per-`:contratos` [`crate::aplicacao::WitContract::source`] /
1301        // [`crate::aplicacao::WitContract::destination`] /
1302        // [`crate::aplicacao::WitContract::world_ref`] trio the
1303        // sibling pin at 279823b already anchors).
1304        const fn as_str_via_const_fn(v: &CaixaVersion) -> &str {
1305            v.as_str()
1306        }
1307        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1308            let v: CaixaVersion = versao.into();
1309            assert_eq!(as_str_via_const_fn(&v), v.as_str());
1310            assert_eq!(v.as_str(), versao);
1311        }
1312    }
1313
1314    #[test]
1315    fn star_is_any() {
1316        let r = parse_requirement("*").unwrap();
1317        assert!(r.matches(&"0.1.0".parse().unwrap()));
1318        assert!(r.matches(&"99.0.0".parse().unwrap()));
1319    }
1320
1321    #[test]
1322    fn caret_matches_minor_range() {
1323        let r = parse_requirement("^0.1").unwrap();
1324        assert!(r.matches(&"0.1.0".parse().unwrap()));
1325        assert!(r.matches(&"0.1.99".parse().unwrap()));
1326        assert!(!r.matches(&"0.2.0".parse().unwrap()));
1327    }
1328
1329    #[test]
1330    fn invalid_version_errors() {
1331        let v: CaixaVersion = "not-a-version".into();
1332        assert!(v.parse().is_err());
1333    }
1334
1335    #[test]
1336    fn semver_ctor_matches_tuple_literal_wrap_on_str_binding() {
1337        // Fail-before-pass-after byte-equality pin: the lifted
1338        // [`VersionError::semver`] inherent ctor projects a `&str`
1339        // binding pair through the paired `impl Into<String>` bounds
1340        // byte-equal to the pre-lift open-coded
1341        // `VersionError::Semver(<into-String-expr>, <into-String-expr>)`
1342        // tuple-literal on the same fixture, so any future silent
1343        // regression that swaps `.into()` for a divergent conversion
1344        // (a stray `String::from(str::trim(v))` normalization, a
1345        // parity-lossy `.to_lowercase()` fold, a `Cow<'_, str>` detour)
1346        // trips at caixa-core test time under `PartialEq` rather than
1347        // at a downstream diagnostic-shape drift on a consumer surface.
1348        // Same shape the peer
1349        // [`crate::LimitsError::empty_byte_size_ctor_matches_tuple_literal_wrap_on_str_binding`]
1350        // / [`crate::DialetoError::leitura_ctor_matches_tuple_literal_wrap_on_str_binding`]
1351        // pins carry on the sibling single-slot `(String)` tuple-newtype
1352        // cousins of the same tuple-newtype error-envelope family on the
1353        // sibling parser surfaces.
1354        let value: &str = "not-a-version";
1355        let reason: &str = "unexpected character 'n' while parsing major version number";
1356        assert_eq!(
1357            VersionError::semver(value, reason),
1358            VersionError::Semver(value.to_string(), reason.to_string()),
1359            "generated semver ctor over `&str` bindings must match \
1360             the pre-lift tuple-literal wrap on the same fixture",
1361        );
1362    }
1363
1364    #[test]
1365    fn semver_ctor_matches_tuple_literal_wrap_on_string_binding() {
1366        // Fail-before-pass-after byte-equality pin on the paired owned-
1367        // `String` shape — the actual wire-up shape on
1368        // [`CaixaVersion::parse`] (`self.0.clone()` +
1369        // `e.to_string()`). Peer to the `&str` variant above; refuses
1370        // any future de-lift that inlines a divergent construction on
1371        // the owned-`String` path (a stray `.trim().to_string()`
1372        // normalization on either slot, a swap that routes the ctor
1373        // through the sibling [`VersionError::Requirement`] variant on
1374        // the paired parser surface).
1375        let value: String = String::from("1.2");
1376        let reason: String =
1377            String::from("unexpected end of input while parsing minor version number");
1378        assert_eq!(
1379            VersionError::semver(value.clone(), reason.clone()),
1380            VersionError::Semver(value, reason),
1381            "generated semver ctor over owned-`String` bindings must \
1382             match the pre-lift tuple-literal wrap on the same fixture",
1383        );
1384    }
1385
1386    #[test]
1387    fn parse_semver_error_routes_through_semver_ctor() {
1388        // Fail-before-pass-after routes-through pin: refuses any future
1389        // de-lift of [`CaixaVersion::parse`]'s
1390        // [`semver::Version::parse`] `map_err` arm off the substrate
1391        // primitive. Sweeps three malformed authoring shapes (a bare
1392        // non-numeric, a partial `major.minor` shape, a stray leading
1393        // `v`-prefix that the [`DEFAULT_PUBLISH_TAG_PREFIX`] git-tag
1394        // convention rejects at the version-body slot) through the
1395        // parser and asserts the emitted [`VersionError`] equals the
1396        // ctor-built error verbatim under `PartialEq`, so any future
1397        // swap of the wire-up (an inline `Self::Semver(...)`
1398        // re-inlining, a routing detour through the sibling
1399        // [`VersionError::Requirement`] variant on the paired parser
1400        // surface, a swap of the ordering on the paired arguments)
1401        // trips at caixa-core test time rather than at a downstream
1402        // diagnostic drift on a `feira lint` / operator admission
1403        // callsite.
1404        for bad in ["not-a-version", "1.2", "v0.1.0"] {
1405            let v: CaixaVersion = bad.into();
1406            let err = v
1407                .parse()
1408                .expect_err("malformed versao fixture must fail semver parsing");
1409            let semver_reason = match semver::Version::parse(bad) {
1410                Err(e) => e.to_string(),
1411                Ok(_) => unreachable!(
1412                    "fixture `{bad}` is documented as a `SemVer` \
1413                     rejection but parsed cleanly — the pin's oracle \
1414                     drifted from `semver`'s current shape",
1415                ),
1416            };
1417            assert_eq!(
1418                err,
1419                VersionError::semver(bad, semver_reason),
1420                "CaixaVersion::parse must route its semver `map_err` \
1421                 arm through the lifted VersionError::semver ctor on \
1422                 the same offending value and semver reason",
1423            );
1424        }
1425    }
1426
1427    #[test]
1428    fn default_git_remote_pins_canonical_origin_byte() {
1429        // Bridge-arm pin: [`DEFAULT_GIT_REMOTE`] resolves to the
1430        // canonical `"origin"` byte today, the same remote-handle every
1431        // `git clone <url>` invocation populates by default and every
1432        // peer `feira` writer-side verb (`feira publish`, `feira deploy
1433        // --apply`, `feira app deploy --apply`) names when it invokes
1434        // `git push <remote> <ref>` against the local clone. Pin the
1435        // literal here (peer with the
1436        // [`DEFAULT_PUBLISH_TAG_PREFIX`] / [`crate::DEFAULT_SERVICO_PORT`]
1437        // / [`crate::DEFAULT_NAMESPACE`] / [`crate::DEFAULT_LIBRARY_NAME`]
1438        // / [`crate::DEFAULT_FLUX_SYSTEM_NAMESPACE`] canonical-literal
1439        // pins on the sibling lifted-constant surfaces) so a future
1440        // remote-naming rebrand surfaces here as a coordinated edit-
1441        // point: the sibling [`caixa-feira`]
1442        // `publish_remote_default_pins_lifted_caixa_core_constant`
1443        // pinning test already pins the equality at the clap-default
1444        // axis; this pin closes the second coordinate of the
1445        // triangle by anchoring the lifted constant's current byte
1446        // to the canonical git-default-remote convention's documented
1447        // shape.
1448        assert_eq!(DEFAULT_GIT_REMOTE, "origin");
1449    }
1450
1451    #[test]
1452    fn default_pleme_git_org_pins_canonical_pleme_io_byte() {
1453        // Bridge-arm pin: [`DEFAULT_PLEME_GIT_ORG`] resolves to the
1454        // canonical `"pleme-io"` GitHub-org-handle today, the same org
1455        // name every peer substrate-side default-git-source consumer
1456        // ([`caixa-feira`]'s `feira lock` `resolve_stub` for the
1457        // per-dep `:fonte`-elided `github:<org>/<nome>` fallback,
1458        // [`caixa-flux`]'s `ClusterBundleOpts::for_caixa` constructor
1459        // for the per-caixa `:repositorio`-elided
1460        // `https://github.com/<org>/<nome>` fallback) fills into its
1461        // per-consumer render/resolve compose site. Pin the literal
1462        // here (peer with the [`DEFAULT_PUBLISH_TAG_PREFIX`] /
1463        // [`DEFAULT_GIT_REMOTE`] canonical-literal pins on the sibling
1464        // lifted-constant surfaces) so a future substrate-side git-org
1465        // migration surfaces here as a coordinated edit-point: both
1466        // sibling consumer sites already thread through the same
1467        // `&'static str`, this pin anchors the lifted constant's
1468        // current byte to the canonical substrate-git-org convention's
1469        // documented shape.
1470        assert_eq!(DEFAULT_PLEME_GIT_ORG, "pleme-io");
1471    }
1472
1473    #[test]
1474    fn requirement_ctor_matches_tuple_literal_wrap_on_str_binding() {
1475        // Fail-before-pass-after byte-equality pin: the lifted
1476        // [`VersionError::requirement`] inherent ctor projects a `&str`
1477        // binding pair through the paired `impl Into<String>` bounds
1478        // byte-equal to the pre-lift open-coded
1479        // `VersionError::Requirement(<into-String-expr>, <into-String-expr>)`
1480        // tuple-literal on the same fixture. Same shape the peer
1481        // [`VersionError::semver_ctor_matches_tuple_literal_wrap_on_str_binding`]
1482        // pin carries on the sibling [`VersionError::Semver`] variant of
1483        // the same `(String, String)` two-slot tuple-newtype envelope.
1484        let value: &str = "not-a-req";
1485        let reason: &str = "unexpected character 'n' while parsing major version number";
1486        assert_eq!(
1487            VersionError::requirement(value, reason),
1488            VersionError::Requirement(value.to_string(), reason.to_string()),
1489            "generated requirement ctor over `&str` bindings must match \
1490             the pre-lift tuple-literal wrap on the same fixture",
1491        );
1492    }
1493
1494    #[test]
1495    fn requirement_ctor_matches_tuple_literal_wrap_on_string_binding() {
1496        // Fail-before-pass-after byte-equality pin on the paired owned-
1497        // `String` shape. Peer to the `&str` variant above; refuses any
1498        // future de-lift that inlines a divergent construction on the
1499        // owned-`String` path (a stray `.trim().to_string()` normalization
1500        // on either slot, a swap that routes the ctor through the sibling
1501        // [`VersionError::Semver`] variant on the paired parser surface,
1502        // an argument-ordering swap on the paired slots).
1503        let value: String = String::from("^bogus");
1504        let reason: String = String::from("unexpected character while parsing requirement");
1505        assert_eq!(
1506            VersionError::requirement(value.clone(), reason.clone()),
1507            VersionError::Requirement(value, reason),
1508            "generated requirement ctor over owned-`String` bindings must \
1509             match the pre-lift tuple-literal wrap on the same fixture",
1510        );
1511    }
1512
1513    #[test]
1514    fn parse_requirement_error_routes_through_requirement_ctor() {
1515        // Fail-before-pass-after routes-through pin: refuses any future
1516        // de-lift of [`parse_requirement`]'s
1517        // [`semver::VersionReq::parse`] `map_err` arm off the substrate
1518        // primitive. Sweeps three malformed authoring shapes (a bare
1519        // non-numeric, a stray operator with no version body, a
1520        // caret-prefixed non-numeric that the [`semver::VersionReq`]
1521        // grammar rejects at the operator-body slot) through the parser
1522        // and asserts the emitted [`VersionError`] equals the ctor-built
1523        // error verbatim under `PartialEq`, so any future swap of the
1524        // wire-up (an inline `Self::Requirement(...)` re-inlining, a
1525        // routing detour through the sibling [`VersionError::Semver`]
1526        // variant on the paired parser surface, an argument-ordering
1527        // swap on the paired slots) trips at caixa-core test time rather
1528        // than at a downstream diagnostic drift on a `feira lock` /
1529        // resolver admission callsite. The `"*"` wildcard short-circuit
1530        // is deliberately excluded from the sweep — it returns
1531        // [`semver::VersionReq::STAR`] before reaching the parser arm.
1532        for bad in ["not-a-req", "^", "^bogus"] {
1533            let err = parse_requirement(bad)
1534                .expect_err("malformed requirement fixture must fail parsing");
1535            let semver_reason = match semver::VersionReq::parse(bad) {
1536                Err(e) => e.to_string(),
1537                Ok(_) => unreachable!(
1538                    "fixture `{bad}` is documented as a `VersionReq` \
1539                     rejection but parsed cleanly — the pin's oracle \
1540                     drifted from `semver`'s current shape",
1541                ),
1542            };
1543            assert_eq!(
1544                err,
1545                VersionError::requirement(bad, semver_reason),
1546                "parse_requirement must route its `map_err` arm through \
1547                 the lifted VersionError::requirement ctor on the same \
1548                 offending value and semver reason",
1549            );
1550        }
1551    }
1552
1553    #[test]
1554    fn default_publish_tag_prefix_pins_canonical_v_byte() {
1555        // Bridge-arm pin: [`DEFAULT_PUBLISH_TAG_PREFIX`] resolves to the
1556        // canonical Zig-style `"v"` byte today, the same prefix every
1557        // peer doc-comment on the typed `:versao` surfaces (the
1558        // top-level `:versao` `validate_versao` cascade at
1559        // caixa-core/src/manifest.rs:646, the four sibling per-axis
1560        // `:versao` requirement gates that name the publish-side
1561        // `v<versao>` tag inline in their bodies) cites as the
1562        // canonical convention. Pin the literal here (peer with the
1563        // [`crate::DEFAULT_SERVICO_PORT`] / [`crate::DEFAULT_NAMESPACE`]
1564        // / [`crate::DEFAULT_LIBRARY_NAME`] canonical-literal pins on
1565        // the sibling lifted-constant surfaces) so a future rebrand of
1566        // the constant surfaces here as a coordinated edit-point: both
1567        // sibling pinning tests on the two consumer crates
1568        // ([`caixa-feira`] `publish_prefix_default_pins_lifted_caixa_core_constant`,
1569        // [`caixa-flux`] `cluster_bundle_default_git_tag_uses_lifted_caixa_core_prefix`)
1570        // already pin the equality at the consumer-default axis; this
1571        // pin closes the third coordinate of the triangle by anchoring
1572        // the lifted constant's current byte to the canonical Zig-style
1573        // convention's documented shape.
1574        assert_eq!(DEFAULT_PUBLISH_TAG_PREFIX, "v");
1575    }
1576
1577    #[test]
1578    fn caixa_version_as_ref_str_routes_through_as_str_accessor() {
1579        // Fail-before-pass-after byte-parity pin on the lifted
1580        // `impl AsRef<str> for CaixaVersion` — asserts the standard-
1581        // library trait impl and the substrate-primitive
1582        // [`CaixaVersion::as_str`] `pub const fn` accessor resolve to
1583        // the same `&str` per instance, so any future silent detour
1584        // that routes the impl through a divergent projection (a
1585        // `Cow<'_, str>` intermediate, a stray `.to_lowercase()`
1586        // normalization, a swap onto a per-arm inline `&self.0.as_str()`
1587        // re-inlining, a swap onto a divergent [`String::trim`]
1588        // fold) trips at caixa-core test time under `PartialEq`
1589        // rather than at a downstream `impl AsRef<str>`-bound
1590        // consumer's silent split. Sweeps four authoring shapes (a
1591        // canonical release version, a pre-release build-metadata
1592        // version, the zero-version canonical unset baseline, and
1593        // the empty-string byte the caller-side default-construct
1594        // path composes) so every non-degenerate arm of the wrapped
1595        // `String` storage is covered. Peer of the sibling
1596        // [`caixa_version_as_str_accessor_is_const_fn`] const-eval
1597        // pin on the same [`CaixaVersion::as_str`] primitive — the
1598        // two pins together cover the const-eval axis (the pin above)
1599        // and the trait-projection axis (this pin) of the same
1600        // substrate-primitive scalar accessor.
1601        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1602            let v: CaixaVersion = versao.into();
1603            assert_eq!(
1604                <CaixaVersion as AsRef<str>>::as_ref(&v),
1605                v.as_str(),
1606                "AsRef<str> impl must byte-equal CaixaVersion::as_str \
1607                 on the same instance — divergence signals a silent \
1608                 detour off the substrate-primitive accessor",
1609            );
1610            assert_eq!(
1611                <CaixaVersion as AsRef<str>>::as_ref(&v),
1612                versao,
1613                "AsRef<str> impl must byte-equal the pre-lift wrapped \
1614                 String storage on round-trip through the From<&str> \
1615                 constructor — divergence signals a normalization \
1616                 detour on either the constructor or the accessor",
1617            );
1618        }
1619    }
1620
1621    #[test]
1622    fn caixa_version_as_ref_str_routes_through_display_via_shared_accessor() {
1623        // Fail-before-pass-after byte-parity pin on the three-path
1624        // convergence discipline the substrate primitive now carries
1625        // on the `&str`-projection axis: `<CaixaVersion as
1626        // AsRef<str>>::as_ref(&v)` (the newly lifted impl),
1627        // `format!("{v}")` (the pre-existing [`fmt::Display`] impl),
1628        // and `v.as_str()` (the substrate-primitive `pub const fn`
1629        // accessor both trait impls delegate through) must resolve to
1630        // the same byte-string on every instance. Refuses any future
1631        // divergence between the two trait impls (a stray
1632        // [`fmt::Display::fmt`] rewrite that inlines
1633        // `f.write_str(&self.0)` on the wrapped `String` directly,
1634        // bypassing the shared accessor; a hypothetical `AsRef<str>`
1635        // rewrite that inlines the same `&self.0` field-access) that
1636        // would silently split the two projection paths of the same
1637        // typed newtype. Mirrors the sibling three-path-convergence
1638        // discipline the peer [`RestartStrategy`] typed enum carries
1639        // on its `Display` / `as_str` / `Serialize` triple (aplicacao.rs
1640        // pin `restart_strategy_display_matches_serialized_wire_byte_string`).
1641        for versao in ["0.1.0", "1.2.3-alpha.1", ""] {
1642            let v: CaixaVersion = versao.into();
1643            let via_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
1644            let via_display: String = format!("{v}");
1645            let via_accessor: &str = v.as_str();
1646            assert_eq!(via_as_ref, via_accessor);
1647            assert_eq!(via_display, via_accessor);
1648            assert_eq!(via_as_ref, via_display.as_str());
1649        }
1650    }
1651
1652    #[test]
1653    fn caixa_version_borrow_str_routes_through_as_str_accessor() {
1654        // Fail-before-pass-after byte-parity pin on the lifted
1655        // `impl std::borrow::Borrow<str> for CaixaVersion` — asserts the
1656        // standard-library trait impl and the substrate-primitive
1657        // [`CaixaVersion::as_str`] `pub const fn` accessor resolve to
1658        // the same `&str` per instance, so any future silent detour
1659        // that routes the impl through a divergent projection (a
1660        // `Cow<'_, str>` intermediate, a stray `.to_lowercase()`
1661        // normalization, a swap onto a per-arm inline `&self.0.as_str()`
1662        // re-inlining that bypasses the shared accessor) trips at
1663        // caixa-core test time under `PartialEq` rather than at a
1664        // downstream `Borrow<str>`-bound collection API's silent
1665        // hash-mismatch on the load-bearing HashMap-key axis. Peer of
1666        // the sibling
1667        // [`caixa_version_as_ref_str_routes_through_as_str_accessor`]
1668        // byte-parity pin on the paired [`AsRef<str>`] impl — both cover
1669        // the borrow-projection axis of the same substrate primitive.
1670        use std::borrow::Borrow;
1671        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1672            let v: CaixaVersion = versao.into();
1673            assert_eq!(
1674                <CaixaVersion as Borrow<str>>::borrow(&v),
1675                v.as_str(),
1676                "Borrow<str> impl must byte-equal CaixaVersion::as_str \
1677                 on the same instance — divergence signals a silent \
1678                 detour off the substrate-primitive accessor",
1679            );
1680            assert_eq!(
1681                <CaixaVersion as Borrow<str>>::borrow(&v),
1682                versao,
1683                "Borrow<str> impl must byte-equal the pre-lift wrapped \
1684                 String storage on round-trip through the From<&str> \
1685                 constructor",
1686            );
1687        }
1688    }
1689
1690    #[test]
1691    fn caixa_version_borrow_str_and_as_ref_str_agree_on_every_shape() {
1692        // Fail-before-pass-after cross-axis partition pin on the two
1693        // trait impls on the same borrow-projection axis: the lifted
1694        // [`std::borrow::Borrow<str>`] impl (this commit) and the paired
1695        // [`AsRef<str>`] impl (a086 lift) must resolve to the same `&str`
1696        // per instance, both routing through the shared substrate-
1697        // primitive [`CaixaVersion::as_str`] accessor. Refuses any future
1698        // silent split between the two trait impls (a stray
1699        // [`AsRef::as_ref`] rewrite that inlines `&self.0.as_str()` on
1700        // the wrapped [`String`] directly, bypassing the shared
1701        // accessor; a hypothetical [`Borrow::borrow`] rewrite that
1702        // inlines the same `&self.0` field-access) that would silently
1703        // split the two projection paths of the same typed newtype and
1704        // break the [`std::borrow::Borrow`] safety contract's
1705        // "hash-agrees on the borrowed view" invariant the collection
1706        // APIs rely on. Mirrors the sibling three-path convergence
1707        // discipline the peer
1708        // [`caixa_version_as_ref_str_routes_through_display_via_shared_accessor`]
1709        // pin carries on the `AsRef<str>` / `Display` / `as_str` triple.
1710        use std::borrow::Borrow;
1711        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1712            let v: CaixaVersion = versao.into();
1713            let via_borrow: &str = <CaixaVersion as Borrow<str>>::borrow(&v);
1714            let via_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
1715            let via_accessor: &str = v.as_str();
1716            assert_eq!(via_borrow, via_accessor);
1717            assert_eq!(via_as_ref, via_accessor);
1718            assert_eq!(via_borrow, via_as_ref);
1719        }
1720    }
1721
1722    #[test]
1723    fn caixa_version_borrow_str_enables_hashmap_lookup_by_borrowed_key() {
1724        // Fail-before-pass-after contract-witness pin on the
1725        // [`std::borrow::Borrow<str>`] safety contract: a
1726        // [`std::collections::HashMap`] keyed by owned [`CaixaVersion`]
1727        // must resolve `.get::<str>("<versao>")` probes through the
1728        // borrowed `&str` view of a stored key to the same slot, and
1729        // (`String::hash` calls `str::hash` on bytes, and the
1730        // [`CaixaVersion`] derived [`Hash`] impl hashes the wrapped
1731        // [`String`] field) the borrowed and owned hash must agree on
1732        // every fixture. Refuses any future silent regression that would
1733        // break the hash-agrees invariant (a
1734        // [`Hash for CaixaVersion`] hand-written impl that diverges from
1735        // the derived shape, a [`Borrow<str>::borrow`] rewrite that
1736        // routes through a normalization detour, an `Eq` hand-written
1737        // impl that diverges from field-wise equality) —
1738        // [`HashMap::get<Q>`] would return [`None`] on a key that
1739        // structurally lives in the map, which is the exact silent
1740        // failure the [`std::borrow::Borrow`] documented safety contract
1741        // rules out. The load-bearing use-case this impl was added for:
1742        // per-`:versao` collection APIs must be probed by borrowed
1743        // `&str` without a per-probe [`CaixaVersion::from(&str)`]
1744        // allocation.
1745        use std::collections::HashMap;
1746        let mut map: HashMap<CaixaVersion, u32> = HashMap::new();
1747        for (i, versao) in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""].iter().enumerate() {
1748            let key: CaixaVersion = (*versao).into();
1749            map.insert(key, u32::try_from(i).unwrap());
1750        }
1751        for (i, versao) in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""].iter().enumerate() {
1752            let hit = map.get(*versao).unwrap_or_else(|| {
1753                panic!(
1754                    "HashMap<CaixaVersion, _>::get(&str) must reach the \
1755                     slot inserted under CaixaVersion::from({versao:?}) \
1756                     through the Borrow<str> bound — a miss signals the \
1757                     borrowed-vs-owned hash-agrees invariant broke",
1758                )
1759            });
1760            assert_eq!(*hit, u32::try_from(i).unwrap());
1761        }
1762        assert!(
1763            !map.contains_key("does-not-exist"),
1764            "HashMap<CaixaVersion, _>::contains_key(&str) on an absent \
1765             key must return false, not accidentally hash-collide onto \
1766             a stored slot — the miss path must respect the same \
1767             invariant as the hit path",
1768        );
1769    }
1770
1771    #[test]
1772    fn caixa_version_from_into_owned_string_returns_wrapped_body() {
1773        // Fail-before-pass-after byte-parity pin on the lifted
1774        // `impl From<CaixaVersion> for String` — asserts the owned-input
1775        // reverse-projection routes the wrapper's own heap allocation
1776        // through verbatim (no re-copy, no normalization detour) so
1777        // `String::from(v)` returns the same bytes `v.as_str()`
1778        // borrows. Refuses any future silent detour that would swap
1779        // the move on `v.0` for an allocating `.as_str().to_owned()` /
1780        // `.to_string()` cascade (the pre-lift compose shape), a stray
1781        // `.trim().to_owned()` normalization, or a routing through the
1782        // sibling [`fmt::Display`] emitter that would introduce a
1783        // formatter round-trip.
1784        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1785            let v: CaixaVersion = versao.into();
1786            let expected = v.as_str().to_owned();
1787            let owned: String = String::from(v);
1788            assert_eq!(
1789                owned, expected,
1790                "String::from(v) must return the wrapper's own bytes verbatim",
1791            );
1792            assert_eq!(
1793                owned, versao,
1794                "String::from(v) must round-trip byte-equal through the From<&str> constructor",
1795            );
1796        }
1797    }
1798
1799    #[test]
1800    fn caixa_version_from_into_owned_string_and_as_str_agree_on_every_shape() {
1801        // Fail-before-pass-after cross-axis partition pin: the owned-
1802        // input [`From<CaixaVersion> for String`] reverse projection
1803        // and the borrowed [`AsRef<str>`] projection resolve to the
1804        // same bytes on every instance, and the paired forward
1805        // [`From<String> for CaixaVersion`] constructor closes the
1806        // `Self → String → Self` round-trip by construction. Refuses
1807        // any future silent split between the owned-move reverse axis
1808        // and the borrowed-clone AsRef axis (a stray normalization on
1809        // one path only) that would let `String::from(v)` and
1810        // `v.as_ref::<str>()` diverge on the same instance.
1811        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1812            let v: CaixaVersion = versao.into();
1813            let via_as_ref: String = <CaixaVersion as AsRef<str>>::as_ref(&v).to_owned();
1814            let via_to_string: String = v.to_string();
1815            let via_from: String = String::from(v.clone());
1816            assert_eq!(via_from, via_as_ref);
1817            assert_eq!(via_from, via_to_string);
1818            let round_trip: CaixaVersion = via_from.clone().into();
1819            assert_eq!(round_trip, v);
1820        }
1821    }
1822
1823    #[test]
1824    fn caixa_version_from_borrowed_into_owned_string_routes_through_as_str_accessor() {
1825        // Fail-before-pass-after byte-parity pin on the lifted
1826        // `impl From<&CaixaVersion> for String` — asserts the
1827        // borrowed-input reverse projection allocates a fresh
1828        // [`String`] whose bytes byte-equal the substrate-primitive
1829        // [`CaixaVersion::as_str`] accessor on the same instance,
1830        // preserving the source [`CaixaVersion`] intact (no move-out).
1831        // Refuses any future silent detour that would route the impl
1832        // through a divergent projection (a stray normalization step,
1833        // a swap onto the sibling [`fmt::Display`]-routed
1834        // [`ToString::to_string`] surface, a re-inlining that
1835        // dereferences `&self.0` outside the shared accessor).
1836        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1837            let v: CaixaVersion = versao.into();
1838            let via_borrowed: String = String::from(&v);
1839            assert_eq!(
1840                via_borrowed,
1841                v.as_str(),
1842                "String::from(&v) must byte-equal CaixaVersion::as_str",
1843            );
1844            // The borrowed-input impl must not move out of the source.
1845            assert_eq!(
1846                v.as_str(),
1847                versao,
1848                "source CaixaVersion must survive borrowed-input projection"
1849            );
1850        }
1851    }
1852
1853    #[test]
1854    fn caixa_version_from_owned_and_borrowed_into_string_agree_on_every_shape() {
1855        // Fail-before-pass-after cross-axis partition pin: the paired
1856        // owned-input [`From<CaixaVersion> for String`] and
1857        // borrowed-input [`From<&CaixaVersion> for String`] impls
1858        // resolve to the same bytes on every instance, closing the
1859        // "owned-input move vs. borrowed-input clone" bifurcation on
1860        // the same wrapped body. Refuses any future silent split
1861        // between the two corners (a normalization on one path only, a
1862        // divergent routing that would let `String::from(v.clone())`
1863        // and `String::from(&v)` disagree on the same body).
1864        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1865            let v: CaixaVersion = versao.into();
1866            let via_borrowed: String = String::from(&v);
1867            let via_owned: String = String::from(v.clone());
1868            assert_eq!(via_owned, via_borrowed);
1869            assert_eq!(via_borrowed, versao);
1870        }
1871    }
1872
1873    #[test]
1874    fn caixa_version_from_into_owned_cow_str_returns_owned_wrapped_body() {
1875        // Fail-before-pass-after byte-parity + [`Cow::Owned`]-arm pin
1876        // on the lifted `impl From<CaixaVersion> for
1877        // std::borrow::Cow<'static, str>` — asserts the owned-input
1878        // reverse projection routes the wrapper's own heap allocation
1879        // through `Cow::Owned(v.0)` verbatim (no re-copy, no
1880        // normalization detour, no `Cow::Borrowed` misclassification
1881        // that would demand a `&'static str` the runtime wrapper cannot
1882        // carry), so the emitted [`Cow`] byte-equals the substrate-
1883        // primitive [`CaixaVersion::as_str`] accessor on the same
1884        // instance and round-trips byte-equal through the paired
1885        // forward [`From<String> for CaixaVersion`] constructor.
1886        // Refuses any future silent detour: a swap of the move on
1887        // `v.0` for an allocating `.as_str().to_owned()` cascade (the
1888        // pre-lift compose shape would double-allocate a fresh
1889        // intermediary [`String`] on the way to the same
1890        // [`Cow::Owned`] arm), a stray `.trim().to_owned()`
1891        // normalization, or a mis-routing through
1892        // [`Cow::Borrowed`] on a non-`'static` byte-string that would
1893        // not type-check.
1894        use std::borrow::Cow;
1895        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1896            let v: CaixaVersion = versao.into();
1897            let expected = v.as_str().to_owned();
1898            let cow: Cow<'static, str> = Cow::from(v.clone());
1899            assert!(
1900                matches!(cow, Cow::Owned(_)),
1901                "From<CaixaVersion> for Cow<'static, str> must land on \
1902                 the Cow::Owned arm — a runtime String wrapper cannot \
1903                 promise the 'static lifetime the Cow::Borrowed arm \
1904                 requires",
1905            );
1906            assert_eq!(
1907                cow.as_ref(),
1908                expected,
1909                "Cow::from(v) must return the wrapper's own bytes verbatim",
1910            );
1911            let round_trip: CaixaVersion = cow.into_owned().into();
1912            assert_eq!(
1913                round_trip, v,
1914                "Cow::from(v).into_owned() must round-trip byte-equal \
1915                 through the From<String> constructor",
1916            );
1917        }
1918    }
1919
1920    #[test]
1921    fn caixa_version_from_into_owned_cow_str_and_string_agree_on_every_shape() {
1922        // Fail-before-pass-after cross-axis partition pin: the owned-
1923        // input [`From<CaixaVersion> for Cow<'static, str>`] reverse
1924        // projection and the paired owned-input
1925        // [`From<CaixaVersion> for String`] reverse projection resolve
1926        // to the same bytes on every instance, and both agree with the
1927        // borrowed [`AsRef<str>`] surface on the same wrapped body.
1928        // Refuses any future silent split between the two owned-input
1929        // reverse-projection axes (a stray normalization on one path
1930        // only, a divergent routing that would let
1931        // `Cow::from(v.clone())` and `String::from(v.clone())` disagree
1932        // on the same body) that would silently split the same-shape
1933        // owned-move discipline across the two reverse-projection
1934        // targets.
1935        use std::borrow::Cow;
1936        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1937            let v: CaixaVersion = versao.into();
1938            let via_string: String = String::from(v.clone());
1939            let via_cow: Cow<'static, str> = Cow::from(v.clone());
1940            let via_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
1941            assert_eq!(via_cow.as_ref(), via_string.as_str());
1942            assert_eq!(via_cow.as_ref(), via_as_ref);
1943            assert_eq!(via_cow.as_ref(), versao);
1944        }
1945    }
1946
1947    #[test]
1948    fn caixa_version_from_borrowed_into_owned_cow_str_routes_through_as_str_accessor() {
1949        // Fail-before-pass-after byte-parity + [`Cow::Owned`]-arm pin
1950        // on the lifted `impl From<&CaixaVersion> for
1951        // std::borrow::Cow<'static, str>` — asserts the borrowed-input
1952        // reverse projection allocates a fresh [`Cow::Owned`] whose
1953        // bytes byte-equal the substrate-primitive
1954        // [`CaixaVersion::as_str`] accessor on the same instance,
1955        // preserving the source [`CaixaVersion`] intact (no move-out).
1956        // Refuses any future silent detour that would route the impl
1957        // through a divergent projection (a stray normalization step,
1958        // a mis-routing onto [`Cow::Borrowed`] on a non-`'static`
1959        // byte-string that would not type-check, a re-inlining that
1960        // dereferences `&self.0` outside the shared accessor).
1961        use std::borrow::Cow;
1962        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
1963            let v: CaixaVersion = versao.into();
1964            let via_borrowed: Cow<'static, str> = Cow::from(&v);
1965            assert!(
1966                matches!(via_borrowed, Cow::Owned(_)),
1967                "From<&CaixaVersion> for Cow<'static, str> must land on \
1968                 the Cow::Owned arm — a runtime String wrapper cannot \
1969                 promise the 'static lifetime the Cow::Borrowed arm \
1970                 requires",
1971            );
1972            assert_eq!(
1973                via_borrowed.as_ref(),
1974                v.as_str(),
1975                "Cow::from(&v) must byte-equal CaixaVersion::as_str",
1976            );
1977            // The borrowed-input impl must not move out of the source.
1978            assert_eq!(
1979                v.as_str(),
1980                versao,
1981                "source CaixaVersion must survive borrowed-input projection",
1982            );
1983        }
1984    }
1985
1986    #[test]
1987    fn caixa_version_from_owned_and_borrowed_into_cow_str_agree_on_every_shape() {
1988        // Fail-before-pass-after cross-axis partition pin: the paired
1989        // owned-input [`From<CaixaVersion> for Cow<'static, str>`] and
1990        // borrowed-input [`From<&CaixaVersion> for Cow<'static, str>`]
1991        // impls resolve to the same bytes on every instance, closing
1992        // the "owned-input move vs. borrowed-input clone" bifurcation
1993        // on the same wrapped body through the [`Cow<'static, str>`]
1994        // axis. Refuses any future silent split between the two
1995        // corners (a normalization on one path only, a divergent
1996        // routing that would let `Cow::from(v.clone())` and
1997        // `Cow::from(&v)` disagree on the same body). Both corners
1998        // must land on [`Cow::Owned`] — the runtime wrapper's storage
1999        // rules out the borrowed arm on both input shapes alike.
2000        use std::borrow::Cow;
2001        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2002            let v: CaixaVersion = versao.into();
2003            let via_borrowed: Cow<'static, str> = Cow::from(&v);
2004            let via_owned: Cow<'static, str> = Cow::from(v.clone());
2005            assert!(matches!(via_borrowed, Cow::Owned(_)));
2006            assert!(matches!(via_owned, Cow::Owned(_)));
2007            assert_eq!(via_owned.as_ref(), via_borrowed.as_ref());
2008            assert_eq!(via_borrowed.as_ref(), versao);
2009        }
2010    }
2011
2012    #[test]
2013    fn caixa_version_from_into_owned_box_str_returns_wrapped_body() {
2014        // Fail-before-pass-after byte-parity pin on the lifted
2015        // `impl From<CaixaVersion> for Box<str>` — asserts the owned-
2016        // input reverse projection routes the wrapper's own heap
2017        // allocation through [`String::into_boxed_str`] verbatim (no
2018        // re-copy of the underlying bytes on the fixed-capacity path;
2019        // `String::into_boxed_str` reuses the same `Vec<u8>` buffer
2020        // when length matches capacity), so `Box::<str>::from(v)`
2021        // returns the same bytes `v.as_str()` borrows and round-trips
2022        // byte-equal through the paired forward
2023        // [`From<String> for CaixaVersion`] constructor closing the
2024        // two-way `Self → Box<str> → Self` cycle by construction.
2025        // Refuses any future silent detour that would swap
2026        // `v.0.into_boxed_str()` for an allocating
2027        // `.as_str().to_owned().into_boxed_str()` cascade (the pre-lift
2028        // compose shape would double-allocate a fresh intermediary
2029        // [`String`] on the way to the same [`Box<str>`] slot), a
2030        // stray `.trim().to_owned().into_boxed_str()` normalization,
2031        // or a routing through the sibling [`fmt::Display`] emitter
2032        // that would introduce a formatter round-trip.
2033        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2034            let v: CaixaVersion = versao.into();
2035            let expected = v.as_str().to_owned();
2036            let boxed: Box<str> = Box::<str>::from(v.clone());
2037            assert_eq!(
2038                boxed.as_ref(),
2039                expected.as_str(),
2040                "Box::<str>::from(v) must return the wrapper's own bytes verbatim",
2041            );
2042            let round_trip: CaixaVersion = boxed.into_string().into();
2043            assert_eq!(
2044                round_trip, v,
2045                "Box::<str>::from(v).into_string() must round-trip byte-equal \
2046                 through the From<String> constructor",
2047            );
2048        }
2049    }
2050
2051    #[test]
2052    fn caixa_version_from_into_owned_box_str_and_string_agree_on_every_shape() {
2053        // Fail-before-pass-after cross-axis partition pin: the owned-
2054        // input [`From<CaixaVersion> for Box<str>`] reverse projection
2055        // and the paired owned-input [`From<CaixaVersion> for String`]
2056        // and [`From<CaixaVersion> for Cow<'static, str>`] reverse
2057        // projections resolve to the same bytes on every instance, and
2058        // all three agree with the borrowed [`AsRef<str>`] surface on
2059        // the same wrapped body. Refuses any future silent split
2060        // between the three owned-input reverse-projection axes (a
2061        // stray normalization on one path only, a divergent routing
2062        // that would let `Box::<str>::from(v.clone())`,
2063        // `String::from(v.clone())`, and `Cow::from(v.clone())`
2064        // disagree on the same body) that would silently split the
2065        // same-shape owned-move discipline across the three
2066        // reverse-projection targets.
2067        use std::borrow::Cow;
2068        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2069            let v: CaixaVersion = versao.into();
2070            let via_string: String = String::from(v.clone());
2071            let via_cow: Cow<'static, str> = Cow::from(v.clone());
2072            let via_box: Box<str> = Box::<str>::from(v.clone());
2073            let via_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
2074            assert_eq!(via_box.as_ref(), via_string.as_str());
2075            assert_eq!(via_box.as_ref(), via_cow.as_ref());
2076            assert_eq!(via_box.as_ref(), via_as_ref);
2077            assert_eq!(via_box.as_ref(), versao);
2078        }
2079    }
2080
2081    #[test]
2082    fn caixa_version_from_borrowed_into_owned_box_str_routes_through_as_str_accessor() {
2083        // Fail-before-pass-after byte-parity pin on the lifted
2084        // `impl From<&CaixaVersion> for Box<str>` — asserts the
2085        // borrowed-input reverse projection allocates a fresh
2086        // [`Box<str>`] whose bytes byte-equal the substrate-primitive
2087        // [`CaixaVersion::as_str`] accessor on the same instance,
2088        // preserving the source [`CaixaVersion`] intact (no move-out).
2089        // Refuses any future silent detour that would route the impl
2090        // through a divergent projection (a stray normalization step,
2091        // a swap onto the sibling [`fmt::Display`]-routed
2092        // [`ToString::to_string`] surface followed by
2093        // `.into_boxed_str()`, a re-inlining that dereferences
2094        // `&self.0` outside the shared accessor).
2095        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2096            let v: CaixaVersion = versao.into();
2097            let via_borrowed: Box<str> = Box::<str>::from(&v);
2098            assert_eq!(
2099                via_borrowed.as_ref(),
2100                v.as_str(),
2101                "Box::<str>::from(&v) must byte-equal CaixaVersion::as_str",
2102            );
2103            // The borrowed-input impl must not move out of the source.
2104            assert_eq!(
2105                v.as_str(),
2106                versao,
2107                "source CaixaVersion must survive borrowed-input projection",
2108            );
2109        }
2110    }
2111
2112    #[test]
2113    fn caixa_version_from_owned_and_borrowed_into_box_str_agree_on_every_shape() {
2114        // Fail-before-pass-after cross-corner partition pin: the paired
2115        // owned-input [`From<CaixaVersion> for Box<str>`] and
2116        // borrowed-input [`From<&CaixaVersion> for Box<str>`] impls
2117        // resolve to the same bytes on every instance, closing the
2118        // "owned-input move vs. borrowed-input clone" bifurcation on
2119        // the same wrapped body through the [`Box<str>`] axis. Refuses
2120        // any future silent split between the two corners (a
2121        // normalization on one path only, a divergent routing that
2122        // would let `Box::<str>::from(v.clone())` and
2123        // `Box::<str>::from(&v)` disagree on the same body).
2124        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2125            let v: CaixaVersion = versao.into();
2126            let via_borrowed: Box<str> = Box::<str>::from(&v);
2127            let via_owned: Box<str> = Box::<str>::from(v.clone());
2128            assert_eq!(via_owned.as_ref(), via_borrowed.as_ref());
2129            assert_eq!(via_borrowed.as_ref(), versao);
2130        }
2131    }
2132
2133    #[test]
2134    fn caixa_version_from_into_owned_arc_str_returns_wrapped_body() {
2135        // Fail-before-pass-after byte-parity pin on the lifted
2136        // `impl From<CaixaVersion> for std::sync::Arc<str>` — asserts
2137        // the owned-input reverse projection routes the wrapper's own
2138        // [`String`] body through [`std::sync::Arc::<str>::from`]
2139        // verbatim (one heap allocation of the atomically-refcounted
2140        // slab, no intermediary [`String`] or [`Box<str>`] on the
2141        // owned-input path), so `Arc::<str>::from(v)` returns the same
2142        // bytes `v.as_str()` borrows and round-trips byte-equal through
2143        // the paired forward [`From<String> for CaixaVersion`]
2144        // constructor closing the two-way `Self → Arc<str> → Self`
2145        // cycle by construction. Refuses any future silent detour that
2146        // would swap `Arc::<str>::from(v.0)` for an allocating
2147        // `.as_str().to_owned().into()` cascade (the pre-lift compose
2148        // shape would double-allocate a fresh intermediary [`String`]
2149        // on the way to the same [`Arc<str>`] slot), a stray
2150        // `.trim().to_owned().into()` normalization, or a routing
2151        // through the sibling [`fmt::Display`] emitter that would
2152        // introduce a formatter round-trip.
2153        use std::sync::Arc;
2154        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2155            let v: CaixaVersion = versao.into();
2156            let expected = v.as_str().to_owned();
2157            let arced: Arc<str> = Arc::<str>::from(v.clone());
2158            assert_eq!(
2159                arced.as_ref(),
2160                expected.as_str(),
2161                "Arc::<str>::from(v) must return the wrapper's own bytes verbatim",
2162            );
2163            let round_trip: CaixaVersion = arced.as_ref().to_owned().into();
2164            assert_eq!(
2165                round_trip, v,
2166                "Arc::<str>::from(v) must round-trip byte-equal through \
2167                 the From<String> constructor",
2168            );
2169        }
2170    }
2171
2172    #[test]
2173    fn caixa_version_from_into_owned_arc_str_and_string_agree_on_every_shape() {
2174        // Fail-before-pass-after cross-axis partition pin: the owned-
2175        // input [`From<CaixaVersion> for std::sync::Arc<str>`] reverse
2176        // projection and the paired owned-input
2177        // [`From<CaixaVersion> for String`],
2178        // [`From<CaixaVersion> for Cow<'static, str>`], and
2179        // [`From<CaixaVersion> for Box<str>`] reverse projections
2180        // resolve to the same bytes on every instance, and all four
2181        // agree with the borrowed [`AsRef<str>`] surface on the same
2182        // wrapped body. Refuses any future silent split between the
2183        // four owned-input reverse-projection axes (a stray
2184        // normalization on one path only, a divergent routing that
2185        // would let `Arc::<str>::from(v.clone())`,
2186        // `Box::<str>::from(v.clone())`, `String::from(v.clone())`,
2187        // and `Cow::from(v.clone())` disagree on the same body) that
2188        // would silently split the same-shape owned-move discipline
2189        // across the four reverse-projection targets.
2190        use std::borrow::Cow;
2191        use std::sync::Arc;
2192        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2193            let v: CaixaVersion = versao.into();
2194            let via_string: String = String::from(v.clone());
2195            let via_cow: Cow<'static, str> = Cow::from(v.clone());
2196            let via_box: Box<str> = Box::<str>::from(v.clone());
2197            let via_arc: Arc<str> = Arc::<str>::from(v.clone());
2198            let via_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
2199            assert_eq!(via_arc.as_ref(), via_string.as_str());
2200            assert_eq!(via_arc.as_ref(), via_cow.as_ref());
2201            assert_eq!(via_arc.as_ref(), via_box.as_ref());
2202            assert_eq!(via_arc.as_ref(), via_as_ref);
2203            assert_eq!(via_arc.as_ref(), versao);
2204        }
2205    }
2206
2207    #[test]
2208    fn caixa_version_from_borrowed_into_owned_arc_str_routes_through_as_str_accessor() {
2209        // Fail-before-pass-after byte-parity pin on the lifted
2210        // `impl From<&CaixaVersion> for std::sync::Arc<str>` — asserts
2211        // the borrowed-input reverse projection allocates a fresh
2212        // [`std::sync::Arc<str>`] whose bytes byte-equal the
2213        // substrate-primitive [`CaixaVersion::as_str`] accessor on the
2214        // same instance, preserving the source [`CaixaVersion`] intact
2215        // (no move-out). Refuses any future silent detour that would
2216        // route the impl through a divergent projection (a stray
2217        // normalization step, a swap onto the sibling [`fmt::Display`]-
2218        // routed [`ToString::to_string`] surface followed by
2219        // `.into()`, a re-inlining that dereferences `&self.0` outside
2220        // the shared accessor).
2221        use std::sync::Arc;
2222        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2223            let v: CaixaVersion = versao.into();
2224            let via_borrowed: Arc<str> = Arc::<str>::from(&v);
2225            assert_eq!(
2226                via_borrowed.as_ref(),
2227                v.as_str(),
2228                "Arc::<str>::from(&v) must byte-equal CaixaVersion::as_str",
2229            );
2230            // The borrowed-input impl must not move out of the source.
2231            assert_eq!(
2232                v.as_str(),
2233                versao,
2234                "source CaixaVersion must survive borrowed-input projection",
2235            );
2236        }
2237    }
2238
2239    #[test]
2240    fn caixa_version_from_owned_and_borrowed_into_arc_str_agree_on_every_shape() {
2241        // Fail-before-pass-after cross-corner partition pin: the paired
2242        // owned-input [`From<CaixaVersion> for std::sync::Arc<str>`]
2243        // and borrowed-input [`From<&CaixaVersion> for std::sync::Arc<str>`]
2244        // impls resolve to the same bytes on every instance, closing
2245        // the "owned-input move vs. borrowed-input clone" bifurcation
2246        // on the same wrapped body through the [`std::sync::Arc<str>`]
2247        // axis. Refuses any future silent split between the two
2248        // corners (a normalization on one path only, a divergent
2249        // routing that would let `Arc::<str>::from(v.clone())` and
2250        // `Arc::<str>::from(&v)` disagree on the same body).
2251        use std::sync::Arc;
2252        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2253            let v: CaixaVersion = versao.into();
2254            let via_borrowed: Arc<str> = Arc::<str>::from(&v);
2255            let via_owned: Arc<str> = Arc::<str>::from(v.clone());
2256            assert_eq!(via_owned.as_ref(), via_borrowed.as_ref());
2257            assert_eq!(via_borrowed.as_ref(), versao);
2258        }
2259    }
2260
2261    #[test]
2262    fn caixa_version_from_into_owned_rc_str_returns_wrapped_body() {
2263        // Fail-before-pass-after byte-parity pin on the lifted
2264        // `impl From<CaixaVersion> for std::rc::Rc<str>` — asserts the
2265        // owned-input reverse projection routes the wrapper's own
2266        // [`String`] body through [`std::rc::Rc::<str>::from`] verbatim
2267        // (one heap allocation of the single-threaded-refcounted slab, no
2268        // intermediary [`String`] or [`Box<str>`] on the owned-input
2269        // path), so `Rc::<str>::from(v)` returns the same bytes
2270        // `v.as_str()` borrows and round-trips byte-equal through the
2271        // paired forward [`From<String> for CaixaVersion`] constructor
2272        // closing the two-way `Self → Rc<str> → Self` cycle by
2273        // construction. Refuses any future silent detour that would swap
2274        // `Rc::<str>::from(v.0)` for an allocating
2275        // `.as_str().to_owned().into()` cascade (the pre-lift compose
2276        // shape would double-allocate a fresh intermediary [`String`] on
2277        // the way to the same [`Rc<str>`] slot), a stray
2278        // `.trim().to_owned().into()` normalization, or a routing through
2279        // the sibling [`fmt::Display`] emitter that would introduce a
2280        // formatter round-trip.
2281        use std::rc::Rc;
2282        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2283            let v: CaixaVersion = versao.into();
2284            let expected = v.as_str().to_owned();
2285            let rced: Rc<str> = Rc::<str>::from(v.clone());
2286            assert_eq!(
2287                rced.as_ref(),
2288                expected.as_str(),
2289                "Rc::<str>::from(v) must return the wrapper's own bytes verbatim",
2290            );
2291            let round_trip: CaixaVersion = rced.as_ref().to_owned().into();
2292            assert_eq!(
2293                round_trip, v,
2294                "Rc::<str>::from(v) must round-trip byte-equal through \
2295                 the From<String> constructor",
2296            );
2297        }
2298    }
2299
2300    #[test]
2301    fn caixa_version_from_into_owned_rc_str_and_arc_str_agree_on_every_shape() {
2302        // Fail-before-pass-after cross-axis partition pin: the owned-
2303        // input [`From<CaixaVersion> for std::rc::Rc<str>`] reverse
2304        // projection and the paired owned-input
2305        // [`From<CaixaVersion> for String`],
2306        // [`From<CaixaVersion> for Cow<'static, str>`],
2307        // [`From<CaixaVersion> for Box<str>`], and
2308        // [`From<CaixaVersion> for std::sync::Arc<str>`] reverse
2309        // projections resolve to the same bytes on every instance, and
2310        // all five agree with the borrowed [`AsRef<str>`] surface on the
2311        // same wrapped body. Refuses any future silent split between the
2312        // five owned-input reverse-projection axes (a stray normalization
2313        // on one path only, a divergent routing that would let
2314        // `Rc::<str>::from(v.clone())`, `Arc::<str>::from(v.clone())`,
2315        // `Box::<str>::from(v.clone())`, `String::from(v.clone())`, and
2316        // `Cow::from(v.clone())` disagree on the same body) that would
2317        // silently split the same-shape owned-move discipline across the
2318        // five reverse-projection targets.
2319        use std::borrow::Cow;
2320        use std::rc::Rc;
2321        use std::sync::Arc;
2322        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2323            let v: CaixaVersion = versao.into();
2324            let owned_string: String = String::from(v.clone());
2325            let owned_cow: Cow<'static, str> = Cow::from(v.clone());
2326            let owned_box: Box<str> = Box::<str>::from(v.clone());
2327            let atomic_handle: Arc<str> = Arc::<str>::from(v.clone());
2328            let single_handle: Rc<str> = Rc::<str>::from(v.clone());
2329            let borrowed_as_ref: &str = <CaixaVersion as AsRef<str>>::as_ref(&v);
2330            assert_eq!(single_handle.as_ref(), owned_string.as_str());
2331            assert_eq!(single_handle.as_ref(), owned_cow.as_ref());
2332            assert_eq!(single_handle.as_ref(), owned_box.as_ref());
2333            assert_eq!(single_handle.as_ref(), atomic_handle.as_ref());
2334            assert_eq!(single_handle.as_ref(), borrowed_as_ref);
2335            assert_eq!(single_handle.as_ref(), versao);
2336        }
2337    }
2338
2339    #[test]
2340    fn caixa_version_from_borrowed_into_owned_rc_str_routes_through_as_str_accessor() {
2341        // Fail-before-pass-after byte-parity pin on the lifted
2342        // `impl From<&CaixaVersion> for std::rc::Rc<str>` — asserts the
2343        // borrowed-input reverse projection allocates a fresh
2344        // [`std::rc::Rc<str>`] whose bytes byte-equal the substrate-
2345        // primitive [`CaixaVersion::as_str`] accessor on the same
2346        // instance, preserving the source [`CaixaVersion`] intact (no
2347        // move-out). Refuses any future silent detour that would route
2348        // the impl through a divergent projection (a stray normalization
2349        // step, a swap onto the sibling [`fmt::Display`]-routed
2350        // [`ToString::to_string`] surface followed by `.into()`, a
2351        // re-inlining that dereferences `&self.0` outside the shared
2352        // accessor).
2353        use std::rc::Rc;
2354        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2355            let v: CaixaVersion = versao.into();
2356            let via_borrowed: Rc<str> = Rc::<str>::from(&v);
2357            assert_eq!(
2358                via_borrowed.as_ref(),
2359                v.as_str(),
2360                "Rc::<str>::from(&v) must byte-equal CaixaVersion::as_str",
2361            );
2362            // The borrowed-input impl must not move out of the source.
2363            assert_eq!(
2364                v.as_str(),
2365                versao,
2366                "source CaixaVersion must survive borrowed-input projection",
2367            );
2368        }
2369    }
2370
2371    #[test]
2372    fn caixa_version_from_owned_and_borrowed_into_rc_str_agree_on_every_shape() {
2373        // Fail-before-pass-after cross-corner partition pin: the paired
2374        // owned-input [`From<CaixaVersion> for std::rc::Rc<str>`] and
2375        // borrowed-input [`From<&CaixaVersion> for std::rc::Rc<str>`]
2376        // impls resolve to the same bytes on every instance, closing the
2377        // "owned-input move vs. borrowed-input clone" bifurcation on the
2378        // same wrapped body through the [`std::rc::Rc<str>`] axis.
2379        // Refuses any future silent split between the two corners (a
2380        // normalization on one path only, a divergent routing that would
2381        // let `Rc::<str>::from(v.clone())` and `Rc::<str>::from(&v)`
2382        // disagree on the same body).
2383        use std::rc::Rc;
2384        for versao in ["0.1.0", "1.2.3-alpha.1", "0.0.0", ""] {
2385            let v: CaixaVersion = versao.into();
2386            let via_borrowed: Rc<str> = Rc::<str>::from(&v);
2387            let via_owned: Rc<str> = Rc::<str>::from(v.clone());
2388            assert_eq!(via_owned.as_ref(), via_borrowed.as_ref());
2389            assert_eq!(via_borrowed.as_ref(), versao);
2390        }
2391    }
2392
2393    #[test]
2394    fn caixa_version_from_str_routes_through_from_str_reference_impl() {
2395        // Fail-before-pass-after byte-parity pin on the lifted
2396        // `impl std::str::FromStr for CaixaVersion` — asserts the
2397        // stdlib parse-set entry point delegates byte-for-byte through
2398        // the paired borrowed-input `impl From<&str> for CaixaVersion`
2399        // constructor above (which wraps `s.to_string()` into the
2400        // newtype's inner `String` slot), so every consumer that reaches
2401        // [`CaixaVersion`] through the standard-library `T: FromStr`-
2402        // bounded parse surface (`str::parse::<CaixaVersion>`, the
2403        // `<CaixaVersion as std::str::FromStr>::from_str` explicit-trait
2404        // spelling on a generic bound, a `clap::value_parser!(CaixaVersion)`
2405        // short-form on a future arg-parse, a `serde_with::DisplayFromStr`
2406        // wrapper on a downstream typed-YAML derive) routes through the
2407        // same wrap the sibling `From<&str>` forward-projection already
2408        // installs. Refuses any future silent detour that would route
2409        // the stdlib entry point through a divergent projection (a stray
2410        // `parse_semver_first` validation gate slipping onto the wrap
2411        // path, a normalization step that would drop whitespace or
2412        // canonicalize a prerelease tag, a swap onto the paired
2413        // [`CaixaVersion::parse`] `Result<semver::Version, VersionError>`
2414        // accessor that would narrow the accept-set to the semver
2415        // grammar's shape ahead of the wrap). Also witnesses the
2416        // `Err = Infallible` type-level shape at compile time under the
2417        // explicit `Result<CaixaVersion, std::convert::Infallible>`
2418        // annotation the loop body binds against — any future accidental
2419        // widening of the error type (a swap onto `type Err =
2420        // VersionError`) trips the annotation at caixa-core build time
2421        // with E0308 (`expected Infallible, found <T>`), strictly stronger
2422        // than a runtime `.unwrap()` on the sibling `.parse()` short-form.
2423        //
2424        // Sweeps the same fixture bodies the sibling
2425        // `caixa_version_as_str_accessor_is_const_fn` /
2426        // `caixa_version_from_owned_and_borrowed_into_rc_str_agree_on_every_shape`
2427        // pins already cover on the paired scalar-accessor and
2428        // owned-vs-borrowed axes: canonical semver, prerelease-shape,
2429        // zero-body, and empty-string corners. Extends the sweep with a
2430        // requirement-shape (`^0.1`), a star (`*`), and a non-semver junk
2431        // body (`not-a-version`) so the total-wrap discipline the
2432        // `Err = Infallible` shape witnesses is asserted across the four
2433        // canonical axes of the input space: semver-shaped bodies the
2434        // paired [`CaixaVersion::parse`] accessor would accept, semver-
2435        // requirement-shaped bodies the sibling [`parse_requirement`]
2436        // surface consumes, empty bodies (which the wrap accepts but
2437        // downstream semver rejects), and non-semver junk (which the
2438        // wrap accepts and downstream semver rejects).
2439        use std::str::FromStr;
2440        for versao in [
2441            "0.1.0",
2442            "1.2.3-alpha.1",
2443            "0.0.0",
2444            "",
2445            "^0.1",
2446            "*",
2447            "not-a-version",
2448        ] {
2449            let via_parse_short_form: Result<CaixaVersion, std::convert::Infallible> =
2450                versao.parse::<CaixaVersion>();
2451            let via_from_str_explicit: Result<CaixaVersion, std::convert::Infallible> =
2452                <CaixaVersion as FromStr>::from_str(versao);
2453            let via_from_ref: CaixaVersion = <CaixaVersion as From<&str>>::from(versao);
2454            let via_parse_ok: CaixaVersion = via_parse_short_form.unwrap();
2455            let via_from_str_ok: CaixaVersion = via_from_str_explicit.unwrap();
2456            assert_eq!(
2457                via_parse_ok.as_str(),
2458                versao,
2459                "str::parse::<CaixaVersion>() must byte-equal the input",
2460            );
2461            assert_eq!(
2462                via_from_str_ok.as_str(),
2463                versao,
2464                "<CaixaVersion as FromStr>::from_str must byte-equal the input",
2465            );
2466            assert_eq!(
2467                via_parse_ok, via_from_ref,
2468                "str::parse::<CaixaVersion>() must byte-equal From<&str>",
2469            );
2470            assert_eq!(
2471                via_from_str_ok, via_from_ref,
2472                "<CaixaVersion as FromStr>::from_str must byte-equal From<&str>",
2473            );
2474        }
2475    }
2476
2477    #[test]
2478    fn caixa_version_from_str_round_trips_through_display_on_every_input() {
2479        // Fail-before-pass-after round-trip pin: the lifted
2480        // `impl std::str::FromStr for CaixaVersion` closes the two-way
2481        // canonical wire-form axis with the paired forward-projection
2482        // [`fmt::Display`] impl at line 29 —
2483        // `s.parse::<CaixaVersion>().unwrap().to_string() == s` for every
2484        // `&str` on the total-wrap axis the newtype installs at rest.
2485        // Refuses any future silent narrowing on either half (a stray
2486        // normalization step slipping onto the [`fmt::Display`] impl that
2487        // would canonicalize the wrapped body ahead of `f.write_str`, a
2488        // divergent wrap on the `FromStr` impl that would swap the paired
2489        // `From<&str>` constructor for a fresh `String::from(s).trim()`-
2490        // style body-mutating projection) so the round-trip theorem the
2491        // pin states remains machine-checked at caixa-core test time.
2492        //
2493        // Peer of the sibling `caixa_version_from_str_routes_through_from_str_reference_impl`
2494        // pin immediately above (which witnesses the byte-parity axis
2495        // against the paired `From<&str>` forward-projection); this pin
2496        // witnesses the same axis against the paired `fmt::Display`
2497        // forward-projection instead, closing the two-way round-trip
2498        // through the standard-library [`fmt::Display`] / [`FromStr`]
2499        // pair the substrate reaches [`CaixaVersion`] through on the
2500        // canonical wire-form axis.
2501        for versao in [
2502            "0.1.0",
2503            "1.2.3-alpha.1",
2504            "0.0.0",
2505            "",
2506            "^0.1",
2507            "*",
2508            "not-a-version",
2509            "1.2.3+build.42",
2510        ] {
2511            let parsed: CaixaVersion = versao.parse::<CaixaVersion>().unwrap();
2512            let displayed: String = parsed.to_string();
2513            assert_eq!(
2514                displayed, versao,
2515                "CaixaVersion::from_str + Display must round-trip byte-for-byte",
2516            );
2517        }
2518    }
2519}