Skip to main content

tatara_process/
tagged_union.rs

1//! `tagged_union::resolve` — the typescape's "exactly-one-Option" pattern,
2//! lifted to one source of truth.
3//!
4//! Several CRD-facing types in this crate ([`crate::intent::Intent`],
5//! [`crate::lifetime::Lifetime`], [`crate::export::ArtifactSource`],
6//! [`crate::export::VectorChannel`], [`crate::encapsulates::EncapsulationKind`])
7//! carry `N` `Option<T>` fields where exactly one is expected to be
8//! populated on the wire. Each previously hand-rolled the same
9//! `count() + if-let-chain + unreachable!()` body — four parallel tables
10//! (the struct fields, an `is_some()` count array, an `if-let-else`
11//! resolution chain, and any sibling projection like `IntentVariant::kind`)
12//! kept coherent only by code review. The `unreachable!()` arm at the
13//! bottom of every chain was a sentinel that fires at runtime if the
14//! parallel tables ever drift.
15//!
16//! This module collapses the resolver to ONE typed sweep over an
17//! `IntoIterator<Item = Option<V>>` of candidate variant projections.
18//! Adding a new tagged-union variant is now ONE additional line at the
19//! callsite — no `unreachable!()` arm to update, no parallel `is_some()`
20//! count array to extend.
21
22/// Outcome of [`resolve`] when the candidate list isn't exactly-one.
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
24pub enum ResolveError {
25    /// No candidate was populated.
26    None,
27    /// More than one candidate was populated.
28    Many,
29}
30
31/// Resolve at most one populated variant from a candidate list.
32///
33/// Each item in `candidates` is the projected borrowed-variant view for
34/// the corresponding `Option<T>` field — `None` when the field is unset,
35/// `Some(V::Variant(...))` when set.
36///
37/// Returns the single populated variant, [`ResolveError::None`] when
38/// none are populated, or [`ResolveError::Many`] when more than one are.
39///
40/// The body is one short-circuiting sweep — `Many` is returned as soon
41/// as the second populated entry is seen, without scanning the rest.
42pub fn resolve<V>(candidates: impl IntoIterator<Item = Option<V>>) -> Result<V, ResolveError> {
43    let mut found: Option<V> = None;
44    for candidate in candidates {
45        if candidate.is_some() {
46            if found.is_some() {
47                return Err(ResolveError::Many);
48            }
49            found = candidate;
50        }
51    }
52    found.ok_or(ResolveError::None)
53}
54
55/// Sibling error carriers on tagged-union `.variant()` sites all
56/// project the two [`ResolveError`] arms onto the SAME closed-set
57/// diagnostic shape — `Empty(&'static str)` for "no variant set"
58/// (carrying the closed-set kind list so the operator diagnostic
59/// names every candidate) and a payload-free `Ambiguous` for
60/// "multiple variants set". This trait names that shared shape as
61/// ONE typed contract; [`resolve_or_err`] then composes [`resolve`]
62/// with the trait so each per-carrier `.map_err(|e| match e { ... })`
63/// site collapses to a one-line typed dispatch.
64///
65/// Impls live at each error carrier's own module so the (diagnostic
66/// message, closed-set list) pair stays owned by the carrier that
67/// publishes it — the trait is the projection, not the message.
68pub trait TaggedUnionError: Sized {
69    /// Construct the "no variant set" arm with the closed-set kind
70    /// list slash-joined into the diagnostic payload.
71    fn empty(kinds: &'static str) -> Self;
72    /// Construct the "multiple variants set" arm.
73    fn ambiguous() -> Self;
74}
75
76/// Resolve at most one populated variant, mapping the two
77/// [`ResolveError`] arms onto the caller's typed carrier via
78/// [`TaggedUnionError`]. The compound-lift primitive: sweep +
79/// short-circuit + typed-error dispatch as ONE call.
80///
81/// Substrate primitive for the four sibling `Xxx::variant()` sites
82/// on `ProcessSpec` (`Intent::variant`,
83/// `EncapsulationKind::variant`, `ArtifactSource::variant`,
84/// `VectorChannel::variant`) that previously restated the SAME
85/// `.map_err(|e| match e { None => Empty(LIST), Many => Ambiguous })`
86/// two-arm dispatch at each call site — every one of them a
87/// byte-identical restatement of the (empty→list, many→ambiguous)
88/// projection whose payload identity is strictly the carrier's own
89/// diagnostic. A fifth sibling error carrier picks up the projection
90/// through ONE `impl TaggedUnionError` block + ONE `resolve_or_err`
91/// call site.
92///
93/// The [`Lifetime::variant`](crate::lifetime::Lifetime::variant)
94/// site is DELIBERATELY not routed through this primitive — its
95/// `ResolveError::None` arm resolves to a `Permanent` default
96/// variant, not to an `Empty` typed error, so the projection shape
97/// diverges at the None arm.
98pub fn resolve_or_err<V, E: TaggedUnionError>(
99    candidates: impl IntoIterator<Item = Option<V>>,
100    kinds: &'static str,
101) -> Result<V, E> {
102    resolve(candidates).map_err(|e| match e {
103        ResolveError::None => E::empty(kinds),
104        ResolveError::Many => E::ambiguous(),
105    })
106}
107
108/// Declare a sibling error carrier for a tagged-union `.variant()`
109/// site — the enum + [`TaggedUnionError`] impl in ONE authoring
110/// surface.
111///
112/// Every one of the four production `.variant()` sites on
113/// `ProcessSpec` ([`crate::intent::Intent`],
114/// [`crate::encapsulates::EncapsulationKind`],
115/// [`crate::export::ArtifactSource`],
116/// [`crate::export::VectorChannel`]) pre-lift restated the same
117/// four-piece authoring shape by hand:
118///
119/// 1. `#[derive(Clone, Copy, Debug, thiserror::Error, PartialEq,
120///    Eq)]` on the carrier — byte-identical across all four.
121/// 2. A two-variant enum body (`Empty(&'static str)`, `Ambiguous`)
122///    — structurally identical.
123/// 3. Two `#[error(...)]` messages whose only per-carrier knob is a
124///    noun-prefix (`"intent"`, `"encapsulation kind"`, ...) — every
125///    other byte of the (`"has no variant set (one of {0}
126///    required)"`, `"has multiple variants set; exactly one
127///    required"`) tails was verbatim.
128/// 4. A six-line `impl TaggedUnionError` whose two constructor
129///    bodies re-projected `Self::Empty(kinds)` / `Self::Ambiguous`
130///    onto each carrier's own typed variants.
131///
132/// The macro collapses (1) + (2) + (4) onto ONE call and takes the
133/// two per-carrier operator-facing diagnostic literals as named
134/// arguments so (3) stays visible at the callsite without re-authoring
135/// the shared derive set or trait impl. A fifth sibling carrier
136/// lands as ONE `declare_tagged_union_error!` invocation — no
137/// re-authored `#[derive(...)]`, no re-authored two-variant enum
138/// body, no re-authored `impl TaggedUnionError` block.
139///
140/// Emitted derives include `Copy` — the `Empty` arm carries only
141/// a `&'static str` and the `Ambiguous` arm is payload-free, so
142/// the carrier is always `Copy` regardless of caller.
143///
144/// # Example
145///
146/// ```ignore
147/// declare_tagged_union_error! {
148///     pub IntentError,
149///     empty = "intent has no variant set (one of {0} required)",
150///     ambiguous = "intent has multiple variants set; exactly one required",
151/// }
152/// ```
153///
154/// Expands to the enum + [`TaggedUnionError`] impl for
155/// `IntentError`; the `Empty` arm carries the caller's closed-set
156/// kind-list literal.
157#[macro_export]
158macro_rules! declare_tagged_union_error {
159    (
160        $(#[$attr:meta])*
161        $vis:vis $name:ident,
162        empty = $empty:literal,
163        ambiguous = $ambiguous:literal $(,)?
164    ) => {
165        $(#[$attr])*
166        #[derive(
167            ::std::clone::Clone,
168            ::std::marker::Copy,
169            ::std::fmt::Debug,
170            ::thiserror::Error,
171            ::std::cmp::PartialEq,
172            ::std::cmp::Eq,
173        )]
174        $vis enum $name {
175            #[error($empty)]
176            Empty(&'static str),
177            #[error($ambiguous)]
178            Ambiguous,
179        }
180
181        impl $crate::tagged_union::TaggedUnionError for $name {
182            fn empty(kinds: &'static str) -> Self {
183                Self::Empty(kinds)
184            }
185            fn ambiguous() -> Self {
186                Self::Ambiguous
187            }
188        }
189    };
190}
191
192/// Declare the three-block impl stanza a tagged-union parent type
193/// publishes to the substrate — inherent `.variant()` forwarder +
194/// [`VariantSelector<Parent>`] impl on the sibling `Kind` +
195/// [`TaggedUnion`] impl on the parent — in ONE authoring surface.
196///
197/// Every one of the four production `.variant()` sites on
198/// `ProcessSpec` ([`crate::intent::Intent`],
199/// [`crate::encapsulates::EncapsulationKind`],
200/// [`crate::export::ArtifactSource`],
201/// [`crate::export::VectorChannel`]) pre-lift restated the same three
202/// impl blocks by hand:
203///
204/// 1. `impl $parent { pub fn variant(&self) -> Result<$variant<'_>, $err> { ... } }`
205///    — a one-line delegation to the [`TaggedUnion::variant`] default
206///    body, plus 5 lines of rustdoc cross-referencing the other three
207///    sibling `.variant()` sites verbatim.
208/// 2. `impl VariantSelector<$parent> for $kind { type Variant<'a> = $variant<'a>; fn select(...) { <$kind>::select(self, parent) } }`
209///    — 6 lines whose only per-site knobs are (`$parent`, `$kind`,
210///    `$variant`); the trait method body a straight delegation to the
211///    inherent `<$kind>::select`.
212/// 3. `impl TaggedUnion for $parent { type Kind = $kind; type Error = $err; const KIND_LIST = $kind_list; }`
213///    — 3 associated-item assignments whose only per-site knobs are
214///    the (`$kind`, `$err`, `$kind_list`) tuple.
215///
216/// The macro takes the (`$parent`, `$kind`, `$variant`, `$err`,
217/// `$kind_list`) five-tuple as named arguments and emits all three
218/// blocks. A fifth sibling tagged-union parent picks up all three
219/// impls through ONE macro call — no re-authored inherent
220/// `.variant()` forwarder, no re-authored `impl VariantSelector`
221/// block, no re-authored `impl TaggedUnion` block.
222///
223/// The emitted inherent `.variant()`'s rustdoc is canonical (names
224/// the substrate primitive, not the exact set of sibling sites) so
225/// a fifth sibling doesn't drift the cross-ref count against reality
226/// merely by existing.
227///
228/// # Example
229///
230/// ```ignore
231/// declare_tagged_union_impls! {
232///     parent = Intent,
233///     kind = IntentKind,
234///     variant = IntentVariant,
235///     error = IntentError,
236///     kind_list = INTENT_KIND_LIST,
237/// }
238/// ```
239///
240/// Expands to the inherent `Intent::variant`, the
241/// `VariantSelector<Intent>` impl on `IntentKind`, and the
242/// `TaggedUnion` impl on `Intent`.
243#[macro_export]
244macro_rules! declare_tagged_union_impls {
245    (
246        parent = $parent:ty,
247        kind = $kind:ty,
248        variant = $variant:ident,
249        error = $err:ty,
250        kind_list = $kind_list:expr $(,)?
251    ) => {
252        impl $parent {
253            /// Resolve to exactly one variant. Errors on zero or many.
254            ///
255            /// One-line inherent forwarder that delegates the sweep
256            /// body to the substrate primitive
257            /// [`crate::tagged_union::TaggedUnion::variant`] — every
258            /// production `.variant()` site on `ProcessSpec` dispatches
259            /// through this ONE default body so the resolve-sweep
260            /// pattern lives at ONE substrate site. The inherent surface
261            /// stays load-bearing so consumer callsites don't need
262            /// `use TaggedUnion`.
263            pub fn variant(&self) -> ::std::result::Result<$variant<'_>, $err> {
264                <Self as $crate::tagged_union::TaggedUnion>::variant(self)
265            }
266        }
267
268        impl $crate::tagged_union::VariantSelector<$parent> for $kind {
269            type Variant<'a> = $variant<'a>;
270            fn select<'a>(self, parent: &'a $parent) -> ::std::option::Option<$variant<'a>>
271            where
272                Self: 'a,
273            {
274                <$kind>::select(self, parent)
275            }
276        }
277
278        impl $crate::tagged_union::TaggedUnion for $parent {
279            type Kind = $kind;
280            type Error = $err;
281            const KIND_LIST: &'static str = $kind_list;
282        }
283    };
284}
285
286/// Project the borrowed-view of a tagged-union variant addressed by
287/// this closed-set discriminator.
288///
289/// Companion trait to [`TaggedUnion`] — binds a `Kind` closed-set to
290/// the parent `P` it discriminates AND to the borrowed-view
291/// [`Self::Variant<'a>`] the resolver hands out. Every one of the
292/// four production `.variant()` sites on `ProcessSpec`
293/// ([`crate::intent::Intent`], [`crate::encapsulates::EncapsulationKind`],
294/// [`crate::export::ArtifactSource`], [`crate::export::VectorChannel`])
295/// pre-lift restated the same
296/// `Self::Kind::ALL.into_iter().map(|k| k.select(self))` sweep body
297/// verbatim at its inherent `.variant()`. Post-lift the trait binds
298/// `(k.select(self), Variant<'a>)` onto ONE typed contract per Kind
299/// so [`TaggedUnion::variant`]'s default body can dispatch the sweep
300/// generically — the four sibling inherent bodies collapse to
301/// one-line delegations and a fifth sibling picks up the sweep for
302/// free through ONE `impl VariantSelector` block.
303///
304/// The GAT `Variant<'a>` carries the parent's lifetime so a borrowed
305/// view projected from `&'a P` composes typed with the resolver's
306/// short-circuit — every projection stays a compile-time refinement,
307/// no `Box<dyn ...>` erasure. The GAT is additionally bound to
308/// [`VariantKind<Self>`] so every implementor's borrowed view knows
309/// its addressing Kind — the reverse projection of [`Self::select`]
310/// closed at compile-time so a fifth sibling that adds `impl
311/// VariantSelector` without opening the peer `impl VariantKind` fails
312/// at the trait bound, not later at a per-consumer round-trip test.
313pub trait VariantSelector<P: ?Sized>: Copy + 'static {
314    /// The borrowed-view enum returned by the parent's inherent
315    /// `.variant()` method — one arm per closed-set variant, each
316    /// arm carrying a `&'a` reference into the parent's populated
317    /// slot. Bound generically here so [`TaggedUnion::variant`]'s
318    /// default body can name the return type without restating it
319    /// per parent. Additionally bound to [`VariantKind<Self>`] so
320    /// the reverse projection `Variant<'a> → Self` is closed at the
321    /// trait boundary — every implementor's borrowed view knows its
322    /// addressing Kind through ONE typed contract, and the substrate
323    /// testkit [`assert_variant_round_trip`] composes `select`
324    /// (forward) with `variant_kind` (reverse) generically.
325    type Variant<'a>: VariantKind<Self>
326    where
327        P: 'a,
328        Self: 'a;
329
330    /// Project a `&'a P` borrow into the optional typed variant view
331    /// for `self` (the addressed discriminator). Returns `None` iff
332    /// the matching slot on `P` is `None`. Composes the closed-set
333    /// sweep [`TaggedUnion::variant`] loops over.
334    fn select<'a>(self, parent: &'a P) -> Option<Self::Variant<'a>>
335    where
336        Self: 'a;
337}
338
339/// Reverse projection — every borrowed-variant view enum knows its
340/// closed-set `K` discriminator.
341///
342/// Dual of [`VariantSelector<P>::select`] on the addressed Kind:
343/// where the selector projects a parent borrow forward into an
344/// optional Variant, this trait projects a populated Variant back
345/// into the Kind that addresses it. Together they compose the
346/// round-trip contract every tagged-union `.variant()` site pins
347/// via the substrate testkit [`assert_variant_round_trip`]:
348/// `k.select(&parent).map(|v| v.variant_kind()) == Some(k)` on the
349/// populated side, and `parent.variant().unwrap().variant_kind() == k`
350/// through the [`TaggedUnion::variant`] resolver's default body.
351///
352/// Every borrowed-view enum on `ProcessSpec`'s tagged-union axis
353/// ([`crate::intent::IntentVariant<'_>`],
354/// [`crate::lifetime::LifetimeVariant<'_>`],
355/// [`crate::encapsulates::EncapsulationKindVariant<'_>`],
356/// [`crate::export::ArtifactVariant<'_>`],
357/// [`crate::export::ChannelVariant<'_>`]) pre-lift restated the same
358/// `match self { Self::A(_) => K::A, Self::B(_) => K::B, ... }`
359/// per-arm mapping at its own inherent method (named `.kind()` on
360/// four of five sites; `.target()` on
361/// [`crate::encapsulates::EncapsulationKindVariant`] where the
362/// discriminator's semantic role is a target of encapsulation, not
363/// a kind of parent). The reverse-projection body must stay
364/// per-implementor — it names the ground-truth arm-to-Kind mapping
365/// only the site knows — but the CONTRACT lives at ONE typed
366/// surface so:
367///
368/// * Every downstream generic consumer binds through
369///   `<T::Variant<'_> as VariantKind<T::Kind>>::variant_kind(&v)`
370///   instead of a per-parent inherent-method restatement.
371/// * [`VariantSelector<P>::Variant<'a>`] bounds this trait — a
372///   fifth sibling that adds `impl VariantSelector<P> for XKind`
373///   without the peer `impl VariantKind<XKind> for XVariant<'_>`
374///   fails at the associated-type bound, so the reverse projection
375///   is closed at compile-time across every implementor.
376/// * The generic testkit [`assert_variant_round_trip`] composes
377///   `select` (forward) with `variant_kind` (reverse) at ONE
378///   substrate site — the four sibling
379///   `_kind_round_trips_through_variant_kind` /
380///   `_target_round_trips_through_variant_target` test bodies
381///   collapse to one-line invocations.
382///
383/// The trait method is named [`Self::variant_kind`] rather than
384/// `kind` to avoid shadowing the inherent `.kind()` (or
385/// `.target()`) methods each borrowed-view enum already publishes.
386/// Every impl body is a one-line delegation to the site's inherent
387/// method — the substrate stays the projection, not the mapping.
388pub trait VariantKind<K: Copy + 'static> {
389    /// Project a borrowed-variant view back into its addressing
390    /// closed-set `K` discriminator. Round-trips the closed set on
391    /// the populated side against [`VariantSelector::select`] — a
392    /// value returned by `k.select(&parent).unwrap()` must satisfy
393    /// `variant_kind() == k`, and a value returned by
394    /// `parent.variant().unwrap()` must satisfy `variant_kind() ==
395    /// k` for the populated slot's `k`.
396    fn variant_kind(&self) -> K;
397}
398
399/// Generic round-trip testkit — pins that
400/// [`VariantSelector::select`] (forward projection) and
401/// [`VariantKind::variant_kind`] (reverse projection) compose the
402/// closed set in both directions on the populated side.
403///
404/// Substrate primitive for the four sibling
405/// `_kind_round_trips_through_variant_kind` /
406/// `_target_round_trips_through_variant_target` tests on
407/// `ProcessSpec` ([`crate::intent::Intent`],
408/// [`crate::encapsulates::EncapsulationKind`],
409/// [`crate::export::ArtifactSource`],
410/// [`crate::export::VectorChannel`]) that pre-lift each restated the
411/// same two-arm round-trip probe at their own test bodies:
412///
413/// 1. For each `k in K::ALL`, construct a parent with only slot `k`
414///    populated (via a site-local `single_slot_X(k) -> Parent`
415///    helper).
416/// 2. Assert that `k.select(&parent).unwrap().variant_kind() == k`
417///    (the forward-then-reverse round-trip).
418/// 3. Assert that `parent.variant().unwrap().variant_kind() == k`
419///    (the resolver-then-reverse round-trip).
420///
421/// Post-lift each site's round-trip test collapses to ONE
422/// `assert_variant_round_trip::<T, _>(single_slot_X)` invocation
423/// whose body is the substrate primitive's own dispatch. A fifth
424/// sibling picks up the round-trip check through ONE call site.
425///
426/// The `make_parent` closure stays per-site — every one of the four
427/// production sites already owns a
428/// `single_slot_intent(k) / single_slot_source(k) /
429/// single_slot_channel(k) / single_slot_kind(t)` helper that
430/// constructs a minimally-valid parent with the addressed slot's
431/// inner spec populated; the closure IS the round-trip's ground
432/// truth for "populate slot k", and lifting it into the primitive
433/// would collapse the per-site construction knowledge that stays
434/// deliberately local.
435///
436/// The [`crate::lifetime::Lifetime`] site is DELIBERATELY excluded
437/// — `Lifetime` doesn't impl [`TaggedUnion`] (its `variant()` returns
438/// `Ok(Permanent)` on empty, not an `Empty` typed error), so the
439/// `<T: TaggedUnion>` bound doesn't reach it. Its per-site
440/// round-trip test binds through [`VariantKind`] directly on
441/// [`crate::lifetime::LifetimeVariant`] instead.
442#[track_caller]
443pub fn assert_variant_round_trip<T, F>(make_parent: F)
444where
445    T: TaggedUnion,
446    T::Kind: PartialEq + std::fmt::Debug,
447    F: Fn(T::Kind) -> T,
448{
449    for k in <T::Kind as tatara_closed_set::ClosedSet>::ALL
450        .iter()
451        .copied()
452    {
453        let parent = make_parent(k);
454        let selected = k.select(&parent).unwrap_or_else(|| {
455            panic!("VariantSelector::select must return Some for populated slot {k:?}")
456        });
457        assert_eq!(
458            <<T::Kind as VariantSelector<T>>::Variant<'_> as VariantKind<T::Kind>>::variant_kind(
459                &selected,
460            ),
461            k,
462            "select→variant_kind round-trip failed for {k:?}",
463        );
464        let resolved = parent.variant().ok().unwrap_or_else(|| {
465            panic!("TaggedUnion::variant must resolve exactly-one populated for {k:?}")
466        });
467        assert_eq!(
468            <<T::Kind as VariantSelector<T>>::Variant<'_> as VariantKind<T::Kind>>::variant_kind(
469                &resolved,
470            ),
471            k,
472            "variant()→variant_kind resolver disagreed on {k:?}",
473        );
474    }
475}
476
477/// Declarative surface that names the (Kind, Error, KIND_LIST) triple
478/// a tagged-union `.variant()` site publishes to the substrate — and
479/// provides the sweep body as ONE default method every implementor
480/// picks up for free.
481///
482/// Every one of the four production `.variant()` sites on `ProcessSpec`
483/// ([`crate::intent::Intent`], [`crate::encapsulates::EncapsulationKind`],
484/// [`crate::export::ArtifactSource`], [`crate::export::VectorChannel`])
485/// exposes the SAME three-piece surface: a closed-set discriminator
486/// [`Self::Kind`], a typed [`Self::Error`] carrier that projects onto
487/// the shared [`TaggedUnionError`] contract, and a slash-joined
488/// operator diagnostic literal [`Self::KIND_LIST`]. Pre-lift the
489/// triple lived on each parent type as independent inherent items —
490/// the (Kind, Error) types cross-referenced only by module-doc prose,
491/// the `KIND_LIST` `&'static str` maintained separately at each site
492/// alongside the inherent `.variant()` body. Post-lift the trait
493/// binds the three onto ONE typed contract per parent so downstream
494/// generic code binds to `<T: TaggedUnion>` instead of restating the
495/// per-parent quadruple of associated names.
496///
497/// The [`Self::variant`] default method is the substrate primitive
498/// every inherent `.variant()` on the four production sites delegates
499/// to — one-line inherent forwarders preserve the load-bearing
500/// calling convention (so no downstream callsite needs
501/// `use crate::tagged_union::TaggedUnion` to reach `.variant()`) while
502/// the resolve-sweep body lives at ONE substrate site. Adding a fifth
503/// sibling means ONE `impl TaggedUnion` block + ONE
504/// `impl VariantSelector<Self>` block on the sibling `Kind` + ONE
505/// one-line inherent forwarder — no re-authored 5-line
506/// `resolve_or_err(K::ALL.into_iter().map(|k| k.select(self)),
507/// KIND_LIST)` sweep body.
508///
509/// The `Kind` type is bound to [`tatara_closed_set::ClosedSet`] so
510/// generic testkit primitives (starting with
511/// [`assert_kind_list_matches_closed_set`]) can compose
512/// `<Self::Kind as ClosedSet>::labels_joined("/")` against
513/// [`Self::KIND_LIST`] byte-identically across every implementor —
514/// the diagnostic-stability invariant every sibling pre-lift pinned
515/// through a hand-rolled per-site test body. It is additionally
516/// bound to [`VariantSelector<Self>`] so [`Self::variant`]'s default
517/// body reaches `k.select(self)` generically.
518///
519/// The [`crate::lifetime::Lifetime`] site is DELIBERATELY not routed
520/// through this trait — its `variant()` returns `Ok(Permanent)` on
521/// empty rather than an `Empty` typed error, so its projection shape
522/// diverges from the four Empty-projecting siblings. Same reasoning
523/// as [`resolve_or_err`]'s explicit exclusion of `Lifetime`.
524pub trait TaggedUnion: Sized {
525    /// The closed-set discriminator over this tagged-union's variants.
526    /// Bound to [`tatara_closed_set::ClosedSet`] so the generic
527    /// diagnostic-stability testkit ([`assert_kind_list_matches_closed_set`])
528    /// can project `<Self::Kind as ClosedSet>::labels_joined("/")`
529    /// against [`Self::KIND_LIST`] byte-identically. Additionally
530    /// bound to [`VariantSelector<Self>`] so [`Self::variant`]'s
531    /// default body can dispatch `k.select(self)` at each
532    /// [`ClosedSet::ALL`] entry generically.
533    type Kind: tatara_closed_set::ClosedSet + VariantSelector<Self>;
534
535    /// The typed error carrier returned by the parent's inherent
536    /// `.variant()` method — projects onto the shared
537    /// [`TaggedUnionError`] contract so [`resolve_or_err`]'s two-arm
538    /// dispatch reaches every implementor uniformly.
539    type Error: TaggedUnionError;
540
541    /// Slash-joined operator diagnostic literal — the payload of
542    /// [`TaggedUnionError::empty`] when no slot is populated on this
543    /// tagged union. Pinned against
544    /// `<Self::Kind as tatara_closed_set::ClosedSet>::labels_joined("/")`
545    /// by [`assert_kind_list_matches_closed_set`] so a variant added
546    /// to `Self::Kind` without updating this constant (or a renamed
547    /// variant) fails-loudly at the testkit boundary.
548    const KIND_LIST: &'static str;
549
550    /// Sweep over every [`Self::Kind`] discriminator in
551    /// [`ClosedSet::ALL`](tatara_closed_set::ClosedSet::ALL) order,
552    /// projecting each into the parent's borrowed variant view via
553    /// [`VariantSelector::select`], and resolve to exactly one populated
554    /// variant through [`resolve_or_err`]. Errors on zero (with
555    /// [`Self::KIND_LIST`] carried on the [`TaggedUnionError::empty`]
556    /// arm) or many.
557    ///
558    /// The substrate primitive every one of the four production
559    /// `.variant()` sites on `ProcessSpec` dispatches through — the
560    /// per-parent inherent `.variant()` is a one-line delegation to
561    /// this default so the calling convention (`intent.variant()`,
562    /// `channel.variant()`, ...) stays load-bearing at the callsite
563    /// without every consumer picking up `use TaggedUnion`.
564    ///
565    /// Adding a fifth sibling picks up this body for free — no
566    /// re-authored `resolve_or_err(...)` sweep at the impl block.
567    fn variant(&self) -> Result<<Self::Kind as VariantSelector<Self>>::Variant<'_>, Self::Error> {
568        resolve_or_err(
569            <Self::Kind as tatara_closed_set::ClosedSet>::ALL
570                .iter()
571                .copied()
572                .map(|k| k.select(self)),
573            Self::KIND_LIST,
574        )
575    }
576}
577
578/// Generic diagnostic-stability testkit — pins that [`TaggedUnion::KIND_LIST`]
579/// matches `<T::Kind as tatara_closed_set::ClosedSet>::labels_joined("/")`
580/// byte-identically for every implementor.
581///
582/// Substrate primitive for the four sibling
583/// `_error_empty_lists_every_kind_in_canonical_order` tests on
584/// `ProcessSpec` ([`crate::intent::Intent`],
585/// [`crate::encapsulates::EncapsulationKind`],
586/// [`crate::export::ArtifactSource`], [`crate::export::VectorChannel`])
587/// that pre-lift each restated the same
588/// `assert_eq!(<XxxKind as ClosedSet>::labels_joined("/"),
589/// XXX_KIND_LIST)` two-argument comparison at their own test bodies —
590/// byte-identical projections whose only per-carrier knobs (the Kind
591/// type + the KIND_LIST constant) are the two associated items the
592/// [`TaggedUnion`] trait names. Post-lift each site collapses to ONE
593/// `assert_kind_list_matches_closed_set::<Xxx>()` invocation whose
594/// body is the substrate primitive's own dispatch.
595///
596/// A fifth sibling tagged-union parent picks up the diagnostic-
597/// stability check through ONE `impl TaggedUnion for X` block + ONE
598/// `assert_kind_list_matches_closed_set::<X>()` call site — no
599/// re-authored `<XKind as ClosedSet>::labels_joined("/")` composition
600/// at the test site, no re-authored per-site `assert_eq!` pair.
601#[track_caller]
602pub fn assert_kind_list_matches_closed_set<T: TaggedUnion>() {
603    let derived = <T::Kind as tatara_closed_set::ClosedSet>::labels_joined("/");
604    assert_eq!(
605        derived,
606        T::KIND_LIST,
607        "TaggedUnion KIND_LIST drift — must equal <T::Kind as ClosedSet>::labels_joined(\"/\")",
608    );
609}
610
611/// Generic ambiguity testkit — pins that [`TaggedUnion::variant`]
612/// resolves to [`TaggedUnionError::ambiguous`] on EVERY off-diagonal
613/// `(a, b)` pair in [`ClosedSet::ALL`](tatara_closed_set::ClosedSet::ALL)
614/// `× ALL`.
615///
616/// Substrate primitive for the sibling
617/// `_two_slots_is_ambiguous_across_every_pair` tests on `ProcessSpec`
618/// ([`crate::encapsulates::EncapsulationKind`],
619/// [`crate::export::ArtifactSource`], [`crate::export::VectorChannel`])
620/// that pre-lift each restated the same nested-`for a in K::ALL { for
621/// b in K::ALL { if a == b { continue; } … } }` sweep at their own
622/// test bodies — byte-identical projections whose only per-carrier
623/// knobs are the (Kind type + the `two_slot_X(a, b) -> Parent`
624/// two-slot factory) pair. Post-lift each site collapses to ONE
625/// `assert_two_slots_ambiguous::<Xxx, _>(two_slot_X)` invocation.
626///
627/// The `two_slot` closure stays per-site — every one of the three
628/// production sites already owns a `two_slot_kind /
629/// two_slot_source / two_slot_channel` helper that composes two
630/// `single_slot_X`s per-field. The closure IS the "populate both
631/// slots a and b" ground truth for the carrier's field structure;
632/// lifting it into the primitive would collapse per-site field-
633/// composition knowledge that stays deliberately local.
634///
635/// The pair sweep excludes the diagonal (`a == b`) — a single slot
636/// populated is exactly-one, not many, and the round-trip primitive
637/// [`assert_variant_round_trip`] already pins that populated slot's
638/// resolution. This primitive is the peer contract for the Many arm.
639///
640/// A fifth sibling tagged-union parent picks up the ambiguity check
641/// through ONE `impl TaggedUnion for X` block + ONE per-site
642/// `two_slot_X` helper + ONE `assert_two_slots_ambiguous::<X, _>`
643/// call site — no re-authored nested-for sweep at the test surface,
644/// no re-authored `assert_eq!(..., X::Error::Ambiguous, ...)` arm.
645///
646/// The [`crate::lifetime::Lifetime`] site is DELIBERATELY excluded
647/// — `Lifetime` doesn't impl [`TaggedUnion`] (its error carrier has
648/// no `Empty` arm; its `variant()` returns `Ok(Permanent)` on empty
649/// rather than an `Empty` typed error), so the `<T: TaggedUnion>`
650/// bound doesn't reach it. Its per-site ambiguity assertion binds
651/// through the inherent `.variant()` + hand-authored two-slot
652/// probe. Same reasoning as [`resolve_or_err`]'s and
653/// [`assert_variant_round_trip`]'s exclusions.
654#[track_caller]
655pub fn assert_two_slots_ambiguous<T, F>(two_slot: F)
656where
657    T: TaggedUnion,
658    T::Kind: PartialEq + std::fmt::Debug,
659    T::Error: PartialEq + std::fmt::Debug,
660    F: Fn(T::Kind, T::Kind) -> T,
661{
662    let expected = T::Error::ambiguous();
663    for a in <T::Kind as tatara_closed_set::ClosedSet>::ALL
664        .iter()
665        .copied()
666    {
667        for b in <T::Kind as tatara_closed_set::ClosedSet>::ALL
668            .iter()
669            .copied()
670        {
671            if a == b {
672                continue;
673            }
674            let parent = two_slot(a, b);
675            let err = parent.variant().err().unwrap_or_else(|| {
676                panic!("({a:?}, {b:?}) two-slot parent must not resolve to a variant")
677            });
678            assert_eq!(err, expected, "({a:?}, {b:?}) should resolve Ambiguous");
679        }
680    }
681}
682
683/// Generic wire-key / kind-label alignment testkit — pins that every
684/// single-slot parent serializes to a JSON object with EXACTLY ONE key
685/// whose name equals `<T::Kind as tatara_closed_set::ClosedSet>::label`
686/// on the populated slot's kind.
687///
688/// Substrate primitive for the four sibling
689/// `X_kind_as_str_matches_field_name` / `intent_kind_as_str_matches_intent_field_name`
690/// tests on `ProcessSpec` ([`crate::intent::Intent`],
691/// [`crate::encapsulates::EncapsulationKind`],
692/// [`crate::export::ArtifactSource`], [`crate::export::VectorChannel`])
693/// that pre-lift each restated the same wire-format sweep at their own
694/// test bodies:
695///
696/// 1. For each `k in K::ALL`, construct a single-slot parent via
697///    the site-local `single_slot_X(k) -> Parent` factory.
698/// 2. Serialize it to the wire format and assert that the emitted
699///    key matches `k.as_str()`.
700///
701/// Post-lift each site's alignment test collapses to ONE
702/// `assert_single_slot_key_matches_label::<T, _>(single_slot_X)`
703/// invocation whose body IS the substrate primitive's own dispatch.
704/// A fifth sibling picks up the alignment check through ONE call site.
705///
706/// The primitive projects through `serde_json::to_value` rather than
707/// `serde_yaml::to_string` for two reasons: (1) the check is
708/// structural (exactly-one-key + name equality), not textual (substring
709/// against a `"{key}:"` YAML fragment), so a future site that gains
710/// non-tagged-union metadata fields is caught HERE at the exactly-one
711/// arm — the YAML-substring check the three encapsulates / export sites
712/// carried pre-lift would silently pass on such drift. (2) serde's
713/// field-rename projection (`rename_all = "camelCase"`) is format-
714/// agnostic, so a JSON check pins the SAME invariant a YAML check
715/// would pin, byte-identically. Every one of the four production
716/// parents already emits exactly one key on a single-slot populate —
717/// their `#[serde(default, skip_serializing_if = "Option::is_none")]`
718/// annotations on every tagged-union slot guarantee it — so upgrading
719/// the three YAML sites to the JSON exactly-one check is a strict
720/// strengthening.
721///
722/// The `single_slot` closure stays per-site — every one of the four
723/// production sites already owns a `single_slot_intent /
724/// single_slot_kind / single_slot_source / single_slot_channel` helper
725/// that constructs a minimally-valid parent with the addressed slot's
726/// inner spec populated; the closure IS the "populate slot k" ground
727/// truth for the carrier's field structure. Reused verbatim from the
728/// [`assert_variant_round_trip`] primitive.
729///
730/// The [`crate::lifetime::Lifetime`] site is DELIBERATELY excluded
731/// from THIS trait-projected surface — `Lifetime` doesn't impl
732/// [`TaggedUnion`] (its `variant()` returns `Ok(Permanent)` on empty
733/// rather than an `Empty` typed error), so the `<T: TaggedUnion>`
734/// bound doesn't reach it. The bound-relaxed peer
735/// [`assert_wire_key_matches_label`] carries the SAME sweep body
736/// under `<T: Serialize>` + `<K: ClosedSet>` alone — Lifetime binds
737/// through it directly and this trait-projected surface becomes a
738/// one-line delegation whose only load-bearing purpose is to name
739/// the TaggedUnion parent's `T::Kind` associated type at the call
740/// site (existing `assert_single_slot_key_matches_label::<T, _>(f)`
741/// callers stay unchanged; the peer inflects the same body onto
742/// non-TaggedUnion parents).
743#[track_caller]
744pub fn assert_single_slot_key_matches_label<T, F>(single_slot: F)
745where
746    T: TaggedUnion + serde::Serialize,
747    T::Kind: PartialEq + std::fmt::Debug,
748    F: Fn(T::Kind) -> T,
749{
750    assert_wire_key_matches_label::<T, T::Kind, F>(single_slot);
751}
752
753/// Bound-relaxed peer of [`assert_single_slot_key_matches_label`] —
754/// the SAME wire-key alignment sweep, but on any `(K, T)` pair where
755/// `K: ClosedSet` addresses `T: Serialize` through a caller-supplied
756/// `single_slot: Fn(K) -> T` factory. Drops the `T: TaggedUnion`
757/// bound the sibling primitive carries so parents whose empty
758/// resolution shape diverges from the tagged-union convention (the
759/// canonical example: [`crate::lifetime::Lifetime`], whose empty
760/// resolves to `Permanent(&DEFAULT_PERMANENT)` rather than to an
761/// [`TaggedUnionError::empty`] carrier) still bind through ONE
762/// substrate wire-key alignment site.
763///
764/// The two primitives share ONE sweep body; the trait-projected
765/// [`assert_single_slot_key_matches_label`] is now a one-line
766/// delegation to this bound-relaxed peer, so every drift-arm the
767/// sibling `#[should_panic]` probe pins on the delegating surface
768/// mechanically pins here too. The compounding gain: a fifth parent
769/// whose closed-set kind K doesn't ride the TaggedUnion trait (a
770/// future variant surface with a default-arm on empty; a wire-only
771/// enum whose parent is a wrapper struct that never publishes a
772/// resolver; a K-addressed `HashMap<K, Payload>` where the payload
773/// isn't a tagged-union variant carrier at all) picks up wire-key
774/// alignment through ONE call site — no re-authored serialize +
775/// exactly-one-key + name-equality body at the test surface, no
776/// per-parent drift risk where the trait-projected surface catches
777/// it and the bespoke surface forgets.
778///
779/// The primitive binds `<K: ClosedSet + PartialEq + Debug>` (the
780/// strict union of the sweep body's projection + the panic-message
781/// substrate-wide shape) — every production `ClosedSet` implementor
782/// across the crate carries `Debug + PartialEq` through the
783/// substrate-wide `#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash,
784/// DeriveClosedSet)]` shape, so no site pays a bound-widening cost
785/// to bind through this peer.
786#[track_caller]
787pub fn assert_wire_key_matches_label<T, K, F>(single_slot: F)
788where
789    T: serde::Serialize,
790    K: tatara_closed_set::ClosedSet + PartialEq + std::fmt::Debug,
791    F: Fn(K) -> T,
792{
793    for k in <K as tatara_closed_set::ClosedSet>::ALL.iter().copied() {
794        let parent = single_slot(k);
795        let value = serde_json::to_value(&parent)
796            .unwrap_or_else(|e| panic!("single_slot({k:?}) must serialize as JSON: {e}"));
797        let obj = value.as_object().unwrap_or_else(|| {
798            panic!("single_slot({k:?}) must serialize to a JSON object, got {value}")
799        });
800        let keys: Vec<&String> = obj.keys().collect();
801        assert_eq!(
802            keys.len(),
803            1,
804            "single_slot({k:?}) must serialize to exactly one populated field, got keys: {keys:?}",
805        );
806        let expected = <K as tatara_closed_set::ClosedSet>::label(k);
807        assert_eq!(
808            keys[0].as_str(),
809            expected,
810            "wire-key drift for {k:?}: single_slot's populated field '{}' must equal <K as ClosedSet>::label ({expected:?})",
811            keys[0],
812        );
813    }
814}
815
816/// Generic Display / [`ClosedSet::label`](tatara_closed_set::ClosedSet::label)
817/// alignment testkit — pins that [`core::fmt::Display`] renders each variant
818/// BYTE-IDENTICALLY to the trait-visible `ClosedSet::label` projection for
819/// every implementor.
820///
821/// Substrate primitive for the 29 sibling
822/// `X_display_matches_as_str` tests across `tatara-process`
823/// (`AllocationPhase`, `IntentKind`, `WorkloadKind`, `EncapsulationMode`,
824/// `EncapsulationTarget`, `ConditionKind`, `TerminateReasonKind`,
825/// `AutoTerminateKind`, `SighupStrategy`, `ReplacementPolicy`,
826/// `ReturnPolicy`, `MemberState`, `PoolPhase`, `VerificationPhase`,
827/// `SelectStrategyKind`, `MustReachPhase`, `ExportTrigger`,
828/// `ReportFormat`, `ReportPayloadShape`, `ArtifactKind`, `ChannelKind`,
829/// `DataClassification`, `ConvergencePointType`, `Arity`,
830/// `SubstrateType`, `CalmClassification`, `OptimizationDirection`,
831/// `HorizonKind`, `TeardownPolicy`) that pre-lift each restated the
832/// same
833/// ```text
834/// for v in K::ALL {
835///     assert_eq!(v.to_string(), v.as_str());
836/// }
837/// ```
838/// two-line probe verbatim at their own test bodies — byte-identical
839/// projections whose only per-carrier knob is the closed-set type name.
840/// Post-lift each site collapses to ONE
841/// `assert_display_matches_label::<X>()` invocation whose body IS the
842/// substrate primitive's own dispatch.
843///
844/// The primitive projects through the STABLE trait-visible name
845/// [`ClosedSet::label`](tatara_closed_set::ClosedSet::label) rather
846/// than the inherent `.as_str()` each site publishes locally. Every
847/// production implementor here derives its `label` body from `as_str`
848/// via `#[closed_set(via = "as_str", display)]` (the substrate-wide
849/// derive shape), so the two are byte-identical by construction; the
850/// primitive's projection through `label` therefore pins the SAME
851/// invariant the pre-lift bodies pinned while binding to the
852/// stable trait-visible surface. A future implementor whose inherent
853/// canonical projection is named something other than `as_str` (e.g.
854/// `.keyword()`, `.spelling()`) but still routes through
855/// `#[closed_set(via = "...", display)]` picks up the alignment check
856/// through ONE `assert_display_matches_label::<X>()` invocation with
857/// no inherent-name coupling at the test site.
858///
859/// A fifth (or thirtieth, or hundredth) implementor picks up the
860/// Display-alignment check through ONE
861/// `#[derive(tatara_closed_set::DeriveClosedSet)]` + `display`
862/// attribute + ONE `assert_display_matches_label::<X>()` call site —
863/// no re-authored two-line
864/// `for v in K::ALL { assert_eq!(v.to_string(), v.as_str()) }` body
865/// at the test surface, no per-site drift risk where 28 sibling
866/// tests carry the assertion and the 29th forgets.
867///
868/// Sibling shape to [`assert_kind_list_matches_closed_set`] on the
869/// (`T::KIND_LIST` slash-join, `Display` byte-identity) axis: both
870/// project the closed-set's label surface onto ONE typed contract
871/// and pin it against a per-implementor rendering; the former for
872/// the tagged-union parent's [`TaggedUnion::KIND_LIST`] `&'static str`,
873/// this one for the enum's `Display` byte stream. Together they close
874/// the "label surface must round-trip verbatim" invariant every
875/// closed-set-carrying implementor across the crate publishes.
876#[track_caller]
877pub fn assert_display_matches_label<T>()
878where
879    T: tatara_closed_set::ClosedSet + core::fmt::Display + PartialEq + core::fmt::Debug,
880{
881    let type_name = core::any::type_name::<T>();
882    for &v in <T as tatara_closed_set::ClosedSet>::ALL {
883        let rendered = v.to_string();
884        let expected = <T as tatara_closed_set::ClosedSet>::label(v);
885        assert_eq!(
886            rendered.as_str(),
887            expected,
888            "{type_name}: Display drifted from ClosedSet::label for {v:?} — expected {expected:?}, got {rendered:?}",
889        );
890    }
891}
892
893/// CANONICAL-KEY CONTRACT testkit — pins that each variant's serde
894/// serialization (as a JSON string value, unquoted) matches its
895/// canonical [`ClosedSet::label`](tatara_closed_set::ClosedSet::label)
896/// projection BYTE-IDENTICALLY for every implementor.
897///
898/// Substrate primitive for the 20 sibling
899/// `X_as_str_matches_serde` tests across `tatara-process`
900/// (`TeardownPolicy`, `EncapsulationMode`, `ConditionKind`,
901/// `SighupStrategy`, `ReplacementPolicy`, `ReturnPolicy`, `MemberState`,
902/// `PoolPhase`, `VerificationPhase`, `MustReachPhase`, `WorkloadKind`,
903/// `ExportTrigger`, `ReportFormat`, `DataClassification`,
904/// `ConvergencePointType`, `SubstrateType`, `CalmClassification`,
905/// `OptimizationDirection`, `HorizonKind`, `AllocationPhase`) that
906/// pre-lift each restated the same
907/// ```text
908/// for v in K::ALL {
909///     let serialized = serde_json::to_string(&v).expect("serialize");
910///     let unquoted = serialized
911///         .trim_start_matches('"')
912///         .trim_end_matches('"')
913///         .to_string();
914///     assert_eq!(unquoted, v.as_str(), "as_str drift for {v:?}: ...");
915/// }
916/// ```
917/// four-line probe verbatim at their own test bodies — byte-identical
918/// projections whose only per-carrier knob is the closed-set type name.
919/// Post-lift each site collapses to ONE
920/// `assert_label_matches_serde_serialization::<X>()` invocation whose
921/// body IS the substrate primitive's own dispatch.
922///
923/// The primitive projects through the STABLE trait-visible name
924/// [`ClosedSet::label`](tatara_closed_set::ClosedSet::label) rather
925/// than the inherent `.as_str()` each site publishes locally. Every
926/// production implementor here derives its `label` body from `as_str`
927/// via `#[closed_set(via = "as_str", display)]` + `#[serde(rename_all
928/// = "PascalCase")]` (the substrate-wide derive shape), so the two are
929/// byte-identical by construction; the primitive's projection through
930/// `label` therefore pins the SAME invariant the pre-lift bodies
931/// pinned while binding to the stable trait-visible surface. A future
932/// implementor whose canonical inherent projection is named something
933/// other than `as_str` (e.g. `.keyword()`, `.spelling()`) but still
934/// routes through `#[closed_set(via = "...")]` picks up the wire-format
935/// alignment check through ONE call with no inherent-name coupling at
936/// the test site.
937///
938/// A twenty-first (or hundredth) implementor picks up the alignment
939/// check through ONE `#[derive(tatara_closed_set::DeriveClosedSet)]` +
940/// `#[derive(serde::Serialize)]` + `#[serde(rename_all = "...")]`
941/// attribute + ONE `assert_label_matches_serde_serialization::<X>()`
942/// call site — no re-authored four-line probe body at the test surface,
943/// no per-site drift risk where 19 sibling tests carry the assertion
944/// and the 20th forgets, no `serde_json::to_string`+`trim_matches`+
945/// `assert_eq!` composition re-derived per implementor.
946///
947/// Sibling shape to [`assert_display_matches_label`] on the
948/// (Display byte-identity, serde-wire-format byte-identity) axis: both
949/// project the closed-set's label surface onto ONE typed contract and
950/// pin it against a per-implementor rendering; the former for the
951/// enum's [`Display`](core::fmt::Display) byte stream, this one for
952/// the serde JSON-string wire format. Together they close the "label
953/// surface renders verbatim across every projection consumers reach
954/// for" invariant every closed-set-carrying implementor across the
955/// crate publishes.
956#[track_caller]
957pub fn assert_label_matches_serde_serialization<T>()
958where
959    T: tatara_closed_set::ClosedSet + serde::Serialize + core::fmt::Debug,
960{
961    let type_name = core::any::type_name::<T>();
962    for &v in <T as tatara_closed_set::ClosedSet>::ALL {
963        let serialized = serde_json::to_string(&v).unwrap_or_else(|e| {
964            panic!("{type_name}: closed-set variant {v:?} must serialize: {e}")
965        });
966        let unquoted = serialized.trim_start_matches('"').trim_end_matches('"');
967        let expected = <T as tatara_closed_set::ClosedSet>::label(v);
968        assert_eq!(
969            unquoted,
970            expected,
971            "{type_name}: serde output drifted from ClosedSet::label for {v:?} — expected {expected:?}, got {unquoted:?} (full serialization {serialized:?})",
972        );
973    }
974}
975
976/// CLOSED-SET CONVENTION PANEL testkit — pins the FULL three-axis
977/// label-surface convention (parse round-trip, Display byte-identity,
978/// serde-JSON-string byte-identity) at ONE substrate call site per
979/// implementor.
980///
981/// Compound-lift of [`tatara_closed_set::assert_closed_set_well_formed`]
982/// + [`assert_display_matches_label`] + [`assert_label_matches_serde_
983/// serialization`] — every closed-set enum on `ProcessSpec` that
984/// carries the substrate-wide `#[derive(DeriveClosedSet)] +
985/// #[derive(Serialize)] + #[closed_set(via = "as_str", display)] +
986/// #[serde(rename_all = "PascalCase")]` shape publishes ALL THREE
987/// axes of the label surface, and pre-lift each production test
988/// module hand-authored three sibling one-line tests
989/// (`X_is_well_formed_closed_set`, `X_display_matches_as_str`,
990/// `X_as_str_matches_serde`) that each restated the SAME
991/// `crate::tagged_union::assert_<axis>::<X>()` invocation with only
992/// the axis name varying between siblings. Post-lift each site
993/// collapses to ONE `assert_closed_set_convention_panel::<X>()`
994/// invocation whose body IS the three-axis composition dispatched
995/// through the substrate primitive here.
996///
997/// The three sub-assertions stay independently callable — a future
998/// implementor that publishes only two of the three axes (a
999/// `Display`-less internal enum, e.g., or a `Serialize`-less
1000/// runtime-only enum) still binds through the two sibling primitives
1001/// individually. The compound is a strict superset: any implementor
1002/// that satisfies the compound's bounds already satisfies each
1003/// sub-assertion's bounds by construction, and the failure mode of
1004/// each sub-assertion still surfaces with the exact-message
1005/// granularity `#[track_caller]` gives the individual primitives
1006/// (the compound is `#[track_caller]` too, so a sub-assertion panic
1007/// surfaces at the compound's call site — a future promotion could
1008/// wrap each sub-assertion in a `std::panic::catch_unwind` to
1009/// aggregate all three axis failures into ONE panic message, but the
1010/// pre-lift discipline is that each axis's failure surfaces with its
1011/// own diagnostic).
1012///
1013/// The compound's bounds are the strict union of the three sub-
1014/// assertions' bounds:
1015///   - [`assert_closed_set_well_formed`] requires
1016///     `T: ClosedSet + PartialEq + Debug` + `T::Unknown: Display`;
1017///   - [`assert_display_matches_label`] requires
1018///     `T: ClosedSet + Display + PartialEq + Debug`;
1019///   - [`assert_label_matches_serde_serialization`] requires
1020///     `T: ClosedSet + Serialize + Debug`.
1021/// The union `T: ClosedSet + Serialize + Display + PartialEq + Debug`
1022/// + `T::Unknown: Display` is what every 3-axis production consumer
1023/// already satisfies through the substrate-wide derive shape — any
1024/// implementor that fails the compound's bounds would ALSO fail the
1025/// individual sub-assertions' bounds, so the compound doesn't shrink
1026/// the reachable set of implementors relative to hand-authoring the
1027/// three sibling calls.
1028///
1029/// A future FOURTH label-surface projection (e.g. a `serde_yaml`
1030/// byte-identity axis if the crate gains a YAML wire form on closed-
1031/// set enums, or a `kubectl_annotation` axis if the reconciler grows
1032/// an annotation-carried label surface) lands as ONE new
1033/// `assert_<axis>_matches_label::<T>()` substrate primitive + ONE
1034/// new line inside this compound's body. Every one of the ~20
1035/// production implementors of the panel picks up the fourth-axis
1036/// alignment check mechanically at their sole `assert_closed_set_
1037/// convention_panel::<X>()` call site — no per-implementor test-site
1038/// authoring, no per-crate test-site drop pathway where 19 sibling
1039/// call sites carry the check and the 20th forgets. The exact
1040/// promise `e4a4eba`'s future gain #2 named after
1041/// `assert_label_matches_serde_serialization` opened the wire-format
1042/// axis: a workspace-wide panel with byte-identical calling shapes
1043/// (`assert_X::<T>()`) that composes as freely as its sub-primitives.
1044///
1045/// Sibling shape to [`assert_variant_round_trip`] +
1046/// [`assert_kind_list_matches_closed_set`] +
1047/// [`assert_two_slots_ambiguous`] +
1048/// [`assert_single_slot_key_matches_label`] on the tagged-union
1049/// PARENT axis: the parent-side compound would compose the four
1050/// parent-side per-axis primitives, this one composes the three
1051/// child-side per-axis primitives on the child's [`ClosedSet`]
1052/// surface. Together the two compounds close the "closed-set
1053/// convention holds across every projection consumers reach for" at
1054/// two adjacent panels — one per closed-set-carrying enum, one per
1055/// tagged-union parent.
1056///
1057/// Theory anchor: THEORY.md §V.1 (knowable platform) — the
1058/// three-axis label-surface convention becomes ONE typed theorem
1059/// provable generically over any
1060/// `T: ClosedSet + Serialize + Display + PartialEq + Debug` bound
1061/// rather than THREE hand-authored per-implementor one-line probes
1062/// held coherent by test-module convention. THEORY.md §II.1
1063/// invariant 5 (composition preserves proofs) — the three sub-
1064/// assertions compose structurally through ONE primitive here, so a
1065/// regression at ONE axis surfaces at the sub-assertion's own
1066/// panic message rather than as silent drift at every consumer that
1067/// might otherwise forget to include the axis in its per-site
1068/// author-time enumeration.
1069#[track_caller]
1070pub fn assert_closed_set_convention_panel<T>()
1071where
1072    T: tatara_closed_set::ClosedSet
1073        + serde::Serialize
1074        + core::fmt::Display
1075        + PartialEq
1076        + core::fmt::Debug,
1077    T::Unknown: core::fmt::Display,
1078{
1079    tatara_closed_set::assert_closed_set_well_formed::<T>();
1080    assert_display_matches_label::<T>();
1081    assert_label_matches_serde_serialization::<T>();
1082}
1083
1084/// TAGGED-UNION CONVENTION PANEL testkit — pins the FULL four-axis
1085/// tagged-union parent convention (KIND_LIST diagnostic-stability,
1086/// variant round-trip on the single-slot side, ALL×ALL two-slot
1087/// ambiguity, wire-key alignment on the single-slot side) at ONE
1088/// substrate call site per parent.
1089///
1090/// Parent-side compound-lift, sibling to
1091/// [`assert_closed_set_convention_panel`] on the child's
1092/// [`tatara_closed_set::ClosedSet`] axis. Composes
1093/// [`assert_kind_list_matches_closed_set`] (no fixture) +
1094/// [`assert_variant_round_trip`] (`single_slot`) +
1095/// [`assert_two_slots_ambiguous`] (`two_slot`) +
1096/// [`assert_single_slot_key_matches_label`] (`single_slot`).
1097///
1098/// Every one of the four production `.variant()` parents on
1099/// `ProcessSpec` ([`crate::intent::Intent`],
1100/// [`crate::encapsulates::EncapsulationKind`],
1101/// [`crate::export::ArtifactSource`],
1102/// [`crate::export::VectorChannel`]) publishes the four-axis
1103/// convention through the shared substrate-wide attribute-set:
1104/// `#[derive(DeriveClosedSet)]` on the addressing `Kind`,
1105/// `declare_tagged_union_impls!` for the resolver+selector+trait
1106/// triple, `#[serde(rename_all = "camelCase")]` +
1107/// `#[serde(default, skip_serializing_if = "Option::is_none")]` on
1108/// every tagged-union slot. Pre-lift each production site
1109/// hand-authored FOUR sibling per-axis tests (`X_kind_round_trips_through_variant_kind`
1110/// / `X_kind_list_matches_ClosedSet_labels` /
1111/// `X_two_slots_are_ambiguous` /
1112/// `X_kind_as_str_matches_field_name`) that each restated the
1113/// SAME `crate::tagged_union::assert_<axis>::<T, _>(fixture)`
1114/// invocation with only the axis name + fixture arity varying
1115/// between siblings. Post-lift each site's four per-axis sibling
1116/// tests can collapse to ONE
1117/// `assert_tagged_union_convention_panel::<T, _, _>(
1118/// single_slot_X, two_slot_X)` invocation whose body IS the
1119/// four-axis composition dispatched through the substrate
1120/// primitive here.
1121///
1122/// The two closures stay per-site — every one of the four
1123/// production parents already owns a `single_slot_X(k) -> Parent`
1124/// / `two_slot_X(a, b) -> Parent` pair, and the substrate-local
1125/// `{single,two}_slot_*_probe` peers (siblings to the wire-key
1126/// sweep's substrate-local probes) let the substrate-wide sweep
1127/// below bind through the compound without reaching across the
1128/// per-crate test-module boundaries. Lifting the two closures
1129/// into the primitive would collapse the per-site construction
1130/// knowledge that stays deliberately local — the closure IS the
1131/// "populate slot k" / "populate the (a, b) pair" ground truth
1132/// for the parent's field structure.
1133///
1134/// Bounds are the strict union of the four sub-assertions' bounds:
1135/// [`assert_kind_list_matches_closed_set`] requires
1136/// `T: TaggedUnion`; [`assert_variant_round_trip`] requires
1137/// `T: TaggedUnion` + `T::Kind: PartialEq + Debug`
1138/// + `F: Fn(T::Kind) -> T`; [`assert_two_slots_ambiguous`] requires
1139/// `T: TaggedUnion` + `T::Kind: PartialEq + Debug`
1140/// + `T::Error: PartialEq + Debug` + `F: Fn(T::Kind, T::Kind) -> T`;
1141/// [`assert_single_slot_key_matches_label`] requires
1142/// `T: TaggedUnion + Serialize` + `T::Kind: PartialEq + Debug`
1143/// + `F: Fn(T::Kind) -> T`. The union
1144/// `T: TaggedUnion + Serialize` + `T::Kind: PartialEq + Debug`
1145/// + `T::Error: PartialEq + Debug` + `F1: Fn(T::Kind) -> T`
1146/// + `F2: Fn(T::Kind, T::Kind) -> T` is what every one of the four
1147/// production parents already satisfies through the shared
1148/// substrate-wide impls — any implementor that fails the compound's
1149/// bounds would ALSO fail the individual sub-assertions' bounds,
1150/// so the compound doesn't shrink the reachable set of
1151/// implementors relative to hand-authoring the four sibling calls.
1152/// The `single_slot` closure is dispatched to
1153/// [`assert_variant_round_trip`] by reference so the compound can
1154/// re-dispatch it to [`assert_single_slot_key_matches_label`] by
1155/// value on the final call — a caller passes ONE `Fn(T::Kind) -> T`
1156/// factory (not `FnOnce`) at the two axes that need it.
1157///
1158/// `#[track_caller]` on both the compound and each sub-primitive,
1159/// so a sub-assertion panic surfaces at the compound's caller site
1160/// with the failing axis's exact panic-message substring
1161/// (e.g. "TaggedUnion KIND_LIST drift", "select→variant_kind
1162/// round-trip failed", "should resolve Ambiguous", "wire-key
1163/// drift"). The four sub-assertions stay independently callable —
1164/// a future parent that publishes only three of the four axes (a
1165/// wire-format-less runtime parent, e.g., or an
1166/// ambiguity-less parent whose `.variant()` short-circuits on
1167/// the first populated slot) still binds through the sibling
1168/// primitives individually.
1169///
1170/// A future FIFTH parent-side projection (e.g. a
1171/// `two_slots_have_stable_diagnostic` axis if the ambiguity error
1172/// gains a per-parent operator-facing message, or a
1173/// `variant_kind_stays_stable_across_generation` axis if the
1174/// resolver's iteration order becomes load-bearing) lands as ONE
1175/// new `assert_<axis>::<T, _>(...)` substrate primitive + ONE new
1176/// line inside this compound's body. Every one of the four
1177/// production parents picks up the fifth-axis alignment check
1178/// mechanically at their sole
1179/// `assert_tagged_union_convention_panel::<T, _, _>(single_slot,
1180/// two_slot)` call site — no per-parent test-site authoring, no
1181/// per-crate test-site drop pathway where 3 sibling call sites
1182/// carry the check and the 4th forgets. The exact promise the
1183/// child-side [`assert_closed_set_convention_panel`] compound's
1184/// docstring named on the child axis, extended here to the parent
1185/// axis: a workspace-wide panel with byte-identical calling shapes
1186/// (`assert_<compound>::<T, _, _>(single_slot, two_slot)`) that
1187/// composes as freely as its sub-primitives.
1188///
1189/// The [`crate::lifetime::Lifetime`] site is DELIBERATELY excluded
1190/// through the `T: TaggedUnion` bound — `Lifetime`'s `variant()`
1191/// returns `Ok(Permanent)` on empty rather than an `Empty` typed
1192/// error, so its projection shape diverges from the four
1193/// Empty-projecting parents. Same reasoning as [`resolve_or_err`]'s
1194/// / [`assert_variant_round_trip`]'s / [`assert_two_slots_ambiguous`]'s
1195/// / [`assert_single_slot_key_matches_label`]'s exclusions.
1196///
1197/// Theory anchor: THEORY.md §V.1 (knowable platform) — the
1198/// four-axis parent-side tagged-union convention becomes ONE typed
1199/// theorem provable generically over any
1200/// `T: TaggedUnion + Serialize` bound rather than FOUR
1201/// hand-authored per-parent tests held coherent by test-module
1202/// convention. THEORY.md §II.1 invariant 5 (composition preserves
1203/// proofs) — the four sub-assertions compose structurally through
1204/// ONE primitive here, so a regression at ONE axis surfaces at the
1205/// sub-assertion's own panic message rather than as silent drift
1206/// at every parent that might otherwise forget to include the
1207/// axis in its per-site author-time enumeration.
1208#[track_caller]
1209pub fn assert_tagged_union_convention_panel<T, F1, F2>(single_slot: F1, two_slot: F2)
1210where
1211    T: TaggedUnion + serde::Serialize,
1212    T::Kind: PartialEq + std::fmt::Debug,
1213    T::Error: PartialEq + std::fmt::Debug,
1214    F1: Fn(T::Kind) -> T,
1215    F2: Fn(T::Kind, T::Kind) -> T,
1216{
1217    assert_kind_list_matches_closed_set::<T>();
1218    assert_variant_round_trip::<T, _>(&single_slot);
1219    assert_two_slots_ambiguous::<T, _>(two_slot);
1220    assert_single_slot_key_matches_label::<T, _>(single_slot);
1221}
1222
1223#[cfg(test)]
1224mod tests {
1225    use super::*;
1226
1227    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
1228    enum V {
1229        A,
1230        B,
1231        C,
1232    }
1233
1234    #[test]
1235    fn empty_candidate_list_is_none() {
1236        let r: Result<V, _> = resolve(std::iter::empty());
1237        assert_eq!(r.unwrap_err(), ResolveError::None);
1238    }
1239
1240    #[test]
1241    fn all_none_is_none() {
1242        let r: Result<V, _> = resolve([None, None, None]);
1243        assert_eq!(r.unwrap_err(), ResolveError::None);
1244    }
1245
1246    #[test]
1247    fn single_some_is_resolved_regardless_of_position() {
1248        assert_eq!(resolve([Some(V::A), None, None]).unwrap(), V::A);
1249        assert_eq!(resolve([None, Some(V::B), None]).unwrap(), V::B);
1250        assert_eq!(resolve([None, None, Some(V::C)]).unwrap(), V::C);
1251    }
1252
1253    #[test]
1254    fn two_or_more_some_is_many() {
1255        assert_eq!(
1256            resolve([Some(V::A), Some(V::B), None]).unwrap_err(),
1257            ResolveError::Many
1258        );
1259        assert_eq!(
1260            resolve([Some(V::A), None, Some(V::C)]).unwrap_err(),
1261            ResolveError::Many
1262        );
1263        assert_eq!(
1264            resolve([None, Some(V::B), Some(V::C)]).unwrap_err(),
1265            ResolveError::Many
1266        );
1267        assert_eq!(
1268            resolve([Some(V::A), Some(V::B), Some(V::C)]).unwrap_err(),
1269            ResolveError::Many
1270        );
1271    }
1272
1273    /// Short-circuit invariant: once `Many` is decided, the sweep does
1274    /// NOT inspect further candidates. Encode it as a side-effect probe.
1275    #[test]
1276    fn many_short_circuits_after_second_some() {
1277        let mut visited = 0usize;
1278        let candidates = (0..4).map(|i| {
1279            visited += 1;
1280            // first two are Some, the rest would be Some too if we got there.
1281            Some(i)
1282        });
1283        // We can't actually consume `visited` here because it's borrowed in
1284        // the closure — fold the count via the resolver's short-circuit.
1285        let _ = resolve(candidates);
1286        // The resolver evaluates the iterator lazily up to the second
1287        // Some — index 0 (found = Some(0)), index 1 (Many → return).
1288        assert_eq!(visited, 2);
1289    }
1290
1291    /// The helper is value-agnostic — works with borrowed enum-view
1292    /// types matching the actual on-the-typescape callsites.
1293    #[test]
1294    fn works_with_borrowed_enum_view() {
1295        #[derive(Debug, PartialEq)]
1296        enum View<'a> {
1297            X(&'a u32),
1298            Y(&'a String),
1299        }
1300        let x = 7u32;
1301        let r = resolve([Some(View::X(&x)), None]).unwrap();
1302        assert_eq!(r, View::X(&7));
1303    }
1304
1305    /// Local sibling-shaped carrier used to pin the trait +
1306    /// [`resolve_or_err`] dispatch without depending on the
1307    /// crate's real error types.
1308    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
1309    enum E {
1310        Empty(&'static str),
1311        Ambiguous,
1312    }
1313
1314    impl TaggedUnionError for E {
1315        fn empty(kinds: &'static str) -> Self {
1316            E::Empty(kinds)
1317        }
1318        fn ambiguous() -> Self {
1319            E::Ambiguous
1320        }
1321    }
1322
1323    /// Four-outcome truth table at the compound-lift boundary.
1324    /// Pins that the two failure arms of [`resolve`] project onto
1325    /// the trait's two typed constructors byte-identically, and
1326    /// that the Ok arm falls through untouched.
1327    #[test]
1328    fn resolve_or_err_dispatches_each_arm_through_the_trait() {
1329        const KINDS: &str = "a/b/c";
1330
1331        assert_eq!(
1332            resolve_or_err::<V, E>([Some(V::A), None, None], KINDS).unwrap(),
1333            V::A
1334        );
1335        assert_eq!(
1336            resolve_or_err::<V, E>([None, Some(V::B), None], KINDS).unwrap(),
1337            V::B
1338        );
1339
1340        assert_eq!(
1341            resolve_or_err::<V, E>([None, None, None], KINDS).unwrap_err(),
1342            E::Empty(KINDS)
1343        );
1344
1345        assert_eq!(
1346            resolve_or_err::<V, E>([Some(V::A), Some(V::B), None], KINDS).unwrap_err(),
1347            E::Ambiguous
1348        );
1349    }
1350
1351    /// The trait's Empty arm carries the &'static str the caller
1352    /// hands `resolve_or_err`, verbatim — a rename at the caller's
1353    /// `KINDS` constant reaches the diagnostic surface intact.
1354    #[test]
1355    fn resolve_or_err_empty_carries_the_caller_kinds_verbatim() {
1356        const KINDS_ALPHA: &str = "alpha/beta";
1357        const KINDS_GAMMA: &str = "gamma/delta/epsilon";
1358
1359        assert_eq!(
1360            resolve_or_err::<V, E>([None, None], KINDS_ALPHA).unwrap_err(),
1361            E::Empty(KINDS_ALPHA)
1362        );
1363        assert_eq!(
1364            resolve_or_err::<V, E>([None, None, None], KINDS_GAMMA).unwrap_err(),
1365            E::Empty(KINDS_GAMMA)
1366        );
1367    }
1368
1369    /// The compound-lift preserves [`resolve`]'s short-circuit at
1370    /// the Many arm — a third-and-later candidate is not
1371    /// inspected once the second populated entry is seen.
1372    #[test]
1373    fn resolve_or_err_short_circuits_on_many() {
1374        let mut visited = 0usize;
1375        let candidates = (0..4).map(|i| {
1376            visited += 1;
1377            Some(i)
1378        });
1379        let _ = resolve_or_err::<i32, E>(candidates, "irrelevant");
1380        assert_eq!(visited, 2);
1381    }
1382
1383    // -------------------------------------------------------------------
1384    // `declare_tagged_union_error!` macro-emitted carrier — pins the
1385    // shape a fifth sibling would land through the macro instead of
1386    // hand-rolling the enum + `impl TaggedUnionError` block.
1387    // -------------------------------------------------------------------
1388
1389    crate::declare_tagged_union_error! {
1390        pub(super) MacroEmittedError,
1391        empty = "test carrier has no variant set (one of {0} required)",
1392        ambiguous = "test carrier has multiple variants set; exactly one required",
1393    }
1394
1395    /// The macro-emitted carrier's [`TaggedUnionError`] impl dispatches
1396    /// the same four-outcome truth table [`resolve_or_err`] pins for a
1397    /// hand-rolled carrier — pins that swapping a hand-rolled carrier
1398    /// for a macro-emitted one preserves the compound-lift's projection
1399    /// byte-identically.
1400    #[test]
1401    fn macro_emitted_carrier_projects_through_resolve_or_err() {
1402        const KINDS: &str = "one/two/three";
1403
1404        assert_eq!(
1405            resolve_or_err::<V, MacroEmittedError>([Some(V::A), None, None], KINDS).unwrap(),
1406            V::A
1407        );
1408        assert_eq!(
1409            resolve_or_err::<V, MacroEmittedError>([None, None, None], KINDS).unwrap_err(),
1410            MacroEmittedError::Empty(KINDS)
1411        );
1412        assert_eq!(
1413            resolve_or_err::<V, MacroEmittedError>([Some(V::A), Some(V::B), None], KINDS)
1414                .unwrap_err(),
1415            MacroEmittedError::Ambiguous
1416        );
1417    }
1418
1419    /// The macro-emitted carrier's `#[error(...)]` messages render the
1420    /// two operator-facing diagnostic strings the caller handed the
1421    /// macro, verbatim — a rename at the caller's literal reaches the
1422    /// operator diagnostic surface intact.
1423    #[test]
1424    fn macro_emitted_carrier_display_renders_caller_literals_verbatim() {
1425        assert_eq!(
1426            MacroEmittedError::Empty("alpha/beta").to_string(),
1427            "test carrier has no variant set (one of alpha/beta required)",
1428        );
1429        assert_eq!(
1430            MacroEmittedError::Ambiguous.to_string(),
1431            "test carrier has multiple variants set; exactly one required",
1432        );
1433    }
1434
1435    /// The macro-emitted carrier is `Copy` — a substrate-wide promise
1436    /// pinned by the macro's `#[derive(..., Copy, ...)]` header so a
1437    /// consumer treating the carrier as a value type (memcpy-cheap
1438    /// return, `.copied()` on an `Option<&E>`) stays valid across every
1439    /// carrier the macro emits.
1440    #[test]
1441    fn macro_emitted_carrier_is_copy() {
1442        fn assert_copy<T: Copy>() {}
1443        assert_copy::<MacroEmittedError>();
1444    }
1445
1446    // -------------------------------------------------------------------
1447    // `TaggedUnion` trait — declarative surface pinning the
1448    // (Kind, Error, KIND_LIST) triple. `assert_kind_list_matches_closed_set`
1449    // is the generic diagnostic-stability testkit primitive shared by
1450    // every implementor's `_error_empty_lists_every_kind_in_canonical_order`
1451    // site.
1452    // -------------------------------------------------------------------
1453
1454    /// Local sibling-shaped Kind enum used to pin the trait's
1455    /// diagnostic-stability primitive without depending on the crate's
1456    /// four production tagged unions. Uses [`tatara_closed_set::DeriveClosedSet`]
1457    /// so `<Self as ClosedSet>::labels_joined("/")` reaches the same
1458    /// substrate composition the four production sites bind through.
1459    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, tatara_closed_set::DeriveClosedSet)]
1460    #[closed_set(via = "as_str", generate_unknown, display)]
1461    enum LocalKind {
1462        Alpha,
1463        Beta,
1464        Gamma,
1465    }
1466
1467    impl LocalKind {
1468        const ALL: [Self; 3] = [Self::Alpha, Self::Beta, Self::Gamma];
1469        const fn as_str(self) -> &'static str {
1470            match self {
1471                Self::Alpha => "alpha",
1472                Self::Beta => "beta",
1473                Self::Gamma => "gamma",
1474            }
1475        }
1476    }
1477
1478    /// Local parent type — impls [`TaggedUnion`] with a `KIND_LIST`
1479    /// literal that matches the canonical `<LocalKind as
1480    /// ClosedSet>::labels_joined("/")` projection. Carries three
1481    /// `Option<u32>` slots so the substrate-primitive
1482    /// [`TaggedUnion::variant`] default method can be exercised
1483    /// directly on a sibling-shaped-but-crate-local parent, isolated
1484    /// from the four production tagged unions.
1485    ///
1486    /// Derives [`serde::Serialize`] with `skip_serializing_if =
1487    /// "Option::is_none"` on every slot so the wire-format primitive
1488    /// [`assert_single_slot_key_matches_label`] can be exercised
1489    /// directly against the sibling-shaped scaffold — mirrors the
1490    /// `#[serde(default, skip_serializing_if = "Option::is_none")]`
1491    /// annotation every one of the four production tagged unions
1492    /// carries on its own slots.
1493    #[derive(Default, serde::Serialize)]
1494    struct LocalParent {
1495        #[serde(skip_serializing_if = "Option::is_none")]
1496        alpha: Option<u32>,
1497        #[serde(skip_serializing_if = "Option::is_none")]
1498        beta: Option<u32>,
1499        #[serde(skip_serializing_if = "Option::is_none")]
1500        gamma: Option<u32>,
1501    }
1502
1503    /// Borrowed-view of a populated slot on [`LocalParent`] — the
1504    /// return type of [`LocalKind::select`] and the substrate-primitive
1505    /// [`TaggedUnion::variant`] default on `LocalParent`.
1506    #[derive(Debug, PartialEq)]
1507    enum LocalVariant<'a> {
1508        Alpha(&'a u32),
1509        Beta(&'a u32),
1510        Gamma(&'a u32),
1511    }
1512
1513    impl VariantSelector<LocalParent> for LocalKind {
1514        type Variant<'a> = LocalVariant<'a>;
1515        fn select<'a>(self, parent: &'a LocalParent) -> Option<LocalVariant<'a>>
1516        where
1517            Self: 'a,
1518        {
1519            match self {
1520                Self::Alpha => parent.alpha.as_ref().map(LocalVariant::Alpha),
1521                Self::Beta => parent.beta.as_ref().map(LocalVariant::Beta),
1522                Self::Gamma => parent.gamma.as_ref().map(LocalVariant::Gamma),
1523            }
1524        }
1525    }
1526
1527    impl VariantKind<LocalKind> for LocalVariant<'_> {
1528        fn variant_kind(&self) -> LocalKind {
1529            match self {
1530                Self::Alpha(_) => LocalKind::Alpha,
1531                Self::Beta(_) => LocalKind::Beta,
1532                Self::Gamma(_) => LocalKind::Gamma,
1533            }
1534        }
1535    }
1536
1537    crate::declare_tagged_union_error! {
1538        pub(super) LocalParentError,
1539        empty = "local carrier has no variant set (one of {0} required)",
1540        ambiguous = "local carrier has multiple variants set; exactly one required",
1541    }
1542
1543    impl TaggedUnion for LocalParent {
1544        type Kind = LocalKind;
1545        type Error = LocalParentError;
1546        const KIND_LIST: &'static str = "alpha/beta/gamma";
1547    }
1548
1549    /// The testkit primitive resolves the canonical join of every
1550    /// `LocalKind` variant's label against the trait's `KIND_LIST`
1551    /// constant byte-identically — the four production sites bind
1552    /// through this exact dispatch. The Ok arm is the "no drift"
1553    /// outcome; a divergence surfaces as a labeled assertion failure.
1554    #[test]
1555    fn assert_kind_list_matches_closed_set_accepts_coherent_impl() {
1556        assert_kind_list_matches_closed_set::<LocalParent>();
1557    }
1558
1559    /// The testkit primitive is a `#[track_caller]` compound-lift:
1560    /// a drift between `<T::Kind as ClosedSet>::labels_joined("/")`
1561    /// and `T::KIND_LIST` fails the assertion at the caller's site,
1562    /// not inside the primitive body. Pin the failing case with a
1563    /// local parent whose `KIND_LIST` is deliberately mis-authored
1564    /// (a variant reorder), so a regression that drops the drift
1565    /// detection fails-loudly here.
1566    #[test]
1567    #[should_panic(expected = "TaggedUnion KIND_LIST drift")]
1568    fn assert_kind_list_matches_closed_set_rejects_drifted_impl() {
1569        struct Drifted;
1570        // The `TaggedUnion` trait bounds `Kind: VariantSelector<Self>`
1571        // with `Variant<'a>: VariantKind<Self>`; the drift test only
1572        // exercises `assert_kind_list_matches_closed_set` (which reaches
1573        // the (Kind, KIND_LIST) pair, not the sweep body), so reusing
1574        // the sibling `LocalVariant<'a>` (with its already-load-bearing
1575        // `impl VariantKind<LocalKind>`) + always-`None` `select`
1576        // satisfies both bounds without wiring a real projection.
1577        impl VariantSelector<Drifted> for LocalKind {
1578            type Variant<'a> = LocalVariant<'a>;
1579            fn select<'a>(self, _: &'a Drifted) -> Option<LocalVariant<'a>>
1580            where
1581                Self: 'a,
1582            {
1583                None
1584            }
1585        }
1586        impl TaggedUnion for Drifted {
1587            type Kind = LocalKind;
1588            type Error = LocalParentError;
1589            // Deliberate drift — canonical join is "alpha/beta/gamma".
1590            const KIND_LIST: &'static str = "beta/alpha/gamma";
1591        }
1592        assert_kind_list_matches_closed_set::<Drifted>();
1593    }
1594
1595    /// Every one of the four production `.variant()` sites on
1596    /// `ProcessSpec` impls [`TaggedUnion`] with `KIND_LIST` reaching
1597    /// the substrate primitive `assert_kind_list_matches_closed_set`
1598    /// coherently. Sweep every production implementor at ONE
1599    /// substrate boundary so a regression that drifts a production
1600    /// site's `KIND_LIST` (or renames a `Kind` variant without
1601    /// updating the constant) fails BOTH at the per-crate test site
1602    /// AND at this substrate-wide sweep — no per-implementor test
1603    /// site can drop the check silently.
1604    #[test]
1605    fn every_production_tagged_union_binds_through_the_testkit_primitive() {
1606        assert_kind_list_matches_closed_set::<crate::intent::Intent>();
1607        assert_kind_list_matches_closed_set::<crate::encapsulates::EncapsulationKind>();
1608        assert_kind_list_matches_closed_set::<crate::export::ArtifactSource>();
1609        assert_kind_list_matches_closed_set::<crate::export::VectorChannel>();
1610    }
1611
1612    /// Every one of the four production `.variant()` sites on
1613    /// `ProcessSpec` binds through the wire-key primitive
1614    /// [`assert_single_slot_key_matches_label`] coherently — every
1615    /// per-site `single_slot_X(k)` factory serializes to a JSON object
1616    /// with EXACTLY ONE key whose name equals `k.label()` (delegating
1617    /// to each Kind's inherent `as_str`, matching the parent's serde
1618    /// `rename_all = "camelCase"` projection). Sweep every production
1619    /// implementor at ONE substrate boundary so a regression that
1620    /// drifts a production site's `single_slot_X` factory (populates
1621    /// the wrong slot; leaks residual slots between calls) OR the
1622    /// parent's field-to-kind alignment (`as_str` returns "receipts"
1623    /// but the field is named `receipt`) fails BOTH at the per-crate
1624    /// test site AND at this substrate-wide sweep — no per-implementor
1625    /// test site can drop the check silently.
1626    #[test]
1627    fn every_production_tagged_union_binds_through_the_wire_key_testkit_primitive() {
1628        assert_single_slot_key_matches_label::<crate::intent::Intent, _>(single_slot_intent_probe);
1629        assert_single_slot_key_matches_label::<crate::encapsulates::EncapsulationKind, _>(
1630            single_slot_encapsulation_kind_probe,
1631        );
1632        assert_single_slot_key_matches_label::<crate::export::ArtifactSource, _>(
1633            single_slot_artifact_source_probe,
1634        );
1635        assert_single_slot_key_matches_label::<crate::export::VectorChannel, _>(
1636            single_slot_vector_channel_probe,
1637        );
1638    }
1639
1640    /// The parent-side four-axis compound-lift dispatches Ok on a
1641    /// coherent implementor — the [`LocalParent`] scaffold publishes
1642    /// every axis (`TaggedUnion` via
1643    /// [`crate::declare_tagged_union_error`]-emitted `LocalParentError`
1644    /// + Serialize via `#[derive(serde::Serialize)]` +
1645    /// `LocalKind: PartialEq + Debug` +
1646    /// `LocalParentError: PartialEq + Debug`), matching the
1647    /// substrate-wide four-axis convention every one of the four
1648    /// production parents carries. The Ok arm is the "no drift"
1649    /// outcome; a divergence at ANY sub-assertion's composition
1650    /// inside the compound (accidentally dropped, silently reordered,
1651    /// or short-circuited) surfaces at the sub-primitive's own
1652    /// panic message (each sub-primitive is `#[track_caller]`), and
1653    /// the per-axis failing arms are pinned by the sibling
1654    /// `#[should_panic]` probes already at the per-axis primitive
1655    /// layer (`assert_kind_list_matches_closed_set_rejects_drifted_impl`,
1656    /// `assert_variant_round_trip_rejects_factory_that_leaves_slot_empty`,
1657    /// `assert_two_slots_ambiguous_rejects_factory_that_populates_only_one_slot`,
1658    /// `assert_single_slot_key_matches_label_rejects_factory_that_populates_wrong_slot`).
1659    /// Re-authoring per-axis drift probes at the compound layer
1660    /// would restate the SAME four axis-typed contracts through a
1661    /// compound wrapper without adding a new gate.
1662    #[test]
1663    fn assert_tagged_union_convention_panel_accepts_coherent_local_impl() {
1664        fn single_slot(k: LocalKind) -> LocalParent {
1665            match k {
1666                LocalKind::Alpha => LocalParent {
1667                    alpha: Some(11),
1668                    ..Default::default()
1669                },
1670                LocalKind::Beta => LocalParent {
1671                    beta: Some(22),
1672                    ..Default::default()
1673                },
1674                LocalKind::Gamma => LocalParent {
1675                    gamma: Some(33),
1676                    ..Default::default()
1677                },
1678            }
1679        }
1680        fn two_slot(a: LocalKind, b: LocalKind) -> LocalParent {
1681            let mut p = LocalParent::default();
1682            for k in [a, b] {
1683                match k {
1684                    LocalKind::Alpha => p.alpha = Some(11),
1685                    LocalKind::Beta => p.beta = Some(22),
1686                    LocalKind::Gamma => p.gamma = Some(33),
1687                }
1688            }
1689            p
1690        }
1691        assert_tagged_union_convention_panel::<LocalParent, _, _>(single_slot, two_slot);
1692    }
1693
1694    /// Every one of the four production `.variant()` parents on
1695    /// `ProcessSpec` binds through the four-axis convention-panel
1696    /// primitive [`assert_tagged_union_convention_panel`] coherently.
1697    /// Sweep every production parent at ONE substrate boundary so a
1698    /// regression that (a) drops ANY of the four sub-assertions from
1699    /// the compound's body, (b) reorders them in a way that skips
1700    /// one on Ok, (c) silently binds the compound against a
1701    /// hollowed-out sub-assertion body, or (d) drifts a substrate-
1702    /// local `{single,two}_slot_*_probe` fixture (populates the
1703    /// wrong slot; leaks residual slots between calls; the `.or()`
1704    /// composition drops a slot on the two-slot side) fails BOTH at
1705    /// the per-crate test site AND at this substrate-wide sweep.
1706    ///
1707    /// Pinned in lock-step with the sibling
1708    /// `every_production_tagged_union_binds_through_the_testkit_primitive`
1709    /// (KIND_LIST axis) and
1710    /// `every_production_tagged_union_binds_through_the_wire_key_testkit_primitive`
1711    /// (wire-key axis) sweeps — every parent enumerated below is a
1712    /// member of BOTH sibling sweeps (their bounds are strict
1713    /// subsets of the compound's `T: TaggedUnion + Serialize` +
1714    /// `T::Kind: PartialEq + Debug` + `T::Error: PartialEq + Debug`
1715    /// bound), and every parent additionally publishes both a
1716    /// substrate-local `single_slot_*_probe` and a
1717    /// substrate-local `two_slot_*_probe` peer above. Post-sweep the
1718    /// substrate-wide four-axis parent-side convention-panel
1719    /// discipline is a property of the workspace, not a per-file
1720    /// convention — even before any per-site test-body sweep
1721    /// collapses the four per-parent sibling tests into ONE compound
1722    /// call each.
1723    #[test]
1724    fn every_production_tagged_union_binds_through_the_convention_panel_testkit_primitive() {
1725        assert_tagged_union_convention_panel::<crate::intent::Intent, _, _>(
1726            single_slot_intent_probe,
1727            two_slot_intent_probe,
1728        );
1729        assert_tagged_union_convention_panel::<crate::encapsulates::EncapsulationKind, _, _>(
1730            single_slot_encapsulation_kind_probe,
1731            two_slot_encapsulation_kind_probe,
1732        );
1733        assert_tagged_union_convention_panel::<crate::export::ArtifactSource, _, _>(
1734            single_slot_artifact_source_probe,
1735            two_slot_artifact_source_probe,
1736        );
1737        assert_tagged_union_convention_panel::<crate::export::VectorChannel, _, _>(
1738            single_slot_vector_channel_probe,
1739            two_slot_vector_channel_probe,
1740        );
1741    }
1742
1743    /// The Display / label alignment primitive dispatches Ok on a
1744    /// coherent implementor — the [`LocalKind`] scaffold derives
1745    /// `Display` from `label` via `#[closed_set(via = "as_str",
1746    /// display)]`, matching the substrate-wide derive shape every
1747    /// production implementor across the crate carries. The Ok arm
1748    /// is the "no drift" outcome; a divergence surfaces as a labeled
1749    /// assertion failure at the caller site (this test's own line).
1750    #[test]
1751    fn assert_display_matches_label_accepts_coherent_impl() {
1752        assert_display_matches_label::<LocalKind>();
1753    }
1754
1755    /// A local closed-set scaffold whose `Display` deliberately
1756    /// diverges from `label` — pins the failing arm of the primitive.
1757    /// The `#[closed_set(via = "as_str")]` attribute WITHOUT `display`
1758    /// leaves the `Display` impl uncovered by the derive, and the
1759    /// hand-authored `impl Display` below emits a suffixed rendering
1760    /// that no `label` projection returns. A regression that drops
1761    /// the alignment assertion inside
1762    /// [`assert_display_matches_label`] fails-loudly at this
1763    /// `#[should_panic]` probe before it can silently thread through
1764    /// the 29 production `X_display_matches_as_str` sites.
1765    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, tatara_closed_set::DeriveClosedSet)]
1766    #[closed_set(via = "as_str", generate_unknown)]
1767    enum DisplayDriftKind {
1768        Alpha,
1769        Beta,
1770    }
1771
1772    impl DisplayDriftKind {
1773        const ALL: [Self; 2] = [Self::Alpha, Self::Beta];
1774        const fn as_str(self) -> &'static str {
1775            match self {
1776                Self::Alpha => "alpha",
1777                Self::Beta => "beta",
1778            }
1779        }
1780    }
1781
1782    impl std::fmt::Display for DisplayDriftKind {
1783        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1784            // Deliberate drift — Display suffixes the label with a
1785            // marker no `label` projection returns.
1786            write!(f, "{}!", self.as_str())
1787        }
1788    }
1789
1790    #[test]
1791    #[should_panic(expected = "Display drifted from ClosedSet::label")]
1792    fn assert_display_matches_label_rejects_drifted_impl() {
1793        assert_display_matches_label::<DisplayDriftKind>();
1794    }
1795
1796    /// Every closed-set enum across `tatara-process` that carried a
1797    /// hand-rolled `X_display_matches_as_str` test pre-lift now binds
1798    /// through the substrate primitive at ONE call site each.  This
1799    /// substrate-wide sweep pins every production Display-alignment
1800    /// consumer at ONE boundary so a per-crate test-site drop cannot
1801    /// silently disable the check — the sweep here catches the drift
1802    /// even when the per-site test body is removed. Mirrors the
1803    /// `every_production_tagged_union_binds_through_the_testkit_primitive`
1804    /// and `every_production_tagged_union_binds_through_the_wire_key_testkit_primitive`
1805    /// sibling sweeps on the (`KIND_LIST` slash-join, wire-key)
1806    /// axes; this one closes the (`Display` byte-identity) axis.
1807    #[test]
1808    fn every_production_display_impl_binds_through_the_testkit_primitive() {
1809        assert_display_matches_label::<crate::allocation::AllocationPhase>();
1810        assert_display_matches_label::<crate::boundary::ConditionKind>();
1811        assert_display_matches_label::<crate::classification::Arity>();
1812        assert_display_matches_label::<crate::classification::CalmClassification>();
1813        assert_display_matches_label::<crate::classification::ConvergencePointType>();
1814        assert_display_matches_label::<crate::classification::DataClassification>();
1815        assert_display_matches_label::<crate::classification::HorizonKind>();
1816        assert_display_matches_label::<crate::classification::OptimizationDirection>();
1817        assert_display_matches_label::<crate::classification::SubstrateType>();
1818        assert_display_matches_label::<crate::compliance::VerificationPhase>();
1819        assert_display_matches_label::<crate::encapsulates::EncapsulationMode>();
1820        assert_display_matches_label::<crate::encapsulates::EncapsulationTarget>();
1821        assert_display_matches_label::<crate::export::ArtifactKind>();
1822        assert_display_matches_label::<crate::export::ChannelKind>();
1823        assert_display_matches_label::<crate::export::ExportTrigger>();
1824        assert_display_matches_label::<crate::export::ReportFormat>();
1825        assert_display_matches_label::<crate::export::ReportPayloadShape>();
1826        assert_display_matches_label::<crate::intent::IntentKind>();
1827        assert_display_matches_label::<crate::intent::WorkloadKind>();
1828        assert_display_matches_label::<crate::lifetime::LifetimeKind>();
1829        assert_display_matches_label::<crate::lifetime::TeardownPolicy>();
1830        assert_display_matches_label::<crate::lifetime_clock::AutoTerminateKind>();
1831        assert_display_matches_label::<crate::lifetime_clock::TerminateReasonKind>();
1832        assert_display_matches_label::<crate::matrix::SelectStrategyKind>();
1833        assert_display_matches_label::<crate::pool::MemberState>();
1834        assert_display_matches_label::<crate::pool::PoolPhase>();
1835        assert_display_matches_label::<crate::pool::ReplacementPolicy>();
1836        assert_display_matches_label::<crate::pool::ReturnPolicy>();
1837        assert_display_matches_label::<crate::signal::SighupStrategy>();
1838        assert_display_matches_label::<crate::spec::MustReachPhase>();
1839    }
1840
1841    /// Local closed-set scaffold whose serde `rename_all = "lowercase"`
1842    /// projection matches its `via = "as_str"` label byte-identically —
1843    /// pins the Ok arm of the wire-format primitive. Every production
1844    /// implementor across the crate carries the substrate-wide
1845    /// `#[closed_set(via = "as_str")]` + `#[serde(rename_all = ...)]`
1846    /// pair whose alignment this scaffold pins on the sibling-shaped
1847    /// local surface.
1848    #[derive(
1849        Clone,
1850        Copy,
1851        Debug,
1852        PartialEq,
1853        Eq,
1854        Hash,
1855        serde::Serialize,
1856        tatara_closed_set::DeriveClosedSet,
1857    )]
1858    #[serde(rename_all = "lowercase")]
1859    #[closed_set(via = "as_str", generate_unknown)]
1860    enum SerdeAlignedKind {
1861        Alpha,
1862        Beta,
1863    }
1864
1865    impl SerdeAlignedKind {
1866        const ALL: [Self; 2] = [Self::Alpha, Self::Beta];
1867        const fn as_str(self) -> &'static str {
1868            match self {
1869                Self::Alpha => "alpha",
1870                Self::Beta => "beta",
1871            }
1872        }
1873    }
1874
1875    #[test]
1876    fn assert_label_matches_serde_serialization_accepts_coherent_impl() {
1877        assert_label_matches_serde_serialization::<SerdeAlignedKind>();
1878    }
1879
1880    /// A local closed-set scaffold whose serde output deliberately
1881    /// diverges from `label` — pins the failing arm of the wire-format
1882    /// primitive. The `#[serde(rename_all = "UPPERCASE")]` projection
1883    /// emits uppercase JSON strings while the `via = "as_str"` label
1884    /// stays lowercase. A regression that drops the alignment assertion
1885    /// inside [`assert_label_matches_serde_serialization`] fails-loudly
1886    /// at this `#[should_panic]` probe before it can silently thread
1887    /// through the 20 production `X_as_str_matches_serde` sites.
1888    #[derive(
1889        Clone,
1890        Copy,
1891        Debug,
1892        PartialEq,
1893        Eq,
1894        Hash,
1895        serde::Serialize,
1896        tatara_closed_set::DeriveClosedSet,
1897    )]
1898    #[serde(rename_all = "UPPERCASE")]
1899    #[closed_set(via = "as_str", generate_unknown)]
1900    enum SerdeDriftKind {
1901        Alpha,
1902        Beta,
1903    }
1904
1905    impl SerdeDriftKind {
1906        const ALL: [Self; 2] = [Self::Alpha, Self::Beta];
1907        const fn as_str(self) -> &'static str {
1908            match self {
1909                Self::Alpha => "alpha",
1910                Self::Beta => "beta",
1911            }
1912        }
1913    }
1914
1915    #[test]
1916    #[should_panic(expected = "serde output drifted from ClosedSet::label")]
1917    fn assert_label_matches_serde_serialization_rejects_drifted_impl() {
1918        assert_label_matches_serde_serialization::<SerdeDriftKind>();
1919    }
1920
1921    /// Local closed-set scaffold whose ALL THREE axes of the label-
1922    /// surface convention align by construction — pins the Ok arm of
1923    /// the compound-panel primitive.
1924    ///
1925    /// `#[serde(rename_all = "lowercase")]` matches the `via = "as_str"`
1926    /// labels byte-identically (the serde-alignment axis). The
1927    /// `display` sub-attribute on `#[closed_set(via = "as_str",
1928    /// display)]` derives `impl Display` from the same `as_str`
1929    /// projection (the Display-alignment axis). The `generate_unknown`
1930    /// sub-attribute emits the `T::Unknown` carrier the round-trip
1931    /// axis's `parse_label` returns on unknown input. Together these
1932    /// three attributes stamp the substrate-wide derive shape every
1933    /// production 3-axis-panel consumer carries; a caller that lands
1934    /// through this scaffold satisfies EVERY bound the compound's
1935    /// where-clause names.
1936    ///
1937    /// Peer to the sibling per-axis fixtures [`LocalKind`] (Display
1938    /// axis, no serde) and [`SerdeAlignedKind`] (serde axis, no
1939    /// Display) on the label-surface primitive family; this fixture
1940    /// closes the diagonal by carrying both attribute-sets at once,
1941    /// so a regression at ANY sub-assertion's composition inside the
1942    /// compound (the compound accidentally dropping the well-formed
1943    /// call, silently reordering the three calls, wrapping them in a
1944    /// short-circuit that skips the middle one on Ok, …) fails the
1945    /// compound's happy-path pin below rather than as silent drift at
1946    /// every 3-axis consumer.
1947    #[derive(
1948        Clone,
1949        Copy,
1950        Debug,
1951        PartialEq,
1952        Eq,
1953        Hash,
1954        serde::Serialize,
1955        tatara_closed_set::DeriveClosedSet,
1956    )]
1957    #[serde(rename_all = "lowercase")]
1958    #[closed_set(via = "as_str", generate_unknown, display)]
1959    enum PanelAlignedKind {
1960        Alpha,
1961        Beta,
1962    }
1963
1964    impl PanelAlignedKind {
1965        const ALL: [Self; 2] = [Self::Alpha, Self::Beta];
1966        const fn as_str(self) -> &'static str {
1967            match self {
1968                Self::Alpha => "alpha",
1969                Self::Beta => "beta",
1970            }
1971        }
1972    }
1973
1974    /// The compound-panel primitive dispatches Ok on a coherent
1975    /// implementor — [`PanelAlignedKind`] carries every attribute the
1976    /// substrate-wide 3-axis derive shape publishes, so all three
1977    /// sub-assertions the compound composes (well-formed, Display /
1978    /// label, serde / label) pass by construction. The Ok arm is the
1979    /// "no drift on any axis" outcome; a divergence at any single
1980    /// sub-assertion surfaces as that sub-assertion's own labeled
1981    /// panic message (with the caller-attributed line via
1982    /// `#[track_caller]` on both the compound and its sub-
1983    /// primitives), NOT as a silent pass.
1984    ///
1985    /// The per-axis failing arms are pinned by the sibling per-axis
1986    /// #[should_panic] probes above:
1987    ///   - the round-trip axis's failing arm is pinned by
1988    ///     [`tatara_closed_set::assert_closed_set_well_formed`]'s own
1989    ///     `#[should_panic]` probe in the `tatara-closed-set` crate;
1990    ///   - the Display axis's failing arm is pinned by
1991    ///     [`assert_display_matches_label_rejects_drifted_impl`] on
1992    ///     [`DisplayDriftKind`];
1993    ///   - the serde axis's failing arm is pinned by
1994    ///     [`assert_label_matches_serde_serialization_rejects_drifted_impl`]
1995    ///     on [`SerdeDriftKind`].
1996    /// Each per-axis drift fixture already surfaces its axis's exact
1997    /// panic-message substring, so re-authoring per-axis
1998    /// `#[should_panic]` probes at the compound layer would restate
1999    /// the SAME three axis-typed contracts through a compound
2000    /// wrapper — one more copy of the same three pins, not a new
2001    /// gate. The compound's happy-path pin here suffices to verify
2002    /// the composition doesn't lose ANY sub-assertion (a regression
2003    /// that swallows one axis silently would still fail the sibling
2004    /// sub-assertion's own drift probe on the drift fixture).
2005    #[test]
2006    fn assert_closed_set_convention_panel_accepts_coherent_impl() {
2007        assert_closed_set_convention_panel::<PanelAlignedKind>();
2008    }
2009
2010    /// Every closed-set enum across `tatara-process` that publishes
2011    /// ALL THREE axes of the label-surface convention (well-formed +
2012    /// Display-alignment + serde-alignment) now binds through the
2013    /// substrate compound-panel primitive at ONE call site each in
2014    /// this sweep. Pinned in lock-step with the sibling
2015    /// `every_production_serde_serialization_binds_through_the_testkit_primitive`
2016    /// sweep — every enum enumerated below is a member of BOTH sweeps
2017    /// (the compound's `T: Serialize + Display + ClosedSet + ...`
2018    /// bound is a strict superset of `assert_label_matches_serde_
2019    /// serialization`'s `T: ClosedSet + Serialize + Debug` bound, and
2020    /// the 20 wire-format consumers all additionally impl Display via
2021    /// `#[closed_set(via = "as_str", display)]`).
2022    ///
2023    /// A regression that (a) drops the compound's `assert_closed_set_
2024    /// well_formed` dispatch, (b) reorders the three sub-assertions
2025    /// in a way that skips one on Ok, or (c) silently binds the
2026    /// compound against a hollowed-out sub-assertion body catches
2027    /// here at the substrate-wide boundary — the sweep pins every
2028    /// production 3-axis consumer's compound-panel discipline through
2029    /// ONE test even before any per-site test-body sweep collapses
2030    /// the three per-enum sibling tests into ONE compound call each.
2031    /// Post-sweep the substrate-wide compound-panel discipline is a
2032    /// property of the workspace, not a per-file convention.
2033    #[test]
2034    fn every_production_convention_panel_binds_through_the_testkit_primitive() {
2035        assert_closed_set_convention_panel::<crate::allocation::AllocationPhase>();
2036        assert_closed_set_convention_panel::<crate::boundary::ConditionKind>();
2037        assert_closed_set_convention_panel::<crate::classification::CalmClassification>();
2038        assert_closed_set_convention_panel::<crate::classification::ConvergencePointType>();
2039        assert_closed_set_convention_panel::<crate::classification::DataClassification>();
2040        assert_closed_set_convention_panel::<crate::classification::HorizonKind>();
2041        assert_closed_set_convention_panel::<crate::classification::OptimizationDirection>();
2042        assert_closed_set_convention_panel::<crate::classification::SubstrateType>();
2043        assert_closed_set_convention_panel::<crate::compliance::VerificationPhase>();
2044        assert_closed_set_convention_panel::<crate::encapsulates::EncapsulationMode>();
2045        assert_closed_set_convention_panel::<crate::export::ExportTrigger>();
2046        assert_closed_set_convention_panel::<crate::export::ReportFormat>();
2047        assert_closed_set_convention_panel::<crate::intent::WorkloadKind>();
2048        assert_closed_set_convention_panel::<crate::lifetime::TeardownPolicy>();
2049        assert_closed_set_convention_panel::<crate::pool::MemberState>();
2050        assert_closed_set_convention_panel::<crate::pool::PoolPhase>();
2051        assert_closed_set_convention_panel::<crate::pool::ReplacementPolicy>();
2052        assert_closed_set_convention_panel::<crate::pool::ReturnPolicy>();
2053        assert_closed_set_convention_panel::<crate::signal::SighupStrategy>();
2054        assert_closed_set_convention_panel::<crate::spec::MustReachPhase>();
2055    }
2056
2057    /// Every closed-set enum across `tatara-process` that carried a
2058    /// hand-rolled `X_as_str_matches_serde` test pre-lift now binds
2059    /// through the substrate primitive at ONE call site each. This
2060    /// substrate-wide sweep pins every production wire-format alignment
2061    /// consumer at ONE boundary so a per-crate test-site drop cannot
2062    /// silently disable the check — the sweep here catches the drift
2063    /// even when the per-site test body is removed. Mirrors the sibling
2064    /// `every_production_display_impl_binds_through_the_testkit_primitive`
2065    /// sweep on the (Display byte-identity) axis; this one closes the
2066    /// (serde JSON-string byte-identity) axis.
2067    #[test]
2068    fn every_production_serde_serialization_binds_through_the_testkit_primitive() {
2069        assert_label_matches_serde_serialization::<crate::allocation::AllocationPhase>();
2070        assert_label_matches_serde_serialization::<crate::boundary::ConditionKind>();
2071        assert_label_matches_serde_serialization::<crate::classification::CalmClassification>();
2072        assert_label_matches_serde_serialization::<crate::classification::ConvergencePointType>();
2073        assert_label_matches_serde_serialization::<crate::classification::DataClassification>();
2074        assert_label_matches_serde_serialization::<crate::classification::HorizonKind>();
2075        assert_label_matches_serde_serialization::<crate::classification::OptimizationDirection>();
2076        assert_label_matches_serde_serialization::<crate::classification::SubstrateType>();
2077        assert_label_matches_serde_serialization::<crate::compliance::VerificationPhase>();
2078        assert_label_matches_serde_serialization::<crate::encapsulates::EncapsulationMode>();
2079        assert_label_matches_serde_serialization::<crate::export::ExportTrigger>();
2080        assert_label_matches_serde_serialization::<crate::export::ReportFormat>();
2081        assert_label_matches_serde_serialization::<crate::intent::WorkloadKind>();
2082        assert_label_matches_serde_serialization::<crate::lifetime::TeardownPolicy>();
2083        assert_label_matches_serde_serialization::<crate::pool::MemberState>();
2084        assert_label_matches_serde_serialization::<crate::pool::PoolPhase>();
2085        assert_label_matches_serde_serialization::<crate::pool::ReplacementPolicy>();
2086        assert_label_matches_serde_serialization::<crate::pool::ReturnPolicy>();
2087        assert_label_matches_serde_serialization::<crate::signal::SighupStrategy>();
2088        assert_label_matches_serde_serialization::<crate::spec::MustReachPhase>();
2089    }
2090
2091    // Substrate-local single-slot factories — mirror the per-site
2092    // `single_slot_X` test helpers each production site owns, so the
2093    // substrate-wide sweep above binds through the wire-key primitive
2094    // without reaching across the per-crate test-module boundaries the
2095    // per-site helpers are scoped to. The primitive only requires that
2096    // the addressed slot on the parent is populated; the inner spec's
2097    // exact field values are irrelevant to the wire-key check.
2098
2099    fn single_slot_intent_probe(kind: crate::intent::IntentKind) -> crate::intent::Intent {
2100        use crate::intent::{
2101            AplicacaoIntent, ContainerIntent, FluxIntent, GuestIntent, Intent, IntentKind,
2102            LispIntent, NixIntent, WorkloadKind,
2103        };
2104        match kind {
2105            IntentKind::Nix => Intent {
2106                nix: Some(NixIntent {
2107                    flake_ref: "f".into(),
2108                    attribute: "a".into(),
2109                    system: None,
2110                    attic_cache: None,
2111                    extra_args: vec![],
2112                    delegate_to_nix_build: false,
2113                }),
2114                ..Intent::default()
2115            },
2116            IntentKind::Flux => Intent {
2117                flux: Some(FluxIntent {
2118                    git_repository: "g".into(),
2119                    path: "p".into(),
2120                    git_repository_namespace: None,
2121                    target_namespace: None,
2122                    decrypt_sops: true,
2123                    helm_chart: None,
2124                    helm_values: None,
2125                }),
2126                ..Intent::default()
2127            },
2128            IntentKind::Lisp => Intent {
2129                lisp: Some(LispIntent {
2130                    source: "()".into(),
2131                    reader: "tatara-lisp".into(),
2132                    version: "v1".into(),
2133                    bindings: std::collections::BTreeMap::new(),
2134                }),
2135                ..Intent::default()
2136            },
2137            IntentKind::Container => Intent {
2138                container: Some(ContainerIntent {
2139                    image: "x".into(),
2140                    replicas: None,
2141                    command: vec![],
2142                    args: vec![],
2143                    env: std::collections::BTreeMap::new(),
2144                    workload_kind: WorkloadKind::default(),
2145                }),
2146                ..Intent::default()
2147            },
2148            IntentKind::Aplicacao => Intent {
2149                aplicacao: Some(AplicacaoIntent {
2150                    chart_ref: "x".into(),
2151                    version: "1".into(),
2152                    profile: String::new(),
2153                    values_overlay: serde_json::Value::Null,
2154                    release_name: None,
2155                    target_namespace: None,
2156                    install_timeout: None,
2157                }),
2158                ..Intent::default()
2159            },
2160            IntentKind::Guest => Intent {
2161                guest: Some(GuestIntent {
2162                    spec: serde_json::json!({"name": "x"}),
2163                    state_dir: None,
2164                    allow_remote_build: None,
2165                }),
2166                ..Intent::default()
2167            },
2168        }
2169    }
2170
2171    fn single_slot_encapsulation_kind_probe(
2172        target: crate::encapsulates::EncapsulationTarget,
2173    ) -> crate::encapsulates::EncapsulationKind {
2174        use crate::encapsulates::{
2175            BareWorkload, EncapsulationKind, EncapsulationTarget, ExistingHelmRelease,
2176            ExistingKustomization,
2177        };
2178        match target {
2179            EncapsulationTarget::ExistingHelmRelease => EncapsulationKind {
2180                existing_helm_release: Some(ExistingHelmRelease {
2181                    namespace: "ns".into(),
2182                    name: "hr".into(),
2183                    release_name: "rel".into(),
2184                }),
2185                ..EncapsulationKind::default()
2186            },
2187            EncapsulationTarget::ExistingKustomization => EncapsulationKind {
2188                existing_kustomization: Some(ExistingKustomization {
2189                    namespace: "ns".into(),
2190                    name: "ks".into(),
2191                }),
2192                ..EncapsulationKind::default()
2193            },
2194            EncapsulationTarget::BareWorkload => {
2195                let mut sel = std::collections::BTreeMap::new();
2196                sel.insert("app".into(), "x".into());
2197                EncapsulationKind {
2198                    bare_workload: Some(BareWorkload {
2199                        namespace: "ns".into(),
2200                        selector: sel,
2201                    }),
2202                    ..EncapsulationKind::default()
2203                }
2204            }
2205        }
2206    }
2207
2208    fn single_slot_artifact_source_probe(
2209        kind: crate::export::ArtifactKind,
2210    ) -> crate::export::ArtifactSource {
2211        use crate::export::{
2212            ArtifactKind, ArtifactSource, ProcessSnapshotSource, ReceiptsSource, ReportFormat,
2213            RunMarkerSource, TestReportSource,
2214        };
2215        match kind {
2216            ArtifactKind::Receipts => ArtifactSource {
2217                receipts: Some(ReceiptsSource::default()),
2218                ..ArtifactSource::default()
2219            },
2220            ArtifactKind::TestReport => ArtifactSource {
2221                test_report: Some(TestReportSource {
2222                    configmap: "cm".into(),
2223                    key: "k".into(),
2224                    format: ReportFormat::Junit,
2225                    namespace: None,
2226                }),
2227                ..ArtifactSource::default()
2228            },
2229            ArtifactKind::ProcessSnapshot => ArtifactSource {
2230                process_snapshot: Some(ProcessSnapshotSource::default()),
2231                ..ArtifactSource::default()
2232            },
2233            ArtifactKind::RunMarker => ArtifactSource {
2234                run_marker: Some(RunMarkerSource::default()),
2235                ..ArtifactSource::default()
2236            },
2237        }
2238    }
2239
2240    fn single_slot_vector_channel_probe(
2241        kind: crate::export::ChannelKind,
2242    ) -> crate::export::VectorChannel {
2243        use crate::export::{
2244            ChannelKind, HttpEventChannel, NatsSubjectChannel, StdoutChannel, VectorChannel,
2245        };
2246        match kind {
2247            ChannelKind::HttpEvent => VectorChannel {
2248                http_event: Some(HttpEventChannel {
2249                    endpoint: None,
2250                    signal_type: "x".into(),
2251                }),
2252                ..VectorChannel::default()
2253            },
2254            ChannelKind::NatsSubject => VectorChannel {
2255                nats_subject: Some(NatsSubjectChannel {
2256                    subject: "s".into(),
2257                    stream: "S".into(),
2258                    url: None,
2259                }),
2260                ..VectorChannel::default()
2261            },
2262            ChannelKind::Stdout => VectorChannel {
2263                stdout: Some(StdoutChannel::default()),
2264                ..VectorChannel::default()
2265            },
2266        }
2267    }
2268
2269    // Substrate-local two-slot factories — peers to the sibling
2270    // `single_slot_*_probe` block above. Each composes
2271    // `single_slot_*_probe(a)` with `single_slot_*_probe(b)`
2272    // through per-field `Option::or` on the parent's tagged-union
2273    // slots, matching the shape every per-site `two_slot_X(a, b)`
2274    // helper across the four production parents already carries.
2275    // The ambiguity-primitive only requires that BOTH addressed
2276    // slots on the parent are populated; the inner spec's exact
2277    // field values are irrelevant to the two-slot ambiguity check.
2278
2279    fn two_slot_intent_probe(
2280        a: crate::intent::IntentKind,
2281        b: crate::intent::IntentKind,
2282    ) -> crate::intent::Intent {
2283        let ia = single_slot_intent_probe(a);
2284        let ib = single_slot_intent_probe(b);
2285        crate::intent::Intent {
2286            nix: ia.nix.or(ib.nix),
2287            flux: ia.flux.or(ib.flux),
2288            lisp: ia.lisp.or(ib.lisp),
2289            container: ia.container.or(ib.container),
2290            aplicacao: ia.aplicacao.or(ib.aplicacao),
2291            guest: ia.guest.or(ib.guest),
2292        }
2293    }
2294
2295    fn two_slot_encapsulation_kind_probe(
2296        a: crate::encapsulates::EncapsulationTarget,
2297        b: crate::encapsulates::EncapsulationTarget,
2298    ) -> crate::encapsulates::EncapsulationKind {
2299        let ka = single_slot_encapsulation_kind_probe(a);
2300        let kb = single_slot_encapsulation_kind_probe(b);
2301        crate::encapsulates::EncapsulationKind {
2302            existing_helm_release: ka.existing_helm_release.or(kb.existing_helm_release),
2303            existing_kustomization: ka.existing_kustomization.or(kb.existing_kustomization),
2304            bare_workload: ka.bare_workload.or(kb.bare_workload),
2305        }
2306    }
2307
2308    fn two_slot_artifact_source_probe(
2309        a: crate::export::ArtifactKind,
2310        b: crate::export::ArtifactKind,
2311    ) -> crate::export::ArtifactSource {
2312        let sa = single_slot_artifact_source_probe(a);
2313        let sb = single_slot_artifact_source_probe(b);
2314        crate::export::ArtifactSource {
2315            receipts: sa.receipts.or(sb.receipts),
2316            test_report: sa.test_report.or(sb.test_report),
2317            process_snapshot: sa.process_snapshot.or(sb.process_snapshot),
2318            run_marker: sa.run_marker.or(sb.run_marker),
2319        }
2320    }
2321
2322    fn two_slot_vector_channel_probe(
2323        a: crate::export::ChannelKind,
2324        b: crate::export::ChannelKind,
2325    ) -> crate::export::VectorChannel {
2326        let ca = single_slot_vector_channel_probe(a);
2327        let cb = single_slot_vector_channel_probe(b);
2328        crate::export::VectorChannel {
2329            http_event: ca.http_event.or(cb.http_event),
2330            nats_subject: ca.nats_subject.or(cb.nats_subject),
2331            stdout: ca.stdout.or(cb.stdout),
2332        }
2333    }
2334
2335    /// The trait's `KIND_LIST` associated const IS the same
2336    /// `&'static str` the inherent `_LIST` constant publishes at
2337    /// each production site — pin identity via `std::ptr::eq` so a
2338    /// future silent copy (e.g. `const KIND_LIST: &'static str =
2339    /// "...literal...";` at the impl block) is caught here.
2340    #[test]
2341    fn production_tagged_union_kind_list_borrows_the_inherent_constant() {
2342        assert!(std::ptr::eq(
2343            <crate::intent::Intent as TaggedUnion>::KIND_LIST,
2344            crate::intent::INTENT_KIND_LIST,
2345        ));
2346        assert!(std::ptr::eq(
2347            <crate::encapsulates::EncapsulationKind as TaggedUnion>::KIND_LIST,
2348            crate::encapsulates::ENCAPSULATION_TARGET_LIST,
2349        ));
2350        assert!(std::ptr::eq(
2351            <crate::export::ArtifactSource as TaggedUnion>::KIND_LIST,
2352            crate::export::ARTIFACT_KIND_LIST,
2353        ));
2354        assert!(std::ptr::eq(
2355            <crate::export::VectorChannel as TaggedUnion>::KIND_LIST,
2356            crate::export::CHANNEL_KIND_LIST,
2357        ));
2358    }
2359
2360    // -------------------------------------------------------------------
2361    // `TaggedUnion::variant` default method — substrate primitive every
2362    // production `.variant()` inherent method delegates to. Pin the
2363    // four-outcome truth table (Empty on all-none, Ambiguous on many,
2364    // Ok on exactly-one at every position) directly on the sibling-
2365    // shaped local parent + local kind + local variant scaffold, so a
2366    // regression on the default body's short-circuit or
2367    // ClosedSet::ALL iteration shape fails here — before any per-parent
2368    // inherent test surfaces the drift.
2369    // -------------------------------------------------------------------
2370
2371    /// Every populated position across [`LocalKind::ALL`] resolves to
2372    /// its own [`LocalVariant`] arm through the default body's
2373    /// `resolve_or_err(<Kind as ClosedSet>::ALL.iter().copied()
2374    /// .map(|k| k.select(self)), KIND_LIST)` sweep. Pin every position
2375    /// so a regression that drifts the iteration order (or drops the
2376    /// `.iter().copied()` bridge to owned-`Copy` Kinds) fails at ONE
2377    /// substrate boundary rather than at four per-parent inherent test
2378    /// sites.
2379    #[test]
2380    fn tagged_union_default_variant_resolves_each_populated_slot() {
2381        let mut p = LocalParent {
2382            alpha: Some(11),
2383            ..Default::default()
2384        };
2385        assert_eq!(
2386            <LocalParent as TaggedUnion>::variant(&p).unwrap(),
2387            LocalVariant::Alpha(&11)
2388        );
2389        p = LocalParent {
2390            beta: Some(22),
2391            ..Default::default()
2392        };
2393        assert_eq!(
2394            <LocalParent as TaggedUnion>::variant(&p).unwrap(),
2395            LocalVariant::Beta(&22)
2396        );
2397        p = LocalParent {
2398            gamma: Some(33),
2399            ..Default::default()
2400        };
2401        assert_eq!(
2402            <LocalParent as TaggedUnion>::variant(&p).unwrap(),
2403            LocalVariant::Gamma(&33)
2404        );
2405    }
2406
2407    /// A [`LocalParent`] with no populated slot resolves through the
2408    /// default body to a [`TaggedUnionError::empty`] carrier whose
2409    /// payload IS the trait's [`TaggedUnion::KIND_LIST`] constant —
2410    /// pin identity via [`std::ptr::eq`] so a regression that
2411    /// composes a fresh `&'static str` at the empty arm (instead of
2412    /// carrying the trait's constant verbatim) is caught here. This
2413    /// is the substrate-wide guarantee the four production sites'
2414    /// operator diagnostics depend on: a rename at
2415    /// `<Parent as TaggedUnion>::KIND_LIST` reaches the error surface
2416    /// intact through ONE `&'static str` handoff.
2417    #[test]
2418    fn tagged_union_default_variant_empty_carries_kind_list_by_pointer() {
2419        let empty = LocalParent::default();
2420        let err = <LocalParent as TaggedUnion>::variant(&empty).unwrap_err();
2421        match err {
2422            LocalParentError::Empty(list) => {
2423                assert!(
2424                    std::ptr::eq(list, <LocalParent as TaggedUnion>::KIND_LIST),
2425                    "TaggedUnion::variant default must carry KIND_LIST by pointer, not by re-composition",
2426                );
2427            }
2428            LocalParentError::Ambiguous => {
2429                panic!("expected Empty carrier, got Ambiguous");
2430            }
2431        }
2432    }
2433
2434    /// A [`LocalParent`] with two populated slots resolves through
2435    /// the default body to a [`TaggedUnionError::ambiguous`] carrier —
2436    /// pin the Many arm at the substrate boundary so a regression
2437    /// that drops the short-circuit (or misroutes the Many arm to
2438    /// Empty) is caught here.
2439    #[test]
2440    fn tagged_union_default_variant_ambiguous_on_multiple_populated_slots() {
2441        let p = LocalParent {
2442            alpha: Some(1),
2443            beta: Some(2),
2444            gamma: None,
2445        };
2446        assert_eq!(
2447            <LocalParent as TaggedUnion>::variant(&p).unwrap_err(),
2448            LocalParentError::Ambiguous
2449        );
2450    }
2451
2452    /// Every one of the four production `.variant()` inherent methods
2453    /// dispatches through the trait's default body byte-identically —
2454    /// pin the delegation shape (inherent forwarder → trait default)
2455    /// on a probe per parent so a regression that copies the pre-lift
2456    /// hand-rolled `resolve_or_err(...)` body back into the inherent
2457    /// method (instead of the `<Self as TaggedUnion>::variant(self)`
2458    /// one-line delegation) reaches this substrate boundary before it
2459    /// reaches any operator diagnostic.
2460    #[test]
2461    fn every_production_inherent_variant_dispatches_through_trait_default() {
2462        use crate::encapsulates::{EncapsulationKind, EncapsulationKindError};
2463        use crate::export::{ArtifactError, ArtifactSource, ChannelError, VectorChannel};
2464        use crate::intent::{Intent, IntentError};
2465
2466        // Intent: default of all-None resolves to Empty via the delegation.
2467        let i = Intent::default();
2468        match (i.variant(), <Intent as TaggedUnion>::variant(&i)) {
2469            (Err(IntentError::Empty(a)), Err(IntentError::Empty(b))) => assert!(
2470                std::ptr::eq(a, b),
2471                "Intent inherent and trait dispatch must return the same &'static str",
2472            ),
2473            (a, b) => panic!("Intent inherent/trait mismatch: inherent={a:?}, trait={b:?}"),
2474        }
2475
2476        // EncapsulationKind: same Empty projection through both dispatch paths.
2477        let k = EncapsulationKind::default();
2478        match (k.variant(), <EncapsulationKind as TaggedUnion>::variant(&k)) {
2479            (Err(EncapsulationKindError::Empty(a)), Err(EncapsulationKindError::Empty(b))) => {
2480                assert!(
2481                std::ptr::eq(a, b),
2482                "EncapsulationKind inherent and trait dispatch must return the same &'static str",
2483            )
2484            }
2485            (a, b) => {
2486                panic!("EncapsulationKind inherent/trait mismatch: inherent={a:?}, trait={b:?}")
2487            }
2488        }
2489
2490        // ArtifactSource: same Empty projection through both dispatch paths.
2491        let s = ArtifactSource::default();
2492        match (s.variant(), <ArtifactSource as TaggedUnion>::variant(&s)) {
2493            (Err(ArtifactError::Empty(a)), Err(ArtifactError::Empty(b))) => assert!(
2494                std::ptr::eq(a, b),
2495                "ArtifactSource inherent and trait dispatch must return the same &'static str",
2496            ),
2497            (a, b) => panic!("ArtifactSource inherent/trait mismatch: inherent={a:?}, trait={b:?}"),
2498        }
2499
2500        // VectorChannel: same Empty projection through both dispatch paths.
2501        let c = VectorChannel::default();
2502        match (c.variant(), <VectorChannel as TaggedUnion>::variant(&c)) {
2503            (Err(ChannelError::Empty(a)), Err(ChannelError::Empty(b))) => assert!(
2504                std::ptr::eq(a, b),
2505                "VectorChannel inherent and trait dispatch must return the same &'static str",
2506            ),
2507            (a, b) => panic!("VectorChannel inherent/trait mismatch: inherent={a:?}, trait={b:?}"),
2508        }
2509    }
2510
2511    // -------------------------------------------------------------------
2512    // `declare_tagged_union_impls!` macro — the three-block impl stanza
2513    // (inherent `.variant()` forwarder + `VariantSelector<Parent>` on
2514    // the Kind + `TaggedUnion` on the parent) as ONE authoring surface.
2515    // Pin the macro's shape against a sibling-shaped local family so a
2516    // regression on any of the three emitted blocks fails here before
2517    // it reaches the four production sites.
2518    // -------------------------------------------------------------------
2519
2520    /// Local sibling-shaped Kind for the macro-emitted-impls test — a
2521    /// dedicated closed set so this test can't share substrate with the
2522    /// hand-rolled [`LocalKind`] block above. Uses
2523    /// [`tatara_closed_set::DeriveClosedSet`] so the macro's
2524    /// `TaggedUnion` bound (`Kind: ClosedSet + VariantSelector<Self>`)
2525    /// is satisfied through the derive.
2526    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, tatara_closed_set::DeriveClosedSet)]
2527    #[closed_set(via = "as_str", generate_unknown)]
2528    enum MacroLocalKind {
2529        Foo,
2530        Bar,
2531    }
2532
2533    impl MacroLocalKind {
2534        const ALL: [Self; 2] = [Self::Foo, Self::Bar];
2535        const fn as_str(self) -> &'static str {
2536            match self {
2537                Self::Foo => "foo",
2538                Self::Bar => "bar",
2539            }
2540        }
2541        fn select<'a>(self, parent: &'a MacroLocalParent) -> Option<MacroLocalVariant<'a>> {
2542            match self {
2543                Self::Foo => parent.foo.as_ref().map(MacroLocalVariant::Foo),
2544                Self::Bar => parent.bar.as_ref().map(MacroLocalVariant::Bar),
2545            }
2546        }
2547    }
2548
2549    /// Local sibling-shaped parent for the macro-emitted-impls test —
2550    /// distinct from [`LocalParent`] so the macro's emitted impls
2551    /// don't collide with the hand-rolled trait impls above.
2552    ///
2553    /// Derives [`serde::Serialize`] with `skip_serializing_if =
2554    /// "Option::is_none"` on every slot so the wire-format primitive
2555    /// [`assert_single_slot_key_matches_label`] can be exercised
2556    /// through the macro-emitted `TaggedUnion` impl path — pins the
2557    /// substrate-wide guarantee that a fifth sibling landing through
2558    /// [`declare_tagged_union_impls!`] picks up the wire-alignment
2559    /// check for free.
2560    #[derive(Default, serde::Serialize)]
2561    struct MacroLocalParent {
2562        #[serde(skip_serializing_if = "Option::is_none")]
2563        foo: Option<u32>,
2564        #[serde(skip_serializing_if = "Option::is_none")]
2565        bar: Option<u32>,
2566    }
2567
2568    /// Borrowed-view of a populated slot on [`MacroLocalParent`] — the
2569    /// return type of the macro-emitted inherent `.variant()`.
2570    #[derive(Debug, PartialEq)]
2571    enum MacroLocalVariant<'a> {
2572        Foo(&'a u32),
2573        Bar(&'a u32),
2574    }
2575
2576    impl VariantKind<MacroLocalKind> for MacroLocalVariant<'_> {
2577        fn variant_kind(&self) -> MacroLocalKind {
2578            match self {
2579                Self::Foo(_) => MacroLocalKind::Foo,
2580                Self::Bar(_) => MacroLocalKind::Bar,
2581            }
2582        }
2583    }
2584
2585    crate::declare_tagged_union_error! {
2586        pub(super) MacroLocalError,
2587        empty = "macro-local parent has no variant set (one of {0} required)",
2588        ambiguous = "macro-local parent has multiple variants set; exactly one required",
2589    }
2590
2591    /// Slash-joined kind list — literal peer of
2592    /// [`crate::intent::INTENT_KIND_LIST`] etc. that the macro's
2593    /// `KIND_LIST` associated const borrows verbatim.
2594    const MACRO_LOCAL_KIND_LIST: &str = "foo/bar";
2595
2596    // ONE macro call emits: inherent `MacroLocalParent::variant`,
2597    // `impl VariantSelector<MacroLocalParent> for MacroLocalKind`, and
2598    // `impl TaggedUnion for MacroLocalParent`. The four production
2599    // sites bind through this exact same call shape.
2600    crate::declare_tagged_union_impls! {
2601        parent = MacroLocalParent,
2602        kind = MacroLocalKind,
2603        variant = MacroLocalVariant,
2604        error = MacroLocalError,
2605        kind_list = MACRO_LOCAL_KIND_LIST,
2606    }
2607
2608    /// The macro-emitted `impl TaggedUnion` binds the (Kind, Error,
2609    /// KIND_LIST) triple exactly as a hand-rolled block would — pin
2610    /// the diagnostic-stability testkit primitive through the macro's
2611    /// output so a regression on any of the three associated items
2612    /// (say the macro pulling `KIND_LIST` from the wrong argument
2613    /// slot) fails here.
2614    #[test]
2615    fn macro_emitted_tagged_union_impl_binds_kind_list_coherently() {
2616        assert_kind_list_matches_closed_set::<MacroLocalParent>();
2617        assert!(std::ptr::eq(
2618            <MacroLocalParent as TaggedUnion>::KIND_LIST,
2619            MACRO_LOCAL_KIND_LIST,
2620        ));
2621    }
2622
2623    /// The macro-emitted inherent `.variant()` forwarder dispatches
2624    /// through the trait default body — every populated slot resolves
2625    /// to its own [`MacroLocalVariant`] arm, all-none resolves to
2626    /// [`TaggedUnionError::empty`] carrying the trait's `KIND_LIST`
2627    /// by pointer, two-populated resolves to
2628    /// [`TaggedUnionError::ambiguous`]. The four production sites
2629    /// exercise the same four-outcome truth table through the same
2630    /// macro-emitted delegation shape.
2631    #[test]
2632    fn macro_emitted_inherent_variant_dispatches_the_four_outcome_truth_table() {
2633        // Foo populated.
2634        let p = MacroLocalParent {
2635            foo: Some(11),
2636            bar: None,
2637        };
2638        assert_eq!(p.variant().unwrap(), MacroLocalVariant::Foo(&11));
2639
2640        // Bar populated.
2641        let p = MacroLocalParent {
2642            foo: None,
2643            bar: Some(22),
2644        };
2645        assert_eq!(p.variant().unwrap(), MacroLocalVariant::Bar(&22));
2646
2647        // All none — Empty arm carries the trait's KIND_LIST value.
2648        // The by-pointer preservation across the trait default body is
2649        // pinned substrate-wide by
2650        // `tagged_union_default_variant_empty_carries_kind_list_by_pointer`
2651        // on the sibling hand-rolled `LocalParent`; this test only pins
2652        // that the macro-emitted `KIND_LIST = MACRO_LOCAL_KIND_LIST`
2653        // assignment reaches the operator diagnostic value-identically.
2654        let p = MacroLocalParent::default();
2655        match p.variant().unwrap_err() {
2656            MacroLocalError::Empty(list) => assert_eq!(list, MACRO_LOCAL_KIND_LIST),
2657            MacroLocalError::Ambiguous => panic!("expected Empty, got Ambiguous"),
2658        }
2659
2660        // Two populated — Ambiguous.
2661        let p = MacroLocalParent {
2662            foo: Some(1),
2663            bar: Some(2),
2664        };
2665        assert_eq!(p.variant().unwrap_err(), MacroLocalError::Ambiguous);
2666    }
2667
2668    /// The macro-emitted `VariantSelector` impl's `select` body
2669    /// delegates to the Kind's inherent `<Kind>::select(self, parent)`
2670    /// — pin the delegation via `std::ptr::eq` on the returned
2671    /// borrowed view so a regression that inlines a divergent select
2672    /// body (rather than reaching the inherent method) is caught here.
2673    #[test]
2674    fn macro_emitted_variant_selector_delegates_to_inherent_select() {
2675        let p = MacroLocalParent {
2676            foo: Some(7),
2677            bar: None,
2678        };
2679        // Trait-dispatched select projects through the macro-emitted body.
2680        let via_trait =
2681            <MacroLocalKind as VariantSelector<MacroLocalParent>>::select(MacroLocalKind::Foo, &p)
2682                .unwrap();
2683        // Inherent select projects through the direct impl.
2684        let via_inherent = MacroLocalKind::Foo.select(&p).unwrap();
2685        match (via_trait, via_inherent) {
2686            (MacroLocalVariant::Foo(a), MacroLocalVariant::Foo(b)) => {
2687                assert!(
2688                    std::ptr::eq(a, b),
2689                    "macro-emitted VariantSelector::select must delegate to <Kind>::select — same borrow, not a copy",
2690                );
2691            }
2692            _ => panic!("expected Foo arm on both dispatch paths"),
2693        }
2694    }
2695
2696    /// The trait's default body sweeps `<Kind as ClosedSet>::ALL` in
2697    /// declaration order — pin the iteration order against the
2698    /// production `Kind::ALL` inherent const on every implementor so
2699    /// a regression on `DeriveClosedSet`'s ALL-projection (or a
2700    /// silent reorder of the enum's variant declarations that drifts
2701    /// only ONE of the two arrays) fails at ONE substrate boundary.
2702    #[test]
2703    fn every_production_kind_closedset_all_matches_inherent_all() {
2704        use crate::encapsulates::EncapsulationTarget;
2705        use crate::export::{ArtifactKind, ChannelKind};
2706        use crate::intent::IntentKind;
2707
2708        assert_eq!(
2709            <IntentKind as tatara_closed_set::ClosedSet>::ALL,
2710            IntentKind::ALL.as_slice(),
2711        );
2712        assert_eq!(
2713            <EncapsulationTarget as tatara_closed_set::ClosedSet>::ALL,
2714            EncapsulationTarget::ALL.as_slice(),
2715        );
2716        assert_eq!(
2717            <ArtifactKind as tatara_closed_set::ClosedSet>::ALL,
2718            ArtifactKind::ALL.as_slice(),
2719        );
2720        assert_eq!(
2721            <ChannelKind as tatara_closed_set::ClosedSet>::ALL,
2722            ChannelKind::ALL.as_slice(),
2723        );
2724    }
2725
2726    // -------------------------------------------------------------------
2727    // `VariantKind<K>` trait — reverse projection from a borrowed-variant
2728    // view back into its addressing Kind, and `assert_variant_round_trip`
2729    // as the substrate testkit primitive that composes it with
2730    // `VariantSelector::select` on the populated side. Pin the four-arm
2731    // truth table (every position round-trips through select→variant_kind
2732    // AND through variant()→variant_kind) directly on the sibling-shaped
2733    // local scaffold, so a regression on either projection or on the
2734    // resolver default body fails here — before any per-parent inherent
2735    // test surfaces the drift.
2736    // -------------------------------------------------------------------
2737
2738    /// Every populated position across [`LocalKind::ALL`] round-trips
2739    /// through both `select→variant_kind` AND `variant()→variant_kind`
2740    /// on the sibling-shaped local scaffold. Pins the substrate
2741    /// primitive's four-arm truth table at ONE boundary — a regression
2742    /// on either projection direction (or on the resolver default
2743    /// short-circuit / iteration order) fails here before any per-parent
2744    /// inherent test surfaces the drift.
2745    #[test]
2746    fn assert_variant_round_trip_accepts_coherent_local_impl() {
2747        fn make_local(k: LocalKind) -> LocalParent {
2748            match k {
2749                LocalKind::Alpha => LocalParent {
2750                    alpha: Some(11),
2751                    ..Default::default()
2752                },
2753                LocalKind::Beta => LocalParent {
2754                    beta: Some(22),
2755                    ..Default::default()
2756                },
2757                LocalKind::Gamma => LocalParent {
2758                    gamma: Some(33),
2759                    ..Default::default()
2760                },
2761            }
2762        }
2763        assert_variant_round_trip::<LocalParent, _>(make_local);
2764    }
2765
2766    /// The testkit primitive is a `#[track_caller]` compound-lift: a
2767    /// factory that fails to populate the addressed slot fails at the
2768    /// caller's site with a labeled panic message, not silently. Pin
2769    /// the failing case with a deliberately empty parent factory so a
2770    /// regression that drops the "select must return Some" check
2771    /// fails-loudly here — the missing-slot arm is the substrate
2772    /// primitive's first failure mode.
2773    #[test]
2774    #[should_panic(expected = "VariantSelector::select must return Some for populated slot")]
2775    fn assert_variant_round_trip_rejects_factory_that_leaves_slot_empty() {
2776        // Factory that returns an all-empty parent regardless of k —
2777        // every `k.select(&parent)` returns None, so the primitive
2778        // panics at the "must return Some" arm.
2779        fn empty_factory(_: LocalKind) -> LocalParent {
2780            LocalParent::default()
2781        }
2782        assert_variant_round_trip::<LocalParent, _>(empty_factory);
2783    }
2784
2785    // -------------------------------------------------------------------
2786    // `assert_two_slots_ambiguous` — the ALL×ALL ambiguity sweep as ONE
2787    // substrate primitive. Pin the truth table (every off-diagonal pair
2788    // resolves to `TaggedUnionError::ambiguous`, diagonal pairs are
2789    // skipped, a factory that yields a non-Ambiguous parent fails-loudly
2790    // at the caller's site) directly on the sibling-shaped `LocalParent`
2791    // scaffold — a regression on either the pair-iteration order or the
2792    // expected-carrier composition fails here before any per-parent test
2793    // surfaces the drift.
2794    // -------------------------------------------------------------------
2795
2796    /// Every off-diagonal pair across [`LocalKind::ALL`] × `ALL`
2797    /// resolves through the substrate primitive to
2798    /// [`LocalParentError::Ambiguous`] on the sibling-shaped local
2799    /// scaffold. Pins the primitive's Ok arm (no false positives on the
2800    /// coherent-impl side) at ONE boundary — a regression that drops
2801    /// the diagonal skip, mis-iterates `ClosedSet::ALL`, or composes a
2802    /// divergent expected carrier fails here before any per-parent
2803    /// inherent test surfaces the drift.
2804    #[test]
2805    fn assert_two_slots_ambiguous_accepts_coherent_local_impl() {
2806        fn two_local(a: LocalKind, b: LocalKind) -> LocalParent {
2807            let mut p = LocalParent::default();
2808            for k in [a, b] {
2809                match k {
2810                    LocalKind::Alpha => p.alpha = Some(11),
2811                    LocalKind::Beta => p.beta = Some(22),
2812                    LocalKind::Gamma => p.gamma = Some(33),
2813                }
2814            }
2815            p
2816        }
2817        assert_two_slots_ambiguous::<LocalParent, _>(two_local);
2818    }
2819
2820    /// A factory that yields a single-slot parent for the FIRST kind
2821    /// (ignoring the second) — every off-diagonal pair resolves to
2822    /// exactly-one Ok(Variant), NOT Ambiguous — MUST fail-loudly at
2823    /// the caller's site through the primitive's "two-slot parent
2824    /// must not resolve to a variant" arm. Pin the Ok-side failure
2825    /// mode so a regression that mis-routes the substrate primitive's
2826    /// resolved-Ok arm past the assertion (silently succeeding on a
2827    /// single-slot factory) is caught here.
2828    #[test]
2829    #[should_panic(expected = "two-slot parent must not resolve to a variant")]
2830    fn assert_two_slots_ambiguous_rejects_factory_that_populates_only_one_slot() {
2831        fn single_only(a: LocalKind, _: LocalKind) -> LocalParent {
2832            let mut p = LocalParent::default();
2833            match a {
2834                LocalKind::Alpha => p.alpha = Some(11),
2835                LocalKind::Beta => p.beta = Some(22),
2836                LocalKind::Gamma => p.gamma = Some(33),
2837            }
2838            p
2839        }
2840        assert_two_slots_ambiguous::<LocalParent, _>(single_only);
2841    }
2842
2843    /// A factory that yields an all-empty parent (so `.variant()`
2844    /// resolves to the `Empty` carrier, NOT `Ambiguous`) MUST
2845    /// fail-loudly at the caller's site through the primitive's
2846    /// `assert_eq!` arm — the composed expected carrier
2847    /// [`TaggedUnionError::ambiguous`] mismatches the resolved
2848    /// [`TaggedUnionError::empty`] carrier. Pin the Empty-arm failure
2849    /// mode so a regression that mis-projects the None arm of
2850    /// [`ResolveError`] onto Ambiguous (silently succeeding on an
2851    /// empty factory) is caught here.
2852    #[test]
2853    #[should_panic(expected = "should resolve Ambiguous")]
2854    fn assert_two_slots_ambiguous_rejects_factory_that_populates_no_slots() {
2855        fn empty_factory(_: LocalKind, _: LocalKind) -> LocalParent {
2856            LocalParent::default()
2857        }
2858        assert_two_slots_ambiguous::<LocalParent, _>(empty_factory);
2859    }
2860
2861    // -------------------------------------------------------------------
2862    // `assert_single_slot_key_matches_label` — the wire-key / kind-label
2863    // alignment sweep as ONE substrate primitive. Pin the truth table
2864    // (every populated slot serializes to exactly one JSON key whose
2865    // name equals the addressing kind's ClosedSet label; a factory that
2866    // populates the wrong slot / no slot / multiple slots fails-loudly
2867    // at the caller's site) directly on the sibling-shaped `LocalParent`
2868    // scaffold — a regression on either the exactly-one arm or the
2869    // name-equality arm fails here before any per-parent inherent test
2870    // surfaces the drift.
2871    // -------------------------------------------------------------------
2872
2873    /// Every kind across [`LocalKind::ALL`] serializes through the
2874    /// substrate primitive to a JSON object with EXACTLY ONE key whose
2875    /// name equals `<LocalKind as ClosedSet>::label` on the addressed
2876    /// kind. Pins the primitive's Ok arm (no false positives on the
2877    /// coherent-impl side) at ONE boundary — a regression that inspects
2878    /// the wrong serde value (e.g. `to_string` instead of `to_value`),
2879    /// counts fields off-by-one, or projects the wrong `ClosedSet`
2880    /// method (`labels_joined` instead of `label`) fails here before any
2881    /// per-parent inherent test surfaces the drift.
2882    #[test]
2883    fn assert_single_slot_key_matches_label_accepts_coherent_local_impl() {
2884        fn make_local(k: LocalKind) -> LocalParent {
2885            match k {
2886                LocalKind::Alpha => LocalParent {
2887                    alpha: Some(11),
2888                    ..Default::default()
2889                },
2890                LocalKind::Beta => LocalParent {
2891                    beta: Some(22),
2892                    ..Default::default()
2893                },
2894                LocalKind::Gamma => LocalParent {
2895                    gamma: Some(33),
2896                    ..Default::default()
2897                },
2898            }
2899        }
2900        assert_single_slot_key_matches_label::<LocalParent, _>(make_local);
2901    }
2902
2903    /// A factory that returns a single-slot parent for the WRONG kind
2904    /// (populates `beta` regardless of what kind is asked for) MUST
2905    /// fail-loudly at the caller's site through the primitive's
2906    /// name-equality arm — the emitted key does not match the addressed
2907    /// kind's label. Pins the drift-detection failure mode so a
2908    /// regression that drops the `assert_eq!(keys[0], label)` arm
2909    /// (silently succeeding on any-key-at-all) is caught here. The
2910    /// caller's site is the `#[should_panic]` boundary through the
2911    /// primitive's `#[track_caller]` compound-lift.
2912    #[test]
2913    #[should_panic(expected = "wire-key drift")]
2914    fn assert_single_slot_key_matches_label_rejects_factory_that_populates_wrong_slot() {
2915        fn always_beta(_: LocalKind) -> LocalParent {
2916            LocalParent {
2917                beta: Some(22),
2918                ..Default::default()
2919            }
2920        }
2921        assert_single_slot_key_matches_label::<LocalParent, _>(always_beta);
2922    }
2923
2924    /// A factory that returns an all-empty parent (so serializing
2925    /// yields ZERO keys, not exactly-one) MUST fail-loudly at the
2926    /// caller's site through the primitive's exactly-one arm. Pins the
2927    /// zero-key failure mode so a regression that projects
2928    /// `obj.keys().count() >= 1` (rather than `== 1`) is caught here.
2929    #[test]
2930    #[should_panic(expected = "exactly one populated field")]
2931    fn assert_single_slot_key_matches_label_rejects_factory_that_populates_no_slots() {
2932        fn empty_factory(_: LocalKind) -> LocalParent {
2933            LocalParent::default()
2934        }
2935        assert_single_slot_key_matches_label::<LocalParent, _>(empty_factory);
2936    }
2937
2938    /// A factory that returns a parent with TWO populated slots (so
2939    /// serializing yields two keys, not exactly-one) MUST fail-loudly
2940    /// at the caller's site through the primitive's exactly-one arm.
2941    /// Pins the many-keys failure mode so a regression that projects
2942    /// `obj.keys().count() <= 1` (rather than `== 1`) is caught here.
2943    /// Cross-pins the substrate promise that a single-slot factory
2944    /// truly populates ONE slot — a future factory bug that leaks
2945    /// residual populated slots between calls (e.g. via shared mutable
2946    /// state) is caught HERE at the primitive boundary.
2947    #[test]
2948    #[should_panic(expected = "exactly one populated field")]
2949    fn assert_single_slot_key_matches_label_rejects_factory_that_populates_two_slots() {
2950        fn two_slot_factory(_: LocalKind) -> LocalParent {
2951            LocalParent {
2952                alpha: Some(1),
2953                beta: Some(2),
2954                gamma: None,
2955            }
2956        }
2957        assert_single_slot_key_matches_label::<LocalParent, _>(two_slot_factory);
2958    }
2959
2960    /// The macro-emitted [`MacroLocalParent`] scaffold impls
2961    /// [`TaggedUnion`] through the [`declare_tagged_union_impls!`]
2962    /// three-block macro AND additionally derives `serde::Serialize` +
2963    /// `#[serde(skip_serializing_if = "Option::is_none")]` on every
2964    /// slot — so the wire-key primitive dispatches on the MACRO-emitted
2965    /// impl path byte-identically with the hand-rolled [`LocalParent`]
2966    /// path above. Pins the substrate-wide guarantee that a fifth
2967    /// sibling landing through the macro picks up the wire-alignment
2968    /// check for free, without a hand-rolled `TaggedUnion` block, so
2969    /// long as its serde derives match the substrate-wide
2970    /// `skip_serializing_if = "Option::is_none"` shape every production
2971    /// site already carries. A regression that mis-routes the
2972    /// primitive's serialize call through the WRONG entry point (e.g.
2973    /// calling a bespoke `to_json` that bypasses serde) is caught here.
2974    #[test]
2975    fn assert_single_slot_key_matches_label_accepts_macro_emitted_impl() {
2976        fn make_macro_local(k: MacroLocalKind) -> MacroLocalParent {
2977            match k {
2978                MacroLocalKind::Foo => MacroLocalParent {
2979                    foo: Some(7),
2980                    bar: None,
2981                },
2982                MacroLocalKind::Bar => MacroLocalParent {
2983                    foo: None,
2984                    bar: Some(8),
2985                },
2986            }
2987        }
2988        assert_single_slot_key_matches_label::<MacroLocalParent, _>(make_macro_local);
2989    }
2990
2991    // -------------------------------------------------------------------
2992    // `assert_wire_key_matches_label` — bound-relaxed peer of the
2993    // `assert_single_slot_key_matches_label` primitive. Pin the truth
2994    // table (every populated slot serializes to exactly one JSON key
2995    // whose name equals the addressing kind's ClosedSet label; a
2996    // factory that populates the wrong slot / no slot / multiple slots
2997    // fails-loudly at the caller's site) on a NON-TaggedUnion parent
2998    // scaffold — the delegation-only path from the trait-projected
2999    // primitive would silently pass this test if the bound-relaxed
3000    // primitive's body regressed, so the direct-dispatch probes here
3001    // pin the bound-relaxed pathway independently.
3002    // -------------------------------------------------------------------
3003
3004    /// Local parent that carries the wire-format shape (`Option<T>`
3005    /// slots + `#[serde(skip_serializing_if = "Option::is_none")]`
3006    /// annotations) but DELIBERATELY does NOT impl [`TaggedUnion`] —
3007    /// pins the bound-relaxed sweep on the exact shape [`crate::lifetime::Lifetime`]
3008    /// carries in production (empty resolves to a default variant,
3009    /// not to a typed error, so the trait's `T::Error` bound doesn't
3010    /// hold and the trait-projected surface excludes it).
3011    #[derive(Default, serde::Serialize)]
3012    struct BareParent {
3013        #[serde(skip_serializing_if = "Option::is_none")]
3014        alpha: Option<u32>,
3015        #[serde(skip_serializing_if = "Option::is_none")]
3016        beta: Option<u32>,
3017        #[serde(skip_serializing_if = "Option::is_none")]
3018        gamma: Option<u32>,
3019    }
3020
3021    /// The bound-relaxed primitive dispatches Ok on a coherent
3022    /// non-TaggedUnion impl — pin the happy path directly on the
3023    /// [`BareParent`] scaffold so a regression that gates the sweep
3024    /// body on the `T: TaggedUnion` bound (accidentally re-adding it,
3025    /// or projecting through `T::Kind` instead of the caller-supplied
3026    /// `K` generic) fails HERE at the primitive-independent boundary
3027    /// rather than at the [`crate::lifetime::Lifetime`] production
3028    /// site alone. The Ok arm is the "no drift" outcome; a divergence
3029    /// surfaces as a labeled assertion failure at the caller site
3030    /// (this test's own line) via the primitive's `#[track_caller]`.
3031    #[test]
3032    fn assert_wire_key_matches_label_accepts_coherent_bare_parent_impl() {
3033        fn make_bare(k: LocalKind) -> BareParent {
3034            match k {
3035                LocalKind::Alpha => BareParent {
3036                    alpha: Some(11),
3037                    ..Default::default()
3038                },
3039                LocalKind::Beta => BareParent {
3040                    beta: Some(22),
3041                    ..Default::default()
3042                },
3043                LocalKind::Gamma => BareParent {
3044                    gamma: Some(33),
3045                    ..Default::default()
3046                },
3047            }
3048        }
3049        assert_wire_key_matches_label::<BareParent, LocalKind, _>(make_bare);
3050    }
3051
3052    /// A factory that returns a bare-parent for the WRONG kind
3053    /// (populates `beta` regardless of what kind is asked for) MUST
3054    /// fail-loudly at the caller's site through the bound-relaxed
3055    /// primitive's name-equality arm — the emitted key does not match
3056    /// the addressed kind's label. Pins the drift-detection failure
3057    /// mode on the non-TaggedUnion pathway so a regression that drops
3058    /// the `assert_eq!(keys[0], label)` arm (silently succeeding on
3059    /// any-key-at-all) is caught here — mechanical peer of the
3060    /// sibling `assert_single_slot_key_matches_label_rejects_factory_that_populates_wrong_slot`
3061    /// on the TaggedUnion pathway.
3062    #[test]
3063    #[should_panic(expected = "wire-key drift")]
3064    fn assert_wire_key_matches_label_rejects_factory_that_populates_wrong_slot() {
3065        fn always_beta(_: LocalKind) -> BareParent {
3066            BareParent {
3067                beta: Some(22),
3068                ..Default::default()
3069            }
3070        }
3071        assert_wire_key_matches_label::<BareParent, LocalKind, _>(always_beta);
3072    }
3073
3074    /// A factory that returns an all-empty bare-parent (so serializing
3075    /// yields ZERO keys, not exactly-one) MUST fail-loudly at the
3076    /// caller's site through the bound-relaxed primitive's
3077    /// exactly-one arm. Pins the zero-key failure mode on the
3078    /// non-TaggedUnion pathway.
3079    #[test]
3080    #[should_panic(expected = "exactly one populated field")]
3081    fn assert_wire_key_matches_label_rejects_factory_that_populates_no_slots() {
3082        fn empty_factory(_: LocalKind) -> BareParent {
3083            BareParent::default()
3084        }
3085        assert_wire_key_matches_label::<BareParent, LocalKind, _>(empty_factory);
3086    }
3087
3088    /// The trait-projected [`assert_single_slot_key_matches_label`]
3089    /// is a one-line delegation to the bound-relaxed
3090    /// [`assert_wire_key_matches_label`] peer — pin the delegation
3091    /// shape at ONE boundary so a regression that inlines a
3092    /// divergent sweep body into the trait-projected surface (rather
3093    /// than the one-line dispatch) is caught here. Ok on a coherent
3094    /// impl means BOTH primitives dispatch through the SAME body on
3095    /// the same fixture — [`LocalParent`] impls [`TaggedUnion`], so
3096    /// both the trait-projected surface and the bound-relaxed peer
3097    /// reach it, and a divergence between the two dispatches would
3098    /// surface here as one succeeding + the other failing.
3099    #[test]
3100    fn assert_single_slot_key_matches_label_delegates_to_wire_key_matches_label() {
3101        fn make_local(k: LocalKind) -> LocalParent {
3102            match k {
3103                LocalKind::Alpha => LocalParent {
3104                    alpha: Some(11),
3105                    ..Default::default()
3106                },
3107                LocalKind::Beta => LocalParent {
3108                    beta: Some(22),
3109                    ..Default::default()
3110                },
3111                LocalKind::Gamma => LocalParent {
3112                    gamma: Some(33),
3113                    ..Default::default()
3114                },
3115            }
3116        }
3117        // Both surfaces reach the same body — dispatched here through
3118        // BOTH entry points so a divergence between them fails one
3119        // arm while the other passes.
3120        assert_single_slot_key_matches_label::<LocalParent, _>(make_local);
3121        assert_wire_key_matches_label::<LocalParent, LocalKind, _>(make_local);
3122    }
3123
3124    /// Every one of the five production borrowed-view enums impls
3125    /// [`VariantKind`] byte-identically with its inherent `.kind()`
3126    /// (or `.target()` on `EncapsulationKindVariant`) — pin the
3127    /// delegation shape at ONE substrate boundary so a regression that
3128    /// inlines a divergent match body into the trait impl (rather than
3129    /// the one-line delegation) is caught here. `Lifetime`'s
3130    /// borrowed-view is included even though `Lifetime` isn't a
3131    /// [`TaggedUnion`] impl — the reverse projection applies uniformly.
3132    #[test]
3133    fn every_production_variant_kind_impl_matches_inherent_projection() {
3134        use crate::encapsulates::{EncapsulationKindVariant, ExistingHelmRelease};
3135        use crate::export::{ArtifactVariant, ChannelVariant, HttpEventChannel, ReceiptsSource};
3136        use crate::intent::{IntentVariant, NixIntent};
3137        use crate::lifetime::{LifetimeVariant, PermanentLifetime};
3138
3139        let nix = NixIntent {
3140            flake_ref: "github:a/b".into(),
3141            attribute: "x".into(),
3142            system: None,
3143            attic_cache: None,
3144            extra_args: vec![],
3145            delegate_to_nix_build: false,
3146        };
3147        let iv = IntentVariant::Nix(&nix);
3148        assert_eq!(iv.kind(), iv.variant_kind());
3149
3150        let perm = PermanentLifetime::default();
3151        let lv = LifetimeVariant::Permanent(&perm);
3152        assert_eq!(lv.kind(), lv.variant_kind());
3153
3154        let hr = ExistingHelmRelease {
3155            namespace: "ns".into(),
3156            name: "n".into(),
3157            release_name: "r".into(),
3158        };
3159        let ev = EncapsulationKindVariant::ExistingHelmRelease(&hr);
3160        assert_eq!(ev.target(), ev.variant_kind());
3161
3162        let rs = ReceiptsSource {};
3163        let av = ArtifactVariant::Receipts(&rs);
3164        assert_eq!(av.kind(), av.variant_kind());
3165
3166        let ch = HttpEventChannel {
3167            endpoint: None,
3168            signal_type: "s".into(),
3169        };
3170        let cv = ChannelVariant::HttpEvent(&ch);
3171        assert_eq!(cv.kind(), cv.variant_kind());
3172    }
3173}