tatara_process/ephemeral.rs
1//! `EphemeralSpec` — the operator-facing typed surface for ephemeral
2//! Aplicacao installations.
3//!
4//! `EphemeralSpec` is *sugar* on top of `ProcessSpec`. The compounding move
5//! is to keep one wire format (`Process`, the Unix-process CRD) and let
6//! ephemeral envs be a Process with `:intent (:aplicacao …)` +
7//! `:lifetime (:ephemeral …)`. This struct gives that combination a
8//! dedicated `(defephemeral …)` keyword and a typed `From` bridge so
9//! authoring stays first-class without forking the CRD.
10//!
11//! Lisp authoring:
12//! ```lisp
13//! (defephemeral closed-loop-attest
14//! :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
15//! :version "0.5.5"
16//! :profile "all-in-one"
17//! :values-overlay (:cluster (:name "ephemeral-test-01")
18//! :persistence false))
19//! :ttl "1h"
20//! :teardown OnAttested
21//! :postconditions
22//! ((:kind HelmReleaseReleased
23//! :params (:name "demo-app-consolidated"
24//! :namespace "demo-test"))
25//! (:kind ClosedLoopAuth
26//! :params (:issuer (:service "demo-app-issuer" :port 8080)
27//! :consumer (:service "demo-app-gateway" :port 8000)
28//! :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
29//! ```
30
31use std::borrow::Cow;
32
33use schemars::JsonSchema;
34use serde::{Deserialize, Serialize};
35use tatara_lisp::DeriveTataraDomain;
36
37use crate::boundary::{Boundary, Condition, ConditionKind, ConditionSliceExt};
38use crate::classification::{
39 Arity, CalmClassification, Classification, ClassificationAxis, ConvergencePointType,
40 DataClassification, HorizonKind, OptimizationDirection, SubstrateType,
41};
42use crate::crd::ProcessSpec;
43use crate::export::{ExportSpec, ExportSpecSliceExt};
44use crate::intent::{AplicacaoIntent, Intent};
45use crate::lifetime::{EphemeralLifetime, Lifetime, TeardownPolicy};
46use crate::phase::ProcessPhase;
47use crate::routing::{RoutingForm, RoutingSpec};
48
49/// `EphemeralSpec` — typed wrapper that authors `(defephemeral …)`.
50///
51/// Lowers to a `ProcessSpec` via `From<EphemeralSpec>` — the bridge is
52/// pure-typed, no string substitution. Defaults to `point_type = Gate`,
53/// `substrate = Compute`, `data_classification = Internal` — every field
54/// can be overridden via the full `(defpoint …)` form when the operator
55/// needs the lower-level surface.
56#[derive(DeriveTataraDomain, Clone, Debug, Serialize, Deserialize, JsonSchema)]
57#[serde(rename_all = "camelCase")]
58#[tatara(keyword = "defephemeral")]
59pub struct EphemeralSpec {
60 /// The Aplicacao chart + profile + overlay to install.
61 pub aplicacao: AplicacaoIntent,
62
63 /// TTL — `humantime` duration (`"1h"`, `"30m"`).
64 #[serde(default = "crate::lifetime::default_ephemeral_ttl")]
65 pub ttl: String,
66
67 /// When the ephemeral Process auto-terminates.
68 #[serde(default)]
69 pub teardown: TeardownPolicy,
70
71 /// Cluster-wide concurrency budget across ephemeral Processes sharing
72 /// the same `:aplicacao :chart-ref`. `0` = no cap.
73 #[serde(default = "crate::lifetime::default_ephemeral_max_concurrent")]
74 pub max_concurrent: u32,
75
76 /// Boundary postconditions evaluated before reaching `Attested`.
77 /// Typically `HelmReleaseReleased` plus one or more `ClosedLoopAuth`
78 /// / `JobAttested` checks for test suites + closed-loop probes.
79 #[serde(default)]
80 pub postconditions: Vec<Condition>,
81
82 /// Optional boundary preconditions (Namespace, Issuer, PullSecret
83 /// readiness etc.).
84 #[serde(default)]
85 pub preconditions: Vec<Condition>,
86
87 /// VERIFY-phase timeout. Empty = controller default.
88 #[serde(default, skip_serializing_if = "Option::is_none")]
89 pub verify_timeout: Option<String>,
90
91 /// Optional Process classification override. When omitted, defaults
92 /// to `Gate / Compute / Internal / Bounded / NonMonotone`.
93 #[serde(default, skip_serializing_if = "Option::is_none")]
94 pub classification: Option<Classification>,
95
96 /// Optional parent PID path.
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub parent: Option<String>,
99
100 /// Declared exports — sugar that propagates through to
101 /// `lifetime.ephemeral.exports` on the lowered `ProcessSpec`.
102 /// Default empty = zero-trace ephemeral (nothing survives
103 /// teardown). See [`crate::export`] for the full type.
104 #[serde(default, skip_serializing_if = "Vec::is_empty")]
105 pub exports: Vec<ExportSpec>,
106
107 /// Routing template — DNS + Ingress declarations inherited by
108 /// the materialized `ProcessSpec`. When set on a pool's
109 /// `template`, every member receives the same shape; each
110 /// member's content-hash form differs by its own canonical
111 /// spec (which differs across members by slot index).
112 /// See [`crate::routing`].
113 #[serde(default, skip_serializing_if = "Option::is_none")]
114 pub routing: Option<RoutingSpec>,
115}
116
117// `default_ttl` + `default_max_concurrent` bindings for the two serde
118// `#[serde(default = "…")]` slots above route through the ONE
119// substrate owner [`crate::lifetime::default_ephemeral_ttl`] +
120// [`crate::lifetime::default_ephemeral_max_concurrent`] — peer of
121// the [`EphemeralLifetime`] serde-default slots on the SAME
122// workspace-canonical "ephemeral wire-form defaults" axis.
123// Pre-lift both slots carried their own private
124// `fn default_*` shims that returned bytewise-identical `"1h"` /
125// `1` values as the peer [`EphemeralLifetime`] slots — one of THREE
126// (TTL) and TWO (max-concurrent) restatements past the ★★ PRIME-
127// DIRECTIVE ≥ 2 duplication threshold. See the substrate owner's
128// doc-comment for the full migration rationale.
129
130impl EphemeralSpec {
131 /// True iff at least one [`Condition`] in
132 /// `preconditions ∪ postconditions` carries the given
133 /// [`ConditionKind`] — the peer of
134 /// [`crate::boundary::Boundary::has_condition_kind`] on the
135 /// [`EphemeralSpec`] surface.
136 ///
137 /// # Semantics — byte-identical to [`Boundary::has_condition_kind`]
138 ///
139 /// The two condition vectors are unioned: a caller asking "does this
140 /// ephemeral spec name a `ClosedLoopAuth` predicate anywhere" doesn't
141 /// care whether the operator authored it on the pre- or post-
142 /// condition side. A spec with the given kind on ONLY preconditions
143 /// returns `true`; a spec with the given kind on ONLY postconditions
144 /// returns `true`; a spec with neither returns `false`.
145 ///
146 /// Both halves compose through the SAME slice-level substrate
147 /// primitive [`ConditionSliceExt::has_kind`] that
148 /// [`Boundary::has_condition_kind`] walks — so a regression at the
149 /// per-slice presence probe fails at that primitive's tests rather
150 /// than as silent drift at either struct-level union caller.
151 ///
152 /// # Sibling to [`Boundary::has_condition_kind`]
153 ///
154 /// Same shape, same axis, same body — [`Boundary::has_condition_kind`]
155 /// composes `preconditions ∪ postconditions` on the point-domain
156 /// [`ProcessSpec`]'s nested [`Boundary`] slot;
157 /// [`Self::has_condition_kind`] composes the SAME union on
158 /// [`EphemeralSpec`]'s direct pre/post fields. `EphemeralSpec` has no
159 /// nested [`Boundary`] struct — the pre/post condition vectors are
160 /// stored directly on the sugar-surface type — so a byte-identical
161 /// inherent method here lets the ephemeral require-tag surface in
162 /// `tatara-reconciler::bin::tatara-check` publish a `condition-<kind>`
163 /// closed-set prefix family byte-for-byte symmetrical with the point
164 /// surface's family via [`Boundary::has_condition_kind`].
165 ///
166 /// # Compounding
167 ///
168 /// The ephemeral require-tag classifier composes this primitive with
169 /// the closed-set `FromStr` autoderived on [`ConditionKind`] through
170 /// the `strip_and_classify_prefixed_kind` substrate to publish a
171 /// fifth closed-set-driven prefix family across the workspace-wide
172 /// require-tag algebra (peer of `intent-<kind>` / `lifetime-<kind>` /
173 /// `condition-<kind>` / `must-reach-<kind>` on the point surface). A
174 /// future [`ConditionKind`] variant added to `ALL` reaches BOTH
175 /// surfaces' `condition-<kind>` prefix families through the SAME
176 /// closed-set walk with no per-caller edit — the two-surface
177 /// symmetry means adding a variant on the closed set publishes it in
178 /// lockstep across every downstream consumer.
179 ///
180 /// A future normalization at the presence-probe shape (a widened
181 /// return carrying the matching Condition ref, a debug-build
182 /// assertion on pre/post drift, a fleet-wide warn on redundant
183 /// duplicates) lands at the ONE slice-level substrate primitive
184 /// [`ConditionSliceExt::has_kind`] both this method and
185 /// [`Boundary::has_condition_kind`] compose against — so the two
186 /// struct-level union methods stay symmetric by construction.
187 ///
188 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
189 /// proofs — the union body composes the SAME slice-level substrate
190 /// primitive on both this ephemeral surface and the point-domain
191 /// [`Boundary`] surface). THEORY.md §VI.1 (generation over
192 /// composition — a future [`ConditionKind`] variant added to `ALL`
193 /// reaches both `condition-<kind>` require-tag surfaces mechanically
194 /// through the SAME closed-set walk).
195 #[must_use]
196 pub fn has_condition_kind(&self, kind: ConditionKind) -> bool {
197 self.has_precondition_kind(kind) || self.has_postcondition_kind(kind)
198 }
199
200 /// True iff at least one [`Condition`] in `self.preconditions`
201 /// carries the given [`ConditionKind`] — the precondition-side arm
202 /// of the (precondition, postcondition, condition-union) triad on
203 /// [`EphemeralSpec`], sibling to [`Self::has_postcondition_kind`]
204 /// and half-composition of [`Self::has_condition_kind`].
205 ///
206 /// Thin typed delegate to [`ConditionSliceExt::has_kind`] over
207 /// [`Self::preconditions`]. Peer of
208 /// [`crate::boundary::Boundary::has_precondition_kind`] on the
209 /// point-domain surface — both peers compose against the SAME
210 /// slice-level substrate primitive
211 /// ([`crate::boundary::ConditionSliceExt::has_kind`]) so a
212 /// regression at the per-slice presence probe fails at that
213 /// primitive's tests rather than as silent drift at either
214 /// struct-level half-slice arm.
215 ///
216 /// # Why lift
217 ///
218 /// See [`crate::boundary::Boundary::has_precondition_kind`] for
219 /// the full rationale — the two surfaces (point + ephemeral)
220 /// publish their `precondition-<kind>` / `postcondition-<kind>`
221 /// require-tag prefix families byte-for-byte symmetrical, each
222 /// through its own struct-level half-slice arm. Post-lift the
223 /// (precondition, postcondition, condition-union) triad lives at
224 /// ONE typed algebra surface per struct rather than at a mixed
225 /// (union-arm-via-method, half-slice-arms-via-direct-field-access)
226 /// asymmetry on the ephemeral side.
227 ///
228 /// # Semantics — byte-identical to the point-domain peer
229 ///
230 /// Returns `true` iff `self.preconditions.iter().any(|c| c.kind ==
231 /// kind)`. Ignores `self.postconditions` — an operator who
232 /// authored the kind on ONLY postconditions gets `false` from this
233 /// probe and `true` from [`Self::has_postcondition_kind`]. The two
234 /// half-slice arms partition the (kind, side) matrix exhaustively
235 /// across the four states (kind absent both, pre-only, post-only,
236 /// both).
237 #[must_use]
238 pub fn has_precondition_kind(&self, kind: ConditionKind) -> bool {
239 self.preconditions.has_kind(kind)
240 }
241
242 /// True iff at least one [`Condition`] in `self.postconditions`
243 /// carries the given [`ConditionKind`] — the postcondition-side arm
244 /// of the (precondition, postcondition, condition-union) triad on
245 /// [`EphemeralSpec`], sibling to [`Self::has_precondition_kind`]
246 /// and half-composition of [`Self::has_condition_kind`].
247 ///
248 /// Thin typed delegate to [`ConditionSliceExt::has_kind`] over
249 /// [`Self::postconditions`]. Peer of
250 /// [`crate::boundary::Boundary::has_postcondition_kind`] on the
251 /// point-domain surface. See [`Self::has_precondition_kind`] for
252 /// the full rationale — both half-slice arms share ONE lift
253 /// motivation, ONE fail-before-pass-after composition-law pin, and
254 /// ONE two-surface parity contract with the point-domain
255 /// [`crate::boundary::Boundary`] peer methods.
256 #[must_use]
257 pub fn has_postcondition_kind(&self, kind: ConditionKind) -> bool {
258 self.postconditions.has_kind(kind)
259 }
260
261 /// Returns the first [`Condition`] in
262 /// `preconditions ∪ postconditions` carrying the given
263 /// [`ConditionKind`], searching preconditions first — the peer of
264 /// [`crate::boundary::Boundary::find_condition_kind`] on the
265 /// [`EphemeralSpec`] sugar surface.
266 ///
267 /// # Semantics — byte-identical to [`Boundary::find_condition_kind`]
268 ///
269 /// Walks `self.preconditions` first, then `self.postconditions`:
270 /// a kind authored on BOTH sides returns the precondition-side
271 /// [`Condition`]. Composition law:
272 /// `find_condition_kind(K) == find_precondition_kind(K).or_else(||
273 /// find_postcondition_kind(K))`, pinned as a first-class typed
274 /// invariant. Both halves compose through the SAME slice-level
275 /// substrate primitive [`crate::boundary::ConditionSliceExt::find_kind`]
276 /// that [`Boundary::find_condition_kind`] walks — so a regression
277 /// at the per-slice walk fails at that primitive's tests rather
278 /// than as silent drift at either struct-level widened caller.
279 ///
280 /// # Sibling to [`Self::has_condition_kind`]
281 ///
282 /// Same axis, one refinement wider: `has_condition_kind` collapses
283 /// the return to a `bool` (`find_condition_kind(k).is_some()`);
284 /// this method returns the matching `&Condition` so consumers can
285 /// read [`Condition::params`] at the presence-probe callsite
286 /// without re-walking the two condition vectors. Pinned by the
287 /// composition law
288 /// `has_condition_kind(K) == find_condition_kind(K).is_some()`.
289 ///
290 /// # Compounding
291 ///
292 /// A future diagnostic consumer on the ephemeral surface (an
293 /// operator-facing "closed-loop-auth matched with
294 /// params.probeImage=X" message emitted by the ephemeral require-
295 /// tag classifier, a coherence check on the ephemeral surface that
296 /// verifies "every `ClosedLoopAuth` postcondition carries a non-
297 /// empty `probeImage`", an editor completion listing params-keys
298 /// per present ephemeral kind) reaches for the matching
299 /// [`Condition`] through this ONE method rather than re-walking
300 /// the two vectors at the callsite. Byte-for-byte peer of the
301 /// point-domain widened triad on [`Boundary`], so the two-surface
302 /// parity contract now covers both refinements (bool via has,
303 /// `&Condition` via find) on the condition axis.
304 ///
305 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
306 /// preserves proofs — the widened union body composes the SAME
307 /// slice-level substrate primitive on both this ephemeral surface
308 /// and the point-domain [`Boundary`] surface). THEORY.md §VI.1
309 /// (generation over composition — a future [`ConditionKind`]
310 /// variant added to `ALL` reaches both surfaces' widened triads
311 /// mechanically through the SAME closed-set walk).
312 #[must_use]
313 pub fn find_condition_kind(&self, kind: ConditionKind) -> Option<&Condition> {
314 self.find_precondition_kind(kind)
315 .or_else(|| self.find_postcondition_kind(kind))
316 }
317
318 /// Returns the first [`Condition`] in [`Self::preconditions`]
319 /// carrying the given [`ConditionKind`], or `None` — the
320 /// precondition-side arm of the (precondition, postcondition,
321 /// condition-union) widened triad on [`EphemeralSpec`]. Thin typed
322 /// delegate to [`crate::boundary::ConditionSliceExt::find_kind`]
323 /// over [`Self::preconditions`].
324 ///
325 /// Peer of [`crate::boundary::Boundary::find_precondition_kind`]
326 /// on the point-domain surface — both peers compose against the
327 /// SAME slice-level substrate primitive so a regression at the
328 /// per-slice walk fails at that primitive's tests rather than as
329 /// silent drift at either struct-level widened half-slice arm.
330 /// Byte-identical semantics to [`Self::has_precondition_kind`]
331 /// with a widened `Option<&Condition>` return rather than a
332 /// `bool`.
333 #[must_use]
334 pub fn find_precondition_kind(&self, kind: ConditionKind) -> Option<&Condition> {
335 self.preconditions.find_kind(kind)
336 }
337
338 /// Returns the first [`Condition`] in [`Self::postconditions`]
339 /// carrying the given [`ConditionKind`], or `None` — the
340 /// postcondition-side arm of the (precondition, postcondition,
341 /// condition-union) widened triad on [`EphemeralSpec`]. Thin typed
342 /// delegate to [`crate::boundary::ConditionSliceExt::find_kind`]
343 /// over [`Self::postconditions`].
344 ///
345 /// Peer of [`crate::boundary::Boundary::find_postcondition_kind`]
346 /// on the point-domain surface. See [`Self::find_precondition_kind`]
347 /// for the full rationale — the two methods share ONE lift
348 /// motivation, ONE fail-before-pass-after composition-law pin, and
349 /// ONE two-surface parity contract with the point-domain
350 /// [`crate::boundary::Boundary`] widened peer methods.
351 #[must_use]
352 pub fn find_postcondition_kind(&self, kind: ConditionKind) -> Option<&Condition> {
353 self.postconditions.find_kind(kind)
354 }
355
356 /// Returns an iterator over every [`Condition`] in
357 /// `preconditions ∪ postconditions` carrying the given
358 /// [`ConditionKind`], walking preconditions first — the peer of
359 /// [`crate::boundary::Boundary::iter_condition_kind`] on the
360 /// [`EphemeralSpec`] sugar surface.
361 ///
362 /// # Semantics — byte-identical to [`Boundary::iter_condition_kind`]
363 ///
364 /// Chains [`Self::iter_precondition_kind`] with
365 /// [`Self::iter_postcondition_kind`] via [`Iterator::chain`]:
366 /// yields every precondition-side match in slice order, then
367 /// every postcondition-side match in slice order. Composition
368 /// law:
369 /// `find_condition_kind(K) == iter_condition_kind(K).next()`,
370 /// pinned as a first-class typed invariant. Both halves compose
371 /// through the SAME slice-level substrate primitive
372 /// [`crate::boundary::ConditionSliceExt::iter_kind`] that
373 /// [`Boundary::iter_condition_kind`] chains — so a regression at
374 /// the per-slice walk fails at that primitive's tests rather than
375 /// as silent drift at either struct-level widened caller.
376 ///
377 /// # Sibling to [`Self::find_condition_kind`]
378 ///
379 /// Same axis, one refinement wider: `find_condition_kind`
380 /// collapses the return to the FIRST match; this method yields
381 /// every match across both sides. Byte-for-byte peer of the
382 /// point-domain widened triad on [`Boundary`], so the two-surface
383 /// parity contract now covers three refinements (bool via has,
384 /// `&Condition` via find, `impl Iterator<Item = &Condition>` via
385 /// iter) on the condition axis.
386 ///
387 /// # Compounding
388 ///
389 /// A future ephemeral-surface coherence check that enforces
390 /// "each [`ConditionKind`] appears at most once across
391 /// preconditions ∪ postconditions" reads
392 /// `spec.iter_condition_kind(k).nth(1).is_none()` at ONE call
393 /// site. A future ephemeral require-tag classifier arm that
394 /// counts matches (a hypothetical `condition-count-<kind>` prefix
395 /// family that surfaces multiplicity to the operator) reaches
396 /// this ONE method through `spec.iter_condition_kind(k).count()`.
397 ///
398 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
399 /// preserves proofs — the widened stream body composes the SAME
400 /// slice-level substrate primitive on both this ephemeral surface
401 /// and the point-domain [`Boundary`] surface). THEORY.md §VI.1
402 /// (generation over composition — a future [`ConditionKind`]
403 /// variant added to `ALL` reaches both surfaces' iterator triads
404 /// mechanically through the SAME closed-set walk).
405 pub fn iter_condition_kind(
406 &self,
407 kind: ConditionKind,
408 ) -> std::iter::Chain<crate::boundary::KindMatches<'_>, crate::boundary::KindMatches<'_>> {
409 self.iter_precondition_kind(kind)
410 .chain(self.iter_postcondition_kind(kind))
411 }
412
413 /// Returns an iterator over every [`Condition`] in
414 /// [`Self::preconditions`] carrying the given [`ConditionKind`]
415 /// — the precondition-side arm of the (precondition,
416 /// postcondition, condition-union) iterator triad on
417 /// [`EphemeralSpec`]. Thin typed delegate to
418 /// [`crate::boundary::ConditionSliceExt::iter_kind`] over
419 /// [`Self::preconditions`].
420 ///
421 /// Peer of [`crate::boundary::Boundary::iter_precondition_kind`]
422 /// on the point-domain surface — both peers compose against the
423 /// SAME slice-level substrate primitive so a regression at the
424 /// per-slice walk fails at that primitive's tests rather than as
425 /// silent drift at either struct-level widened half-slice arm.
426 /// Byte-identical semantics to [`Self::find_precondition_kind`]
427 /// with a widened stream return rather than only the first match.
428 pub fn iter_precondition_kind(&self, kind: ConditionKind) -> crate::boundary::KindMatches<'_> {
429 self.preconditions.iter_kind(kind)
430 }
431
432 /// Returns an iterator over every [`Condition`] in
433 /// [`Self::postconditions`] carrying the given [`ConditionKind`]
434 /// — the postcondition-side arm of the (precondition,
435 /// postcondition, condition-union) iterator triad on
436 /// [`EphemeralSpec`]. Thin typed delegate to
437 /// [`crate::boundary::ConditionSliceExt::iter_kind`] over
438 /// [`Self::postconditions`].
439 ///
440 /// Peer of [`crate::boundary::Boundary::iter_postcondition_kind`]
441 /// on the point-domain surface. See
442 /// [`Self::iter_precondition_kind`] for the full rationale — the
443 /// two methods share ONE lift motivation, ONE fail-before-
444 /// pass-after composition-law pin, and ONE two-surface parity
445 /// contract with the point-domain [`crate::boundary::Boundary`]
446 /// widened peer methods.
447 pub fn iter_postcondition_kind(&self, kind: ConditionKind) -> crate::boundary::KindMatches<'_> {
448 self.postconditions.iter_kind(kind)
449 }
450
451 /// Number of [`Condition`]s in `preconditions ∪ postconditions`
452 /// carrying the given [`ConditionKind`] — the peer of
453 /// [`crate::boundary::Boundary::count_condition_kind`] on the
454 /// [`EphemeralSpec`] sugar surface.
455 ///
456 /// # Semantics — byte-identical to [`Boundary::count_condition_kind`]
457 ///
458 /// Composed as
459 /// `count_precondition_kind(k) + count_postcondition_kind(k)` —
460 /// the SUM-composed arm on the presence-probe algebra (distinct
461 /// from `has_condition_kind`'s `||`, `find_condition_kind`'s
462 /// `or_else`, and `iter_condition_kind`'s `Chain`). Composition
463 /// law `count_condition_kind(K) == iter_condition_kind(K).count()`
464 /// pinned as a first-class typed invariant. Both halves compose
465 /// through the SAME slice-level substrate primitive
466 /// [`crate::boundary::ConditionSliceExt::count_kind`] that
467 /// [`Boundary::count_condition_kind`] sums — so a regression at
468 /// the per-slice count fails at that primitive's tests rather
469 /// than as silent drift at either struct-level widened caller.
470 ///
471 /// # Sibling to [`Self::iter_condition_kind`]
472 ///
473 /// Same axis, one refinement lower on the cardinality projection:
474 /// `iter_condition_kind` yields the whole match stream; this
475 /// method collapses that stream to its cardinality. Byte-for-byte
476 /// peer of the point-domain count triad on [`Boundary`], so the
477 /// two-surface parity contract now covers four refinements (bool
478 /// via has, `&Condition` via find, `impl Iterator<Item =
479 /// &Condition>` via iter, `usize` via count) on the condition
480 /// axis.
481 ///
482 /// # Compounding
483 ///
484 /// A future ephemeral-surface coherence check that enforces
485 /// "each [`ConditionKind`] appears at most once across
486 /// preconditions ∪ postconditions" reads
487 /// `spec.count_condition_kind(k) <= 1` at ONE call site. A future
488 /// ephemeral require-tag classifier arm that surfaces multiplicity
489 /// to the operator (a hypothetical `condition-count-<kind>` prefix
490 /// family that publishes the raw cardinality on the ephemeral
491 /// surface, an operator-facing "3 ClosedLoopAuth postconditions
492 /// matched" message) reaches this ONE method rather than restating
493 /// the `.iter_condition_kind(k).count()` chain body at the
494 /// callsite.
495 ///
496 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
497 /// preserves proofs — the scalar cardinality body composes the
498 /// SAME slice-level substrate primitive on both this ephemeral
499 /// surface and the point-domain [`Boundary`] surface). THEORY.md
500 /// §VI.1 (generation over composition — a future
501 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
502 /// count triads mechanically through the SAME closed-set walk).
503 #[must_use]
504 pub fn count_condition_kind(&self, kind: ConditionKind) -> usize {
505 self.count_precondition_kind(kind) + self.count_postcondition_kind(kind)
506 }
507
508 /// Number of [`Condition`]s in [`Self::preconditions`] carrying
509 /// the given [`ConditionKind`] — the precondition-side arm of the
510 /// (precondition, postcondition, condition-union) count triad on
511 /// [`EphemeralSpec`]. Thin typed delegate to
512 /// [`crate::boundary::ConditionSliceExt::count_kind`] over
513 /// [`Self::preconditions`].
514 ///
515 /// Peer of [`crate::boundary::Boundary::count_precondition_kind`]
516 /// on the point-domain surface — both peers compose against the
517 /// SAME slice-level substrate primitive so a regression at the
518 /// per-slice count fails at that primitive's tests rather than as
519 /// silent drift at either struct-level count arm.
520 #[must_use]
521 pub fn count_precondition_kind(&self, kind: ConditionKind) -> usize {
522 self.preconditions.count_kind(kind)
523 }
524
525 /// Number of [`Condition`]s in [`Self::postconditions`] carrying
526 /// the given [`ConditionKind`] — the postcondition-side arm of
527 /// the (precondition, postcondition, condition-union) count triad
528 /// on [`EphemeralSpec`]. Thin typed delegate to
529 /// [`crate::boundary::ConditionSliceExt::count_kind`] over
530 /// [`Self::postconditions`].
531 ///
532 /// Peer of [`crate::boundary::Boundary::count_postcondition_kind`]
533 /// on the point-domain surface. See
534 /// [`Self::count_precondition_kind`] for the full rationale — the
535 /// two methods share ONE lift motivation, ONE fail-before-
536 /// pass-after composition-law pin, and ONE two-surface parity
537 /// contract with the point-domain [`crate::boundary::Boundary`]
538 /// count peer methods.
539 #[must_use]
540 pub fn count_postcondition_kind(&self, kind: ConditionKind) -> usize {
541 self.postconditions.count_kind(kind)
542 }
543
544 /// The set of [`ConditionKind`] variants appearing at least once in
545 /// `preconditions ∪ postconditions`, projected in
546 /// [`ConditionKind::ALL`] order — the peer of
547 /// [`crate::boundary::Boundary::distinct_condition_kinds`] on the
548 /// [`EphemeralSpec`] sugar surface.
549 ///
550 /// # Semantics — byte-identical to [`crate::boundary::Boundary::distinct_condition_kinds`]
551 ///
552 /// Composed as `ConditionKind::ALL.into_iter().filter(|k|
553 /// self.has_condition_kind(*k)).collect()` — the ONE closed-set-
554 /// inversion arm on the presence-probe algebra (distinct in axis
555 /// from the four point-probe arms `has_condition_kind` /
556 /// `find_condition_kind` / `iter_condition_kind` /
557 /// `count_condition_kind` which fix a [`ConditionKind`] and vary
558 /// the return type). Equivalent to the set-union of
559 /// [`Self::distinct_precondition_kinds`] and
560 /// [`Self::distinct_postcondition_kinds`] projected in canonical
561 /// [`ConditionKind::ALL`] order.
562 ///
563 /// # Peer on the point surface — [`crate::boundary::Boundary::distinct_condition_kinds`]
564 ///
565 /// Same signature `(&Self) -> Vec<ConditionKind>`, same closed-set-
566 /// inversion body, on the point-domain [`crate::boundary::Boundary`]
567 /// nested-slot carrier. Both methods compose against the SAME
568 /// slice-level substrate primitive
569 /// [`crate::boundary::ConditionSliceExt::distinct_kinds`] via the
570 /// two-slice union composed through [`Self::has_condition_kind`] —
571 /// a regression at the per-slice walk fails at that primitive's
572 /// tests rather than as silent drift at either struct-level union
573 /// caller.
574 ///
575 /// # Sibling to the four point-probe refinements
576 ///
577 /// FIFTH refinement on the ephemeral-surface presence-probe algebra,
578 /// distinct in axis from the other four. The composition law
579 /// `distinct_condition_kinds().contains(&k) == has_condition_kind(k)`
580 /// for every `k ∈ ConditionKind::ALL` binds the closed-set-inversion
581 /// probe to the point probe at the (precondition, postcondition,
582 /// condition-union) triad. The two-surface parity contract now
583 /// covers FIVE refinements (bool / `&Condition` / `impl Iterator` /
584 /// `usize` / `Vec<ConditionKind>` closed-set-inversion) on the
585 /// condition axis, byte-for-byte peer of the point-domain triad on
586 /// [`crate::boundary::Boundary`].
587 ///
588 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
589 /// proofs — the closed-set-inversion aggregate composes the SAME
590 /// slice-level substrate primitive on both this ephemeral surface
591 /// and the point-domain [`crate::boundary::Boundary`] surface).
592 /// THEORY.md §VI.1 (generation over composition — a future
593 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
594 /// distinct-set triads mechanically through the SAME closed-set
595 /// walk).
596 #[must_use]
597 pub fn distinct_condition_kinds(&self) -> Vec<ConditionKind> {
598 ConditionKind::ALL
599 .into_iter()
600 .filter(|k| self.has_condition_kind(*k))
601 .collect()
602 }
603
604 /// The set of [`ConditionKind`] variants appearing at least once in
605 /// [`Self::preconditions`], projected in [`ConditionKind::ALL`]
606 /// order — the precondition-side arm of the (precondition,
607 /// postcondition, condition-union) distinct-set triad on
608 /// [`EphemeralSpec`]. Thin typed delegate to
609 /// [`crate::boundary::ConditionSliceExt::distinct_kinds`] over
610 /// [`Self::preconditions`].
611 ///
612 /// Peer of [`crate::boundary::Boundary::distinct_precondition_kinds`]
613 /// on the point-domain surface — both peers compose against the
614 /// SAME slice-level substrate primitive so a regression at the
615 /// per-slice closed-set walk fails at that primitive's tests
616 /// rather than as silent drift at either struct-level arm.
617 #[must_use]
618 pub fn distinct_precondition_kinds(&self) -> Vec<ConditionKind> {
619 self.preconditions.distinct_kinds()
620 }
621
622 /// The set of [`ConditionKind`] variants appearing at least once in
623 /// [`Self::postconditions`], projected in [`ConditionKind::ALL`]
624 /// order — the postcondition-side arm of the (precondition,
625 /// postcondition, condition-union) distinct-set triad on
626 /// [`EphemeralSpec`]. Thin typed delegate to
627 /// [`crate::boundary::ConditionSliceExt::distinct_kinds`] over
628 /// [`Self::postconditions`].
629 ///
630 /// Peer of [`crate::boundary::Boundary::distinct_postcondition_kinds`]
631 /// on the point-domain surface. See
632 /// [`Self::distinct_precondition_kinds`] for the full rationale —
633 /// the two methods share ONE lift motivation, ONE fail-before-
634 /// pass-after composition-law pin, and ONE two-surface parity
635 /// contract with the point-domain
636 /// [`crate::boundary::Boundary`] distinct-set peer methods.
637 #[must_use]
638 pub fn distinct_postcondition_kinds(&self) -> Vec<ConditionKind> {
639 self.postconditions.distinct_kinds()
640 }
641
642 /// Zero-allocation iterator peer of [`Self::distinct_condition_kinds`]
643 /// — the condition-union arm of the (precondition, postcondition,
644 /// condition-union) closed-set-inversion iterator triad on
645 /// [`EphemeralSpec`]. Byte-identical to
646 /// [`crate::boundary::Boundary::iter_distinct_condition_kinds`] on the
647 /// point-domain surface. Walks [`ConditionKind::ALL`] in canonical
648 /// order and yields every [`ConditionKind`] appearing at least once in
649 /// `preconditions ∪ postconditions`, WITHOUT materializing an
650 /// intermediate `Vec<ConditionKind>`.
651 pub fn iter_distinct_condition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
652 ConditionKind::ALL
653 .iter()
654 .copied()
655 .filter(|&k| self.has_condition_kind(k))
656 }
657
658 /// Zero-allocation iterator peer of
659 /// [`Self::distinct_precondition_kinds`] — the precondition-side arm
660 /// of the (precondition, postcondition, condition-union) closed-set-
661 /// inversion iterator triad on [`EphemeralSpec`]. Thin typed delegate
662 /// to [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
663 /// [`Self::preconditions`].
664 pub fn iter_distinct_precondition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
665 self.preconditions.iter_distinct_kinds()
666 }
667
668 /// Zero-allocation iterator peer of
669 /// [`Self::distinct_postcondition_kinds`] — the postcondition-side
670 /// arm of the (precondition, postcondition, condition-union) closed-
671 /// set-inversion iterator triad on [`EphemeralSpec`]. Thin typed
672 /// delegate to
673 /// [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
674 /// [`Self::postconditions`].
675 pub fn iter_distinct_postcondition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
676 self.postconditions.iter_distinct_kinds()
677 }
678
679 /// Scalar cardinality of the [`ConditionKind`] set appearing at
680 /// least once in `preconditions ∪ postconditions` — the peer of
681 /// [`crate::boundary::Boundary::distinct_condition_kind_count`] on
682 /// the [`EphemeralSpec`] sugar surface.
683 ///
684 /// # Composed body — byte-identical to
685 /// [`crate::boundary::Boundary::distinct_condition_kind_count`]
686 ///
687 /// `ConditionKind::ALL.iter().filter(|k|
688 /// self.has_condition_kind(**k)).count()` — the scalar cardinality
689 /// projection of [`Self::distinct_condition_kinds`] onto its
690 /// `.len()`, without materializing the intermediate
691 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
692 /// point-domain [`crate::boundary::Boundary`] surface — both
693 /// compose against the SAME slice-level substrate primitive
694 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`] via
695 /// the two-slice union composed through [`Self::has_condition_kind`]
696 /// so a regression at the per-slice closed-set walk fails at that
697 /// primitive's tests rather than as silent drift at either
698 /// struct-level scalar-cardinality caller.
699 ///
700 /// # Sibling to [`Self::distinct_condition_kinds`]
701 ///
702 /// Scalar projection of the closed-set-inversion widened primitive
703 /// on the ephemeral-union surface — where `distinct_condition_kinds`
704 /// returns the SET, `distinct_condition_kind_count` collapses it to
705 /// its cardinality. The two-surface parity contract now covers SIX
706 /// refinements (bool / `&Condition` / `impl Iterator` / `usize` /
707 /// `Vec<ConditionKind>` closed-set-inversion / `usize` scalar
708 /// cardinality of the closed-set-inversion) on the condition axis,
709 /// byte-for-byte peer of the point-domain triad on
710 /// [`crate::boundary::Boundary`].
711 ///
712 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
713 /// proofs — the scalar cardinality composes the SAME closed-set
714 /// walk on both this ephemeral surface and the point-domain
715 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
716 /// (generation over composition — a future [`ConditionKind`] variant
717 /// added to `ALL` reaches both surfaces' distinct-kind-count triads
718 /// mechanically through the SAME closed-set walk).
719 #[must_use]
720 pub fn distinct_condition_kind_count(&self) -> usize {
721 ConditionKind::ALL
722 .iter()
723 .filter(|k| self.has_condition_kind(**k))
724 .count()
725 }
726
727 /// Scalar cardinality of the [`ConditionKind`] set appearing at
728 /// least once in [`Self::preconditions`] — the precondition-side
729 /// arm of the (precondition, postcondition, condition-union)
730 /// distinct-kind-count triad on [`EphemeralSpec`]. Thin typed
731 /// delegate to
732 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
733 /// over [`Self::preconditions`].
734 ///
735 /// Peer of
736 /// [`crate::boundary::Boundary::distinct_precondition_kind_count`]
737 /// on the point-domain surface — both peers compose against the
738 /// SAME slice-level substrate primitive so a regression at the
739 /// per-slice closed-set walk fails at that primitive's tests rather
740 /// than as silent drift at either struct-level arm.
741 #[must_use]
742 pub fn distinct_precondition_kind_count(&self) -> usize {
743 self.preconditions.distinct_kind_count()
744 }
745
746 /// Scalar cardinality of the [`ConditionKind`] set appearing at
747 /// least once in [`Self::postconditions`] — the postcondition-side
748 /// arm of the (precondition, postcondition, condition-union)
749 /// distinct-kind-count triad on [`EphemeralSpec`]. Thin typed
750 /// delegate to
751 /// [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
752 /// over [`Self::postconditions`].
753 ///
754 /// Peer of
755 /// [`crate::boundary::Boundary::distinct_postcondition_kind_count`]
756 /// on the point-domain surface. See
757 /// [`Self::distinct_precondition_kind_count`] for the full rationale
758 /// — the two methods share ONE lift motivation, ONE fail-before-
759 /// pass-after composition-law pin, and ONE two-surface parity
760 /// contract with the point-domain
761 /// [`crate::boundary::Boundary`] distinct-kind-count peer methods.
762 #[must_use]
763 pub fn distinct_postcondition_kind_count(&self) -> usize {
764 self.postconditions.distinct_kind_count()
765 }
766
767 /// The set of [`ConditionKind`] variants that do NOT appear in
768 /// `preconditions ∪ postconditions`, projected in
769 /// [`ConditionKind::ALL`] order — the closed-set-inversion
770 /// COMPLEMENT of [`Self::distinct_condition_kinds`] on the
771 /// (precondition, postcondition, condition-union) missing-set triad.
772 /// Byte-identical peer of
773 /// [`crate::boundary::Boundary::missing_condition_kinds`] on the
774 /// ephemeral sugar surface.
775 ///
776 /// # Composed body — byte-identical to
777 /// [`crate::boundary::Boundary::missing_condition_kinds`]
778 ///
779 /// `ConditionKind::ALL.into_iter().filter(|k|
780 /// !self.has_condition_kind(*k)).collect()` — a thin projection
781 /// over the closed set composed against the two-slice union
782 /// primitive [`Self::has_condition_kind`] under a negated
783 /// predicate. Equivalent to the SET-INTERSECTION of
784 /// [`Self::missing_precondition_kinds`] and
785 /// [`Self::missing_postcondition_kinds`] projected in canonical
786 /// [`ConditionKind::ALL`] order (the union-composition law pinned
787 /// by [`crate::assert_surface_union_composition_laws`]).
788 ///
789 /// # Peer on the point surface — [`crate::boundary::Boundary::missing_condition_kinds`]
790 ///
791 /// Same signature `(&Self) -> Vec<ConditionKind>`, same closed-set-
792 /// complement body, on the point-domain [`crate::boundary::Boundary`]
793 /// nested-slot carrier. Both methods compose against the SAME
794 /// slice-level substrate primitive
795 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] via the
796 /// two-slice union composed through [`Self::has_condition_kind`] —
797 /// a regression at the per-slice walk fails at that primitive's
798 /// tests rather than as silent drift at either struct-level
799 /// complement caller.
800 ///
801 /// # Sibling to [`Self::distinct_condition_kinds`]
802 ///
803 /// SIXTH refinement on the ephemeral-surface presence-probe algebra,
804 /// on the SAME closed-set-inversion axis as `distinct_condition_kinds`
805 /// but under a NEGATED point-probe. The two-surface parity contract
806 /// now covers SEVEN refinements (bool / `&Condition` /
807 /// `impl Iterator` / `usize` / `Vec<ConditionKind>` closed-set-
808 /// inversion / `usize` scalar cardinality of the closed-set-
809 /// inversion / `Vec<ConditionKind>` closed-set-complement) on the
810 /// condition axis, byte-for-byte peer of the point-domain triad on
811 /// [`crate::boundary::Boundary`].
812 ///
813 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
814 /// preserves proofs — the closed-set complement composes the SAME
815 /// closed-set walk on both this ephemeral surface and the point-
816 /// domain [`crate::boundary::Boundary`] surface).
817 /// THEORY.md §VI.1 (generation over composition — a future
818 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
819 /// missing-set triads mechanically through the SAME closed-set walk).
820 #[must_use]
821 pub fn missing_condition_kinds(&self) -> Vec<ConditionKind> {
822 ConditionKind::ALL
823 .into_iter()
824 .filter(|k| !self.has_condition_kind(*k))
825 .collect()
826 }
827
828 /// The set of [`ConditionKind`] variants that do NOT appear in
829 /// [`Self::preconditions`], projected in [`ConditionKind::ALL`]
830 /// order — the precondition-side arm of the (precondition,
831 /// postcondition, condition-union) missing-set triad on
832 /// [`EphemeralSpec`]. Thin typed delegate to
833 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over
834 /// [`Self::preconditions`].
835 ///
836 /// Peer of [`crate::boundary::Boundary::missing_precondition_kinds`]
837 /// on the point-domain surface — both peers compose against the
838 /// SAME slice-level substrate primitive so a regression at the
839 /// per-slice closed-set walk fails at that primitive's tests
840 /// rather than as silent drift at either struct-level arm.
841 #[must_use]
842 pub fn missing_precondition_kinds(&self) -> Vec<ConditionKind> {
843 self.preconditions.missing_kinds()
844 }
845
846 /// The set of [`ConditionKind`] variants that do NOT appear in
847 /// [`Self::postconditions`], projected in [`ConditionKind::ALL`]
848 /// order — the postcondition-side arm of the (precondition,
849 /// postcondition, condition-union) missing-set triad on
850 /// [`EphemeralSpec`]. Thin typed delegate to
851 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over
852 /// [`Self::postconditions`].
853 ///
854 /// Peer of [`crate::boundary::Boundary::missing_postcondition_kinds`]
855 /// on the point-domain surface. See
856 /// [`Self::missing_precondition_kinds`] for the full rationale —
857 /// the two methods share ONE lift motivation, ONE fail-before-
858 /// pass-after composition-law pin, and ONE two-surface parity
859 /// contract with the point-domain
860 /// [`crate::boundary::Boundary`] missing-set peer methods.
861 #[must_use]
862 pub fn missing_postcondition_kinds(&self) -> Vec<ConditionKind> {
863 self.postconditions.missing_kinds()
864 }
865
866 /// Zero-allocation iterator peer of [`Self::missing_condition_kinds`]
867 /// — the condition-union arm of the (precondition, postcondition,
868 /// condition-union) closed-set-complement iterator triad on
869 /// [`EphemeralSpec`]. Byte-identical to
870 /// [`crate::boundary::Boundary::iter_missing_condition_kinds`] on the
871 /// point-domain surface. Walks [`ConditionKind::ALL`] in canonical
872 /// order and yields every [`ConditionKind`] that does NOT appear in
873 /// `preconditions ∪ postconditions`, WITHOUT materializing an
874 /// intermediate `Vec<ConditionKind>`.
875 pub fn iter_missing_condition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
876 ConditionKind::ALL
877 .iter()
878 .copied()
879 .filter(|&k| !self.has_condition_kind(k))
880 }
881
882 /// Zero-allocation iterator peer of
883 /// [`Self::missing_precondition_kinds`] — the precondition-side arm
884 /// of the (precondition, postcondition, condition-union) closed-set-
885 /// complement iterator triad on [`EphemeralSpec`]. Thin typed delegate
886 /// to [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
887 /// [`Self::preconditions`].
888 pub fn iter_missing_precondition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
889 self.preconditions.iter_missing_kinds()
890 }
891
892 /// Zero-allocation iterator peer of
893 /// [`Self::missing_postcondition_kinds`] — the postcondition-side arm
894 /// of the (precondition, postcondition, condition-union) closed-set-
895 /// complement iterator triad on [`EphemeralSpec`]. Thin typed delegate
896 /// to [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
897 /// [`Self::postconditions`].
898 pub fn iter_missing_postcondition_kinds(&self) -> impl Iterator<Item = ConditionKind> + '_ {
899 self.postconditions.iter_missing_kinds()
900 }
901
902 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
903 /// `preconditions ∪ postconditions` — the peer of
904 /// [`crate::boundary::Boundary::missing_condition_kind_count`] on
905 /// the [`EphemeralSpec`] sugar surface.
906 ///
907 /// # Composed body — byte-identical to
908 /// [`crate::boundary::Boundary::missing_condition_kind_count`]
909 ///
910 /// `ConditionKind::ALL.iter().filter(|k|
911 /// !self.has_condition_kind(**k)).count()` — the scalar cardinality
912 /// projection of [`Self::missing_condition_kinds`] onto its
913 /// `.len()`, without materializing the intermediate
914 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
915 /// point-domain [`crate::boundary::Boundary`] surface — both
916 /// compose against the SAME slice-level substrate primitive
917 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] via
918 /// the two-slice union composed through [`Self::has_condition_kind`]
919 /// so a regression at the per-slice negated closed-set walk fails
920 /// at that primitive's tests rather than as silent drift at either
921 /// struct-level scalar-cardinality caller.
922 ///
923 /// # Sibling to [`Self::missing_condition_kinds`]
924 ///
925 /// Scalar projection of the closed-set-complement widened primitive
926 /// on the ephemeral-union surface — where `missing_condition_kinds`
927 /// returns the SET, `missing_condition_kind_count` collapses it to
928 /// its cardinality. The two-surface parity contract now covers
929 /// EIGHT refinements (bool / `&Condition` / `impl Iterator` /
930 /// `usize` / `Vec<ConditionKind>` closed-set-inversion / `usize`
931 /// scalar cardinality of the closed-set-inversion /
932 /// `Vec<ConditionKind>` closed-set-complement / `usize` scalar
933 /// cardinality of the closed-set-complement) on the condition axis,
934 /// byte-for-byte peer of the point-domain triad on
935 /// [`crate::boundary::Boundary`].
936 ///
937 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
938 /// proofs — the scalar cardinality composes the SAME closed-set
939 /// walk under negation on both this ephemeral surface and the
940 /// point-domain [`crate::boundary::Boundary`] surface).
941 /// THEORY.md §VI.1 (generation over composition — a future
942 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
943 /// missing-kind-count triads mechanically through the SAME
944 /// closed-set walk).
945 #[must_use]
946 pub fn missing_condition_kind_count(&self) -> usize {
947 ConditionKind::ALL
948 .iter()
949 .filter(|k| !self.has_condition_kind(**k))
950 .count()
951 }
952
953 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
954 /// [`Self::preconditions`] — the precondition-side arm of the
955 /// (precondition, postcondition, condition-union) missing-kind-count
956 /// triad on [`EphemeralSpec`]. Thin typed delegate to
957 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
958 /// [`Self::preconditions`].
959 ///
960 /// Peer of
961 /// [`crate::boundary::Boundary::missing_precondition_kind_count`]
962 /// on the point-domain surface — both peers compose against the
963 /// SAME slice-level substrate primitive so a regression at the
964 /// per-slice negated closed-set walk fails at that primitive's tests
965 /// rather than as silent drift at either struct-level arm.
966 #[must_use]
967 pub fn missing_precondition_kind_count(&self) -> usize {
968 self.preconditions.missing_kind_count()
969 }
970
971 /// Scalar cardinality of the [`ConditionKind`] set NOT appearing in
972 /// [`Self::postconditions`] — the postcondition-side arm of the
973 /// (precondition, postcondition, condition-union) missing-kind-count
974 /// triad on [`EphemeralSpec`]. Thin typed delegate to
975 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
976 /// [`Self::postconditions`].
977 ///
978 /// Peer of
979 /// [`crate::boundary::Boundary::missing_postcondition_kind_count`]
980 /// on the point-domain surface. See
981 /// [`Self::missing_precondition_kind_count`] for the full rationale
982 /// — the two methods share ONE lift motivation, ONE fail-before-
983 /// pass-after composition-law pin, and ONE two-surface parity
984 /// contract with the point-domain
985 /// [`crate::boundary::Boundary`] missing-kind-count peer methods.
986 #[must_use]
987 pub fn missing_postcondition_kind_count(&self) -> usize {
988 self.postconditions.missing_kind_count()
989 }
990
991 /// Earliest [`ConditionKind::ALL`] entry present in
992 /// `preconditions ∪ postconditions`, or `None` when neither side
993 /// populates any variant — the peer of
994 /// [`crate::boundary::Boundary::first_distinct_condition_kind`]
995 /// on the [`EphemeralSpec`] sugar surface.
996 ///
997 /// # Composed body — byte-identical to
998 /// [`crate::boundary::Boundary::first_distinct_condition_kind`]
999 ///
1000 /// `ConditionKind::ALL.iter().copied().find(|k|
1001 /// self.has_condition_kind(*k))` — the earliest-element scalar
1002 /// projection of [`Self::distinct_condition_kinds`] onto its first
1003 /// entry, without materializing the intermediate
1004 /// `Vec<ConditionKind>`. Byte-identical to the peer method on the
1005 /// point-domain [`crate::boundary::Boundary`] surface — both
1006 /// compose against the SAME slice-level substrate primitive
1007 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] via
1008 /// the two-slice union composed through
1009 /// [`Self::has_condition_kind`] so a regression at the per-slice
1010 /// short-circuit walk fails at that primitive's tests rather than
1011 /// as silent drift at either struct-level earliest-element caller.
1012 ///
1013 /// # Sibling to [`Self::distinct_condition_kinds`]
1014 ///
1015 /// Third scalar projection of the closed-set-inversion widened
1016 /// primitive on the ephemeral-union surface. The two-surface
1017 /// parity contract now covers NINE refinements on the condition
1018 /// axis (bool / `&Condition` / `impl Iterator` / `usize` /
1019 /// `Vec<ConditionKind>` closed-set-inversion / `usize` scalar
1020 /// cardinality of the closed-set-inversion / `Vec<ConditionKind>`
1021 /// closed-set-complement / `usize` scalar cardinality of the
1022 /// closed-set-complement / `Option<ConditionKind>` earliest-element
1023 /// scalar of the closed-set-inversion), byte-for-byte peer of the
1024 /// point-domain triad on [`crate::boundary::Boundary`].
1025 ///
1026 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1027 /// preserves proofs — the earliest-element projection composes the
1028 /// SAME closed-set walk on both this ephemeral surface and the
1029 /// point-domain [`crate::boundary::Boundary`] surface under short-
1030 /// circuit semantics). THEORY.md §VI.1 (generation over composition
1031 /// — a future [`ConditionKind`] variant added to `ALL` reaches both
1032 /// surfaces' first-distinct-kind triads mechanically through the
1033 /// SAME closed-set walk).
1034 #[must_use]
1035 pub fn first_distinct_condition_kind(&self) -> Option<ConditionKind> {
1036 ConditionKind::ALL
1037 .iter()
1038 .copied()
1039 .find(|k| self.has_condition_kind(*k))
1040 }
1041
1042 /// Earliest [`ConditionKind::ALL`] entry present in
1043 /// [`Self::preconditions`], or `None` when preconditions carry no
1044 /// matching kind — the precondition-side arm of the (precondition,
1045 /// postcondition, condition-union) first-distinct-kind triad on
1046 /// [`EphemeralSpec`]. Thin typed delegate to
1047 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`]
1048 /// over [`Self::preconditions`].
1049 ///
1050 /// Peer of
1051 /// [`crate::boundary::Boundary::first_distinct_precondition_kind`]
1052 /// on the point-domain surface — both peers compose against the
1053 /// SAME slice-level substrate primitive so a regression at the
1054 /// per-slice short-circuit walk fails at that primitive's tests
1055 /// rather than as silent drift at either struct-level arm.
1056 #[must_use]
1057 pub fn first_distinct_precondition_kind(&self) -> Option<ConditionKind> {
1058 self.preconditions.first_distinct_kind()
1059 }
1060
1061 /// Earliest [`ConditionKind::ALL`] entry present in
1062 /// [`Self::postconditions`], or `None` when postconditions carry
1063 /// no matching kind — the postcondition-side arm of the
1064 /// (precondition, postcondition, condition-union) first-distinct-
1065 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
1066 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`]
1067 /// over [`Self::postconditions`].
1068 ///
1069 /// Peer of
1070 /// [`crate::boundary::Boundary::first_distinct_postcondition_kind`]
1071 /// on the point-domain surface. See
1072 /// [`Self::first_distinct_precondition_kind`] for the full
1073 /// rationale — the two methods share ONE lift motivation, ONE
1074 /// fail-before-pass-after composition-law pin, and ONE two-surface
1075 /// parity contract with the point-domain
1076 /// [`crate::boundary::Boundary`] first-distinct-kind peer methods.
1077 #[must_use]
1078 pub fn first_distinct_postcondition_kind(&self) -> Option<ConditionKind> {
1079 self.postconditions.first_distinct_kind()
1080 }
1081
1082 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1083 /// `preconditions ∪ postconditions`, or `None` when the union
1084 /// carries every variant — the peer of
1085 /// [`crate::boundary::Boundary::first_missing_condition_kind`]
1086 /// on the [`EphemeralSpec`] sugar surface.
1087 ///
1088 /// # Composed body — byte-identical to
1089 /// [`crate::boundary::Boundary::first_missing_condition_kind`]
1090 ///
1091 /// `ConditionKind::ALL.iter().copied().find(|k|
1092 /// !self.has_condition_kind(*k))` — the earliest-element scalar
1093 /// projection of [`Self::missing_condition_kinds`] onto its first
1094 /// entry under a NEGATED predicate. Byte-identical to the peer
1095 /// method on the point-domain [`crate::boundary::Boundary`]
1096 /// surface — both compose against the SAME slice-level substrate
1097 /// primitive [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1098 /// via the two-slice union composed through
1099 /// [`Self::has_condition_kind`] so a regression at the per-slice
1100 /// negated short-circuit walk fails at that primitive's tests
1101 /// rather than as silent drift at either struct-level earliest-
1102 /// element caller.
1103 ///
1104 /// # Sibling to [`Self::missing_condition_kinds`]
1105 ///
1106 /// Third scalar projection of the closed-set-complement widened
1107 /// primitive on the ephemeral-union surface. The two-surface
1108 /// parity contract now covers TEN refinements on the condition
1109 /// axis (the nine listed at [`Self::first_distinct_condition_kind`]
1110 /// plus `Option<ConditionKind>` earliest-element scalar of the
1111 /// closed-set-complement), byte-for-byte peer of the point-domain
1112 /// triad on [`crate::boundary::Boundary`].
1113 ///
1114 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1115 /// preserves proofs — the complement-earliest-element projection
1116 /// composes the SAME closed-set walk on both this ephemeral
1117 /// surface and the point-domain [`crate::boundary::Boundary`]
1118 /// surface under short-circuit semantics with a negated predicate).
1119 /// THEORY.md §VI.1 (generation over composition — a future
1120 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
1121 /// first-missing-kind triads mechanically through the SAME closed-
1122 /// set walk).
1123 #[must_use]
1124 pub fn first_missing_condition_kind(&self) -> Option<ConditionKind> {
1125 ConditionKind::ALL
1126 .iter()
1127 .copied()
1128 .find(|k| !self.has_condition_kind(*k))
1129 }
1130
1131 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1132 /// [`Self::preconditions`], or `None` when preconditions carry
1133 /// every variant — the precondition-side arm of the (precondition,
1134 /// postcondition, condition-union) first-missing-kind triad on
1135 /// [`EphemeralSpec`]. Thin typed delegate to
1136 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1137 /// over [`Self::preconditions`].
1138 ///
1139 /// Peer of
1140 /// [`crate::boundary::Boundary::first_missing_precondition_kind`]
1141 /// on the point-domain surface — both peers compose against the
1142 /// SAME slice-level substrate primitive so a regression at the
1143 /// per-slice negated short-circuit walk fails at that primitive's
1144 /// tests rather than as silent drift at either struct-level arm.
1145 #[must_use]
1146 pub fn first_missing_precondition_kind(&self) -> Option<ConditionKind> {
1147 self.preconditions.first_missing_kind()
1148 }
1149
1150 /// Earliest [`ConditionKind::ALL`] entry ABSENT from
1151 /// [`Self::postconditions`], or `None` when postconditions carry
1152 /// every variant — the postcondition-side arm of the (precondition,
1153 /// postcondition, condition-union) first-missing-kind triad on
1154 /// [`EphemeralSpec`]. Thin typed delegate to
1155 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`]
1156 /// over [`Self::postconditions`].
1157 ///
1158 /// Peer of
1159 /// [`crate::boundary::Boundary::first_missing_postcondition_kind`]
1160 /// on the point-domain surface. See
1161 /// [`Self::first_missing_precondition_kind`] for the full
1162 /// rationale — the two methods share ONE lift motivation, ONE
1163 /// fail-before-pass-after composition-law pin, and ONE two-surface
1164 /// parity contract with the point-domain
1165 /// [`crate::boundary::Boundary`] first-missing-kind peer methods.
1166 #[must_use]
1167 pub fn first_missing_postcondition_kind(&self) -> Option<ConditionKind> {
1168 self.postconditions.first_missing_kind()
1169 }
1170
1171 /// Latest [`ConditionKind::ALL`] entry present in
1172 /// `preconditions ∪ postconditions`, or `None` when neither side
1173 /// populates any variant — the peer of
1174 /// [`crate::boundary::Boundary::last_distinct_condition_kind`]
1175 /// on the [`EphemeralSpec`] sugar surface.
1176 ///
1177 /// # Composed body — byte-identical to
1178 /// [`crate::boundary::Boundary::last_distinct_condition_kind`]
1179 ///
1180 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
1181 /// self.has_condition_kind(*k))` — the latest-element scalar
1182 /// projection of [`Self::distinct_condition_kinds`] onto its last
1183 /// entry via a REVERSED closed-set walk, without materializing
1184 /// the intermediate `Vec<ConditionKind>`. Byte-identical to the
1185 /// peer method on the point-domain [`crate::boundary::Boundary`]
1186 /// surface — both compose against the SAME slice-level substrate
1187 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1188 /// via the two-slice union composed through
1189 /// [`Self::has_condition_kind`] so a regression at the per-slice
1190 /// REVERSED short-circuit walk fails at that primitive's tests
1191 /// rather than as silent drift at either struct-level latest-
1192 /// element caller.
1193 ///
1194 /// # Sibling to [`Self::first_distinct_condition_kind`] /
1195 /// [`Self::distinct_condition_kinds`]
1196 ///
1197 /// Time-reversed scalar peer of the earliest-element projection
1198 /// under the SAME two-slice union predicate. The two-surface
1199 /// parity contract now covers ELEVEN refinements on the condition
1200 /// axis (the nine listed at `first_distinct_condition_kind` plus
1201 /// `Option<ConditionKind>` earliest-element scalar of the closed-
1202 /// set-complement (`first_missing_*_kind`), plus this
1203 /// `Option<ConditionKind>` latest-element scalar of the closed-
1204 /// set-inversion (`last_distinct_*_kind`)). Byte-for-byte peer of
1205 /// the point-domain triad on [`crate::boundary::Boundary`].
1206 ///
1207 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1208 /// preserves proofs — the latest-element projection composes the
1209 /// SAME reversed closed-set walk on both this ephemeral surface
1210 /// and the point-domain [`crate::boundary::Boundary`] surface
1211 /// under short-circuit semantics). THEORY.md §VI.1 (generation
1212 /// over composition — a future [`ConditionKind`] variant added to
1213 /// `ALL` reaches both surfaces' last-distinct-kind triads
1214 /// mechanically through the SAME reversed closed-set walk).
1215 #[must_use]
1216 pub fn last_distinct_condition_kind(&self) -> Option<ConditionKind> {
1217 ConditionKind::ALL
1218 .iter()
1219 .rev()
1220 .copied()
1221 .find(|k| self.has_condition_kind(*k))
1222 }
1223
1224 /// Latest [`ConditionKind::ALL`] entry present in
1225 /// [`Self::preconditions`], or `None` when preconditions carry no
1226 /// matching kind — the precondition-side arm of the (precondition,
1227 /// postcondition, condition-union) last-distinct-kind triad on
1228 /// [`EphemeralSpec`]. Thin typed delegate to
1229 /// [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1230 /// over [`Self::preconditions`].
1231 ///
1232 /// Peer of
1233 /// [`crate::boundary::Boundary::last_distinct_precondition_kind`]
1234 /// on the point-domain surface — both peers compose against the
1235 /// SAME slice-level substrate primitive so a regression at the
1236 /// per-slice REVERSED short-circuit walk fails at that primitive's
1237 /// tests rather than as silent drift at either struct-level arm.
1238 #[must_use]
1239 pub fn last_distinct_precondition_kind(&self) -> Option<ConditionKind> {
1240 self.preconditions.last_distinct_kind()
1241 }
1242
1243 /// Latest [`ConditionKind::ALL`] entry present in
1244 /// [`Self::postconditions`], or `None` when postconditions carry
1245 /// no matching kind — the postcondition-side arm of the
1246 /// (precondition, postcondition, condition-union) last-distinct-
1247 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
1248 /// [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
1249 /// over [`Self::postconditions`].
1250 ///
1251 /// Peer of
1252 /// [`crate::boundary::Boundary::last_distinct_postcondition_kind`]
1253 /// on the point-domain surface. See
1254 /// [`Self::last_distinct_precondition_kind`] for the full
1255 /// rationale — the two methods share ONE lift motivation, ONE
1256 /// fail-before-pass-after composition-law pin, and ONE two-surface
1257 /// parity contract with the point-domain
1258 /// [`crate::boundary::Boundary`] last-distinct-kind peer methods.
1259 #[must_use]
1260 pub fn last_distinct_postcondition_kind(&self) -> Option<ConditionKind> {
1261 self.postconditions.last_distinct_kind()
1262 }
1263
1264 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1265 /// `preconditions ∪ postconditions`, or `None` when the union
1266 /// carries every variant — the peer of
1267 /// [`crate::boundary::Boundary::last_missing_condition_kind`]
1268 /// on the [`EphemeralSpec`] sugar surface.
1269 ///
1270 /// # Composed body — byte-identical to
1271 /// [`crate::boundary::Boundary::last_missing_condition_kind`]
1272 ///
1273 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
1274 /// !self.has_condition_kind(*k))` — the latest-element scalar
1275 /// projection of [`Self::missing_condition_kinds`] onto its last
1276 /// entry via a REVERSED closed-set walk under a NEGATED
1277 /// predicate. Byte-identical to the peer method on the point-
1278 /// domain [`crate::boundary::Boundary`] surface — both compose
1279 /// against the SAME slice-level substrate primitive
1280 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] via
1281 /// the two-slice union composed through
1282 /// [`Self::has_condition_kind`] so a regression at the per-slice
1283 /// negated REVERSED short-circuit walk fails at that primitive's
1284 /// tests rather than as silent drift at either struct-level
1285 /// latest-element caller.
1286 ///
1287 /// # Sibling to [`Self::first_missing_condition_kind`] /
1288 /// [`Self::missing_condition_kinds`]
1289 ///
1290 /// Time-reversed scalar peer of the earliest-element projection
1291 /// under the SAME negated two-slice union predicate. The two-
1292 /// surface parity contract now covers TWELVE refinements on the
1293 /// condition axis (the ten listed at `first_missing_condition_kind`
1294 /// plus `Option<ConditionKind>` latest-element scalar of the
1295 /// closed-set-inversion (`last_distinct_*_kind`), plus this
1296 /// `Option<ConditionKind>` latest-element scalar of the closed-
1297 /// set-complement). Byte-for-byte peer of the point-domain triad
1298 /// on [`crate::boundary::Boundary`].
1299 ///
1300 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1301 /// preserves proofs — the complement-latest-element projection
1302 /// composes the SAME reversed closed-set walk on both this
1303 /// ephemeral surface and the point-domain
1304 /// [`crate::boundary::Boundary`] surface under short-circuit
1305 /// semantics with a negated predicate). THEORY.md §VI.1
1306 /// (generation over composition — a future [`ConditionKind`]
1307 /// variant added to `ALL` reaches both surfaces' last-missing-kind
1308 /// triads mechanically through the SAME reversed closed-set walk).
1309 #[must_use]
1310 pub fn last_missing_condition_kind(&self) -> Option<ConditionKind> {
1311 ConditionKind::ALL
1312 .iter()
1313 .rev()
1314 .copied()
1315 .find(|k| !self.has_condition_kind(*k))
1316 }
1317
1318 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1319 /// [`Self::preconditions`], or `None` when preconditions carry
1320 /// every variant — the precondition-side arm of the (precondition,
1321 /// postcondition, condition-union) last-missing-kind triad on
1322 /// [`EphemeralSpec`]. Thin typed delegate to
1323 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`]
1324 /// over [`Self::preconditions`].
1325 ///
1326 /// Peer of
1327 /// [`crate::boundary::Boundary::last_missing_precondition_kind`]
1328 /// on the point-domain surface — both peers compose against the
1329 /// SAME slice-level substrate primitive so a regression at the
1330 /// per-slice negated REVERSED short-circuit walk fails at that
1331 /// primitive's tests rather than as silent drift at either
1332 /// struct-level arm.
1333 #[must_use]
1334 pub fn last_missing_precondition_kind(&self) -> Option<ConditionKind> {
1335 self.preconditions.last_missing_kind()
1336 }
1337
1338 /// Latest [`ConditionKind::ALL`] entry ABSENT from
1339 /// [`Self::postconditions`], or `None` when postconditions carry
1340 /// every variant — the postcondition-side arm of the
1341 /// (precondition, postcondition, condition-union) last-missing-
1342 /// kind triad on [`EphemeralSpec`]. Thin typed delegate to
1343 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`]
1344 /// over [`Self::postconditions`].
1345 ///
1346 /// Peer of
1347 /// [`crate::boundary::Boundary::last_missing_postcondition_kind`]
1348 /// on the point-domain surface. See
1349 /// [`Self::last_missing_precondition_kind`] for the full
1350 /// rationale — the two methods share ONE lift motivation, ONE
1351 /// fail-before-pass-after composition-law pin, and ONE two-surface
1352 /// parity contract with the point-domain
1353 /// [`crate::boundary::Boundary`] last-missing-kind peer methods.
1354 #[must_use]
1355 pub fn last_missing_postcondition_kind(&self) -> Option<ConditionKind> {
1356 self.postconditions.last_missing_kind()
1357 }
1358
1359 /// `true` iff `preconditions ∪ postconditions` carries every
1360 /// [`ConditionKind::ALL`] variant at least once — the peer of
1361 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on
1362 /// the [`EphemeralSpec`] sugar surface.
1363 ///
1364 /// # Composed body — byte-identical to
1365 /// [`crate::boundary::Boundary::is_condition_kind_saturated`]
1366 ///
1367 /// `ConditionKind::ALL.iter().all(|k| self.has_condition_kind(*k))`
1368 /// — the saturation-endpoint projection of
1369 /// [`Self::missing_condition_kinds`] onto its emptiness test via
1370 /// a SHORT-CIRCUITING closed-set walk under the two-slice union
1371 /// primitive [`Self::has_condition_kind`]. Byte-identical to the
1372 /// peer method on the point-domain [`crate::boundary::Boundary`]
1373 /// surface — both compose against the SAME slice-level substrate
1374 /// primitive [`crate::boundary::ConditionSliceExt::is_kind_saturated`]
1375 /// via the two-slice union so a regression at the per-slice `all`
1376 /// short-circuit fails at that primitive's tests rather than as
1377 /// silent drift at either struct-level saturation caller.
1378 ///
1379 /// # Sibling to [`Self::missing_condition_kinds`] /
1380 /// [`Self::missing_condition_kind_count`]
1381 ///
1382 /// Boolean saturation-endpoint peer of the widened and scalar
1383 /// closed-set-complement primitives on the ephemeral-union
1384 /// surface — where those primitives return the SET and its
1385 /// cardinality, `is_condition_kind_saturated` collapses the
1386 /// scalar to its zero-arm Boolean projection.
1387 ///
1388 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1389 /// preserves proofs — the saturation-endpoint projection composes
1390 /// the SAME closed-set walk on both this ephemeral surface and the
1391 /// point-domain [`crate::boundary::Boundary`] surface under
1392 /// short-circuit semantics). THEORY.md §VI.1 (generation over
1393 /// composition — a future [`ConditionKind`] variant added to `ALL`
1394 /// reaches both surfaces' saturation-predicate triads mechanically
1395 /// through the SAME closed-set walk).
1396 #[must_use]
1397 pub fn is_condition_kind_saturated(&self) -> bool {
1398 ConditionKind::ALL
1399 .iter()
1400 .all(|k| self.has_condition_kind(*k))
1401 }
1402
1403 /// `true` iff [`Self::preconditions`] carries every
1404 /// [`ConditionKind::ALL`] variant at least once — the precondition-
1405 /// side arm of the (precondition, postcondition, condition-union)
1406 /// saturation-predicate triad on [`EphemeralSpec`]. Thin typed
1407 /// delegate to
1408 /// [`crate::boundary::ConditionSliceExt::is_kind_saturated`] over
1409 /// [`Self::preconditions`].
1410 ///
1411 /// Peer of
1412 /// [`crate::boundary::Boundary::is_precondition_kind_saturated`]
1413 /// on the point-domain surface — both peers compose against the
1414 /// SAME slice-level substrate primitive so a regression at the
1415 /// per-slice `all` short-circuit fails at that primitive's tests
1416 /// rather than as silent drift at either struct-level arm.
1417 #[must_use]
1418 pub fn is_precondition_kind_saturated(&self) -> bool {
1419 self.preconditions.is_kind_saturated()
1420 }
1421
1422 /// `true` iff [`Self::postconditions`] carries every
1423 /// [`ConditionKind::ALL`] variant at least once — the postcondition-
1424 /// side arm of the (precondition, postcondition, condition-union)
1425 /// saturation-predicate triad on [`EphemeralSpec`]. Thin typed
1426 /// delegate to
1427 /// [`crate::boundary::ConditionSliceExt::is_kind_saturated`] over
1428 /// [`Self::postconditions`].
1429 ///
1430 /// Peer of
1431 /// [`crate::boundary::Boundary::is_postcondition_kind_saturated`]
1432 /// on the point-domain surface. See
1433 /// [`Self::is_precondition_kind_saturated`] for the full rationale
1434 /// — the two methods share ONE lift motivation, ONE fail-before-
1435 /// pass-after composition-law pin, and ONE two-surface parity
1436 /// contract with the point-domain
1437 /// [`crate::boundary::Boundary`] saturation-predicate peer methods.
1438 #[must_use]
1439 pub fn is_postcondition_kind_saturated(&self) -> bool {
1440 self.postconditions.is_kind_saturated()
1441 }
1442
1443 /// `true` iff `preconditions ∪ postconditions` is MISSING at least
1444 /// one [`ConditionKind::ALL`] variant — the peer of
1445 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
1446 /// the [`EphemeralSpec`] sugar surface.
1447 ///
1448 /// # Composed body — byte-identical to
1449 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`]
1450 ///
1451 /// `!self.is_condition_kind_saturated()` — the at-least-one
1452 /// halfspace projection of [`Self::missing_condition_kinds`] onto
1453 /// its non-emptiness test via a SHORT-CIRCUITING closed-set walk
1454 /// under the two-slice union primitive [`Self::has_condition_kind`]
1455 /// negated. Byte-identical to the peer method on the point-domain
1456 /// [`crate::boundary::Boundary`] surface — both compose against the
1457 /// SAME slice-level substrate primitive
1458 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`] via
1459 /// the two-slice union so a regression at the per-slice `all`
1460 /// short-circuit under negation fails at that primitive's tests
1461 /// rather than as silent drift at either struct-level at-least-
1462 /// one halfspace caller.
1463 ///
1464 /// # Sibling to [`Self::missing_condition_kinds`] /
1465 /// [`Self::missing_condition_kind_count`]
1466 ///
1467 /// Boolean at-least-one halfspace peer of the widened and scalar
1468 /// closed-set-complement primitives on the ephemeral-union
1469 /// surface — where those primitives return the SET and its
1470 /// cardinality, `has_any_missing_condition_kind` collapses either
1471 /// to its `>= 1` halfspace Boolean.
1472 ///
1473 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1474 /// preserves proofs — the at-least-one halfspace projection
1475 /// composes the SAME closed-set walk under negation on both this
1476 /// ephemeral surface and the point-domain
1477 /// [`crate::boundary::Boundary`] surface under short-circuit
1478 /// semantics). THEORY.md §VI.1 (generation over composition — a
1479 /// future [`ConditionKind`] variant added to `ALL` reaches both
1480 /// surfaces' at-least-one halfspace triads mechanically through
1481 /// the SAME closed-set walk).
1482 #[must_use]
1483 pub fn has_any_missing_condition_kind(&self) -> bool {
1484 !self.is_condition_kind_saturated()
1485 }
1486
1487 /// `true` iff [`Self::preconditions`] is MISSING at least one
1488 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1489 /// the (precondition, postcondition, condition-union) at-least-
1490 /// one halfspace triad on [`EphemeralSpec`]. Thin typed delegate
1491 /// to [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
1492 /// over [`Self::preconditions`].
1493 ///
1494 /// Peer of
1495 /// [`crate::boundary::Boundary::has_any_missing_precondition_kind`]
1496 /// on the point-domain surface — both peers compose against the
1497 /// SAME slice-level substrate primitive so a regression at the
1498 /// per-slice `all` short-circuit under negation fails at that
1499 /// primitive's tests rather than as silent drift at either
1500 /// struct-level arm.
1501 #[must_use]
1502 pub fn has_any_missing_precondition_kind(&self) -> bool {
1503 self.preconditions.has_any_missing_kind()
1504 }
1505
1506 /// `true` iff [`Self::postconditions`] is MISSING at least one
1507 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1508 /// the (precondition, postcondition, condition-union) at-least-
1509 /// one halfspace triad on [`EphemeralSpec`]. Thin typed delegate
1510 /// to [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
1511 /// over [`Self::postconditions`].
1512 ///
1513 /// Peer of
1514 /// [`crate::boundary::Boundary::has_any_missing_postcondition_kind`]
1515 /// on the point-domain surface. See
1516 /// [`Self::has_any_missing_precondition_kind`] for the full
1517 /// rationale — the two methods share ONE lift motivation, ONE
1518 /// fail-before-pass-after composition-law pin, and ONE two-surface
1519 /// parity contract with the point-domain
1520 /// [`crate::boundary::Boundary`] at-least-one halfspace peer
1521 /// methods.
1522 #[must_use]
1523 pub fn has_any_missing_postcondition_kind(&self) -> bool {
1524 self.postconditions.has_any_missing_kind()
1525 }
1526
1527 /// `true` iff `preconditions ∪ postconditions` carries at least one
1528 /// [`ConditionKind::ALL`] variant — the peer of
1529 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
1530 /// on the [`EphemeralSpec`] sugar surface.
1531 ///
1532 /// # Composed body — byte-identical to
1533 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
1534 ///
1535 /// `ConditionKind::ALL.iter().copied().any(|k|
1536 /// self.has_condition_kind(k))` — the at-least-one halfspace
1537 /// projection of [`Self::distinct_condition_kinds`] onto its non-
1538 /// emptiness test via a SHORT-CIRCUITING closed-set walk under the
1539 /// two-slice union primitive [`Self::has_condition_kind`]. Byte-
1540 /// identical to the peer method on the point-domain
1541 /// [`crate::boundary::Boundary`] surface — both compose against
1542 /// the SAME slice-level substrate primitive
1543 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
1544 /// via the two-slice union so a regression at the per-slice `any`
1545 /// short-circuit fails at that primitive's tests rather than as
1546 /// silent drift at either struct-level at-least-one halfspace
1547 /// caller.
1548 ///
1549 /// # Sibling to [`Self::distinct_condition_kinds`] /
1550 /// [`Self::distinct_condition_kind_count`]
1551 ///
1552 /// Boolean at-least-one halfspace peer of the widened and scalar
1553 /// closed-set-inversion primitives on the ephemeral-union
1554 /// surface — where those primitives return the SET and its
1555 /// cardinality, `has_any_distinct_condition_kind` collapses either
1556 /// to its `>= 1` halfspace Boolean.
1557 ///
1558 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1559 /// preserves proofs — the at-least-one halfspace projection
1560 /// composes the SAME closed-set walk on both this ephemeral
1561 /// surface and the point-domain [`crate::boundary::Boundary`]
1562 /// surface under short-circuit semantics). THEORY.md §VI.1
1563 /// (generation over composition — a future [`ConditionKind`]
1564 /// variant added to `ALL` reaches both surfaces' at-least-one
1565 /// halfspace triads mechanically through the SAME closed-set
1566 /// walk).
1567 #[must_use]
1568 pub fn has_any_distinct_condition_kind(&self) -> bool {
1569 ConditionKind::ALL
1570 .iter()
1571 .copied()
1572 .any(|k| self.has_condition_kind(k))
1573 }
1574
1575 /// `true` iff [`Self::preconditions`] carries at least one
1576 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1577 /// the (precondition, postcondition, condition-union) at-least-
1578 /// one halfspace triad on [`EphemeralSpec`] on the closed-set-
1579 /// inversion axis. Thin typed delegate to
1580 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
1581 /// over [`Self::preconditions`].
1582 ///
1583 /// Peer of
1584 /// [`crate::boundary::Boundary::has_any_distinct_precondition_kind`]
1585 /// on the point-domain surface — both peers compose against the
1586 /// SAME slice-level substrate primitive so a regression at the
1587 /// per-slice `any` short-circuit fails at that primitive's tests
1588 /// rather than as silent drift at either struct-level arm.
1589 #[must_use]
1590 pub fn has_any_distinct_precondition_kind(&self) -> bool {
1591 self.preconditions.has_any_distinct_kind()
1592 }
1593
1594 /// `true` iff [`Self::postconditions`] carries at least one
1595 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1596 /// the (precondition, postcondition, condition-union) at-least-
1597 /// one halfspace triad on [`EphemeralSpec`] on the closed-set-
1598 /// inversion axis. Thin typed delegate to
1599 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
1600 /// over [`Self::postconditions`].
1601 ///
1602 /// Peer of
1603 /// [`crate::boundary::Boundary::has_any_distinct_postcondition_kind`]
1604 /// on the point-domain surface. See
1605 /// [`Self::has_any_distinct_precondition_kind`] for the full
1606 /// rationale — the two methods share ONE lift motivation, ONE
1607 /// fail-before-pass-after composition-law pin, and ONE two-surface
1608 /// parity contract with the point-domain
1609 /// [`crate::boundary::Boundary`] at-least-one halfspace peer
1610 /// methods.
1611 #[must_use]
1612 pub fn has_any_distinct_postcondition_kind(&self) -> bool {
1613 self.postconditions.has_any_distinct_kind()
1614 }
1615
1616 /// `true` iff `preconditions ∪ postconditions` carries EXACTLY
1617 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
1618 /// (precondition, postcondition, condition-union) cardinality-
1619 /// mid-endpoint triad on [`EphemeralSpec`] closing the singleton-
1620 /// coverage arm on the closed-set-inversion axis on the union of
1621 /// the two condition slots. The Boolean cardinality-mid-endpoint
1622 /// fast-path peer of [`Self::has_any_distinct_condition_kind`]
1623 /// (≥1 halfspace) on the union axis: where the at-least-one
1624 /// halfspace predicate answers "is ANY kind covered by the
1625 /// union?", `has_unique_distinct_condition_kind` answers "is
1626 /// EXACTLY ONE kind covered by the union?".
1627 ///
1628 /// Composed body: constructs a two-step-short-circuit walk over
1629 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1630 /// union primitive — the first covered union arm surfaces, then
1631 /// the walk short-circuits at the second. Byte-for-byte peer of
1632 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
1633 /// one slice-layer down, lifted to compose against
1634 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1635 /// against a single slice's `has_kind`.
1636 ///
1637 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_unique_distinct_condition_kind`]
1638 ///
1639 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1640 /// two-step short-circuit body composed against the point-domain
1641 /// surface's own union primitive. Both methods compose against
1642 /// the SAME slice-level substrate primitive
1643 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
1644 /// via the two-slice union — a regression at the per-slice
1645 /// singleton-coverage walk fails at that primitive's tests rather
1646 /// than as silent drift at either struct-level singleton-coverage
1647 /// caller.
1648 ///
1649 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1650 /// preserves proofs — the cardinality-mid-endpoint projection on
1651 /// the closed-set-inversion axis composes the SAME two-step
1652 /// short-circuit walk on both this ephemeral surface and the
1653 /// point-domain [`crate::boundary::Boundary`] surface). THEORY.md
1654 /// §VI.1 (generation over composition — a new [`ConditionKind`]
1655 /// variant reaches both surfaces' cardinality-mid-endpoint triads
1656 /// mechanically through the delegated union primitive).
1657 #[must_use]
1658 pub fn has_unique_distinct_condition_kind(&self) -> bool {
1659 let mut it = ConditionKind::ALL
1660 .iter()
1661 .copied()
1662 .filter(|k| self.has_condition_kind(*k));
1663 it.next().is_some() && it.next().is_none()
1664 }
1665
1666 /// `true` iff [`Self::preconditions`] carries EXACTLY ONE
1667 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1668 /// the (precondition, postcondition, condition-union)
1669 /// cardinality-mid-endpoint triad on [`EphemeralSpec`] on the
1670 /// closed-set-inversion axis. Thin typed delegate to
1671 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
1672 /// over [`Self::preconditions`].
1673 ///
1674 /// Peer of
1675 /// [`crate::boundary::Boundary::has_unique_distinct_precondition_kind`]
1676 /// on the point-domain surface — both peers compose against the
1677 /// SAME slice-level substrate primitive so a regression at the
1678 /// per-slice two-step short-circuit walk fails at that primitive's
1679 /// tests rather than as silent drift at either struct-level arm.
1680 #[must_use]
1681 pub fn has_unique_distinct_precondition_kind(&self) -> bool {
1682 self.preconditions.has_unique_distinct_kind()
1683 }
1684
1685 /// `true` iff [`Self::postconditions`] carries EXACTLY ONE
1686 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1687 /// the (precondition, postcondition, condition-union)
1688 /// cardinality-mid-endpoint triad on [`EphemeralSpec`] on the
1689 /// closed-set-inversion axis. Thin typed delegate to
1690 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
1691 /// over [`Self::postconditions`].
1692 ///
1693 /// Peer of
1694 /// [`crate::boundary::Boundary::has_unique_distinct_postcondition_kind`]
1695 /// on the point-domain surface. See
1696 /// [`Self::has_unique_distinct_precondition_kind`] for the full
1697 /// rationale — the two methods share ONE lift motivation, ONE
1698 /// fail-before-pass-after composition-law pin, and ONE two-surface
1699 /// parity contract with the point-domain
1700 /// [`crate::boundary::Boundary`] cardinality-mid-endpoint peer
1701 /// methods.
1702 #[must_use]
1703 pub fn has_unique_distinct_postcondition_kind(&self) -> bool {
1704 self.postconditions.has_unique_distinct_kind()
1705 }
1706
1707 /// The SOLE [`ConditionKind::ALL`] variant covered by
1708 /// `preconditions ∪ postconditions`, or `None` when the union
1709 /// covers 0 or ≥ 2 kinds — the peer of
1710 /// [`crate::boundary::Boundary::unique_distinct_condition_kind`]
1711 /// on the [`EphemeralSpec`] sugar surface.
1712 ///
1713 /// # Composed body — byte-identical to
1714 /// [`crate::boundary::Boundary::unique_distinct_condition_kind`]
1715 ///
1716 /// A two-step-short-circuit walk over [`ConditionKind::ALL`] under
1717 /// the [`Self::has_condition_kind`] union primitive — pull the
1718 /// first hit; return `Some(first)` iff the second hit is [`None`],
1719 /// else `None`. Byte-identical to the peer method on the point-
1720 /// domain [`crate::boundary::Boundary`] surface — both compose
1721 /// against the SAME slice-level substrate primitive
1722 /// [`crate::boundary::ConditionSliceExt::unique_distinct_kind`]
1723 /// via the two-slice union so a regression at the per-slice
1724 /// singleton-coverage witnessing walk fails at that primitive's
1725 /// tests rather than as silent drift at either struct-level
1726 /// singleton-coverage caller.
1727 ///
1728 /// # Sibling to [`Self::has_unique_distinct_condition_kind`]
1729 ///
1730 /// Witnessing scalar peer of the Boolean cardinality-mid-endpoint
1731 /// predicate at the SAME two-step short-circuit shape — where
1732 /// `has_unique_distinct_condition_kind` returns `true` iff the
1733 /// union covers exactly one kind, `unique_distinct_condition_kind`
1734 /// returns `Some(k)` naming that SOLE covered kind (composition
1735 /// law `unique_distinct_condition_kind().is_some() ==
1736 /// has_unique_distinct_condition_kind()` binds the two).
1737 ///
1738 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1739 /// preserves proofs — the exactly-one-hit witnessing projection
1740 /// composes the SAME two-step short-circuit walk on both this
1741 /// ephemeral surface and the point-domain
1742 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
1743 /// (generation over composition — a future [`ConditionKind`]
1744 /// variant added to `ALL` reaches both surfaces' unique-distinct-
1745 /// kind triads mechanically through the SAME two-step short-
1746 /// circuit walk).
1747 #[must_use]
1748 pub fn unique_distinct_condition_kind(&self) -> Option<ConditionKind> {
1749 let mut it = ConditionKind::ALL
1750 .iter()
1751 .copied()
1752 .filter(|k| self.has_condition_kind(*k));
1753 let first = it.next()?;
1754 match it.next() {
1755 None => Some(first),
1756 Some(_) => None,
1757 }
1758 }
1759
1760 /// The SOLE [`ConditionKind::ALL`] variant covered by
1761 /// [`Self::preconditions`], or `None` when preconditions cover 0
1762 /// or ≥ 2 kinds — the precondition-side arm of the (precondition,
1763 /// postcondition, condition-union) exactly-one-hit witnessing
1764 /// triad on [`EphemeralSpec`] on the closed-set-inversion axis.
1765 /// Thin typed delegate to
1766 /// [`crate::boundary::ConditionSliceExt::unique_distinct_kind`]
1767 /// over [`Self::preconditions`].
1768 ///
1769 /// Peer of
1770 /// [`crate::boundary::Boundary::unique_distinct_precondition_kind`]
1771 /// on the point-domain surface — both peers compose against the
1772 /// SAME slice-level substrate primitive so a regression at the
1773 /// per-slice two-step short-circuit witnessing walk fails at that
1774 /// primitive's tests rather than as silent drift at either
1775 /// struct-level arm.
1776 #[must_use]
1777 pub fn unique_distinct_precondition_kind(&self) -> Option<ConditionKind> {
1778 self.preconditions.unique_distinct_kind()
1779 }
1780
1781 /// The SOLE [`ConditionKind::ALL`] variant covered by
1782 /// [`Self::postconditions`], or `None` when postconditions cover
1783 /// 0 or ≥ 2 kinds — the postcondition-side arm of the
1784 /// (precondition, postcondition, condition-union) exactly-one-hit
1785 /// witnessing triad on [`EphemeralSpec`] on the closed-set-
1786 /// inversion axis. Thin typed delegate to
1787 /// [`crate::boundary::ConditionSliceExt::unique_distinct_kind`]
1788 /// over [`Self::postconditions`].
1789 ///
1790 /// Peer of
1791 /// [`crate::boundary::Boundary::unique_distinct_postcondition_kind`]
1792 /// on the point-domain surface. See
1793 /// [`Self::unique_distinct_precondition_kind`] for the full
1794 /// rationale — the two methods share ONE lift motivation, ONE
1795 /// fail-before-pass-after composition-law pin, and ONE two-
1796 /// surface parity contract with the point-domain
1797 /// [`crate::boundary::Boundary`] unique-distinct-kind peer methods.
1798 #[must_use]
1799 pub fn unique_distinct_postcondition_kind(&self) -> Option<ConditionKind> {
1800 self.postconditions.unique_distinct_kind()
1801 }
1802
1803 /// `true` iff `preconditions ∪ postconditions` COVERS AT LEAST
1804 /// TWO [`ConditionKind::ALL`] variants — the union arm of the
1805 /// (precondition, postcondition, condition-union) cardinality-
1806 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 kinds
1807 /// covered" arm on the union of the two condition slots. The
1808 /// Boolean cardinality many-arm fast-path peer of
1809 /// [`Self::has_unique_distinct_condition_kind`] (=1 arm) and
1810 /// [`Self::has_any_distinct_condition_kind`] (≥1 halfspace):
1811 /// closes the {0, 1, ≥2} trichotomy on the distinct axis at the
1812 /// ephemeral union struct layer.
1813 ///
1814 /// Composed body: constructs a two-step-short-circuit walk over
1815 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
1816 /// union primitive — pulls up to two hits off the filtered
1817 /// iterator; the primitive returns `true` iff BOTH the first and
1818 /// the second are [`Some`]. Byte-for-byte peer of
1819 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1820 /// one slice-layer down, lifted to compose against
1821 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1822 /// against a single slice's `has_kind`.
1823 ///
1824 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_distinct_condition_kind`]
1825 ///
1826 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1827 /// two-step short-circuit body composed against the point-domain
1828 /// surface's own union primitive. Both methods compose against
1829 /// the SAME slice-level substrate primitive
1830 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1831 /// via the two-slice union — a regression at the per-slice many-
1832 /// arm walk fails at that primitive's tests rather than as silent
1833 /// drift at either struct-level many-distinct caller.
1834 ///
1835 /// # Sibling to [`Self::distinct_condition_kinds`] /
1836 /// [`Self::distinct_condition_kind_count`]
1837 ///
1838 /// Cardinality-many-arm Boolean projection of the widened +
1839 /// scalar closed-set-inversion primitives on the ephemeral-union
1840 /// surface — where those primitives return the FULL distinct SET
1841 /// (a `Vec` of every present kind) and its cardinality (a `usize`
1842 /// in `0..=ConditionKind::ALL.len()`),
1843 /// `has_multiple_distinct_condition_kind` collapses either the
1844 /// widened primitive to its ≥ 2-length Boolean or the scalar to
1845 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
1846 /// either widened primitive on every arm with `≥ 2` distinct kinds
1847 /// because the walk short-circuits at the second distinct kind
1848 /// rather than allocating the closed-set-inversion scan or walking
1849 /// every slot to build the scalar cardinality.
1850 ///
1851 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1852 /// preserves proofs — the cardinality-many-arm projection on the
1853 /// distinct axis composes the SAME two-step short-circuit walk
1854 /// under a two-slice union on both this ephemeral surface and the
1855 /// point-domain [`crate::boundary::Boundary`] surface). THEORY.md
1856 /// §VI.1 (generation over composition — a new [`ConditionKind`]
1857 /// variant reaches both surfaces' cardinality-many-arm triads
1858 /// mechanically through the delegated union primitive).
1859 #[must_use]
1860 pub fn has_multiple_distinct_condition_kind(&self) -> bool {
1861 let mut it = ConditionKind::ALL
1862 .iter()
1863 .copied()
1864 .filter(|k| self.has_condition_kind(*k));
1865 it.next().is_some() && it.next().is_some()
1866 }
1867
1868 /// `true` iff [`Self::preconditions`] carries AT LEAST TWO
1869 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
1870 /// the (precondition, postcondition, condition-union) cardinality-
1871 /// many-arm triad on [`EphemeralSpec`] on the closed-set-inversion
1872 /// axis. Thin typed delegate to
1873 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1874 /// over [`Self::preconditions`].
1875 ///
1876 /// Peer of
1877 /// [`crate::boundary::Boundary::has_multiple_distinct_precondition_kind`]
1878 /// on the point-domain surface — both peers compose against the
1879 /// SAME slice-level substrate primitive so a regression at the
1880 /// per-slice two-step short-circuit walk fails at that primitive's
1881 /// tests rather than as silent drift at either struct-level arm.
1882 #[must_use]
1883 pub fn has_multiple_distinct_precondition_kind(&self) -> bool {
1884 self.preconditions.has_multiple_distinct_kinds()
1885 }
1886
1887 /// `true` iff [`Self::postconditions`] carries AT LEAST TWO
1888 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
1889 /// the (precondition, postcondition, condition-union) cardinality-
1890 /// many-arm triad on [`EphemeralSpec`] on the closed-set-inversion
1891 /// axis. Thin typed delegate to
1892 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
1893 /// over [`Self::postconditions`].
1894 ///
1895 /// Peer of
1896 /// [`crate::boundary::Boundary::has_multiple_distinct_postcondition_kind`]
1897 /// on the point-domain surface. See
1898 /// [`Self::has_multiple_distinct_precondition_kind`] for the full
1899 /// rationale — the two methods share ONE lift motivation, ONE
1900 /// fail-before-pass-after composition-law pin, and ONE two-surface
1901 /// parity contract with the point-domain
1902 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
1903 /// methods.
1904 #[must_use]
1905 pub fn has_multiple_distinct_postcondition_kind(&self) -> bool {
1906 self.postconditions.has_multiple_distinct_kinds()
1907 }
1908
1909 /// `true` iff `preconditions ∪ postconditions` carries AT MOST ONE
1910 /// [`ConditionKind::ALL`] variant — the union arm of the
1911 /// (precondition, postcondition, condition-union) cardinality
1912 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one kind
1913 /// covered" arm on the union of the two condition slots on the
1914 /// closed-set-inversion axis. The Boolean cardinality "≤ 1"
1915 /// negation peer of [`Self::has_multiple_distinct_condition_kind`]
1916 /// (≥ 2 many-arm) under the definitional negation
1917 /// `!has_multiple_distinct_condition_kind`, and the trichotomy-
1918 /// union peer of `!has_any_distinct_condition_kind` (=0 empty-
1919 /// endpoint) OR [`Self::has_unique_distinct_condition_kind`] (=1
1920 /// mid-endpoint) — names the arrangement space where the ephemeral
1921 /// spec is EMPTY-OR-SINGLETON on the union (zero or exactly one
1922 /// kind present across the union of the two slices).
1923 ///
1924 /// Composed body: `!self.has_multiple_distinct_condition_kind()`
1925 /// — a definitional negation of the many-arm union primitive.
1926 /// Short-circuits transitively through
1927 /// [`Self::has_multiple_distinct_condition_kind`]'s two-step
1928 /// short-circuit walk over [`ConditionKind::ALL`] under
1929 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
1930 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1931 /// one slice-layer down, lifted to compose against
1932 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
1933 /// against a single slice's `has_kind`.
1934 ///
1935 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_distinct_condition_kind`]
1936 ///
1937 /// Byte-identical signature `(&Self) -> bool`, byte-identical
1938 /// definitional-negation body composed against the point-domain
1939 /// surface's own many-arm union primitive. Both methods compose
1940 /// against the SAME slice-level substrate primitive
1941 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1942 /// via the two-slice union — a regression at the per-slice "≤ 1"
1943 /// negation fails at that primitive's tests rather than as silent
1944 /// drift at either struct-level empty-or-singleton caller.
1945 ///
1946 /// # Sibling to [`Self::distinct_condition_kinds`] /
1947 /// [`Self::distinct_condition_kind_count`]
1948 ///
1949 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
1950 /// closed-set-inversion primitives on the ephemeral-union
1951 /// surface — where those primitives return the FULL distinct SET
1952 /// (a `Vec` of every present kind) and its cardinality (a `usize`
1953 /// in `0..=ConditionKind::ALL.len()`),
1954 /// `has_at_most_one_distinct_condition_kind` collapses either the
1955 /// widened primitive to its `≤ 1`-length Boolean or the scalar
1956 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
1957 /// than either widened primitive on every arm because the
1958 /// underlying many-arm walk short-circuits at the second distinct
1959 /// kind — a subsequent bit-flip surfaces at ONE substrate call
1960 /// with no allocation.
1961 ///
1962 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
1963 /// preserves proofs — the cardinality "≤ 1" projection on the
1964 /// distinct axis composes the SAME definitional negation of the
1965 /// many-arm two-step short-circuit walk on both this ephemeral
1966 /// surface and the point-domain [`crate::boundary::Boundary`]
1967 /// surface). THEORY.md §VI.1 (generation over composition — a
1968 /// new [`ConditionKind`] variant reaches both surfaces'
1969 /// cardinality "≤ 1" triads mechanically through the delegated
1970 /// union primitive).
1971 #[must_use]
1972 pub fn has_at_most_one_distinct_condition_kind(&self) -> bool {
1973 !self.has_multiple_distinct_condition_kind()
1974 }
1975
1976 /// `true` iff [`Self::preconditions`] carries AT MOST ONE
1977 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
1978 /// the (precondition, postcondition, condition-union) cardinality
1979 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1980 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1981 /// over [`Self::preconditions`].
1982 ///
1983 /// Peer of
1984 /// [`crate::boundary::Boundary::has_at_most_one_distinct_precondition_kind`]
1985 /// on the point-domain surface — both peers compose against the
1986 /// SAME slice-level substrate primitive so a regression at the
1987 /// per-slice "≤ 1" negation fails at that primitive's tests
1988 /// rather than as silent drift at either struct-level arm.
1989 #[must_use]
1990 pub fn has_at_most_one_distinct_precondition_kind(&self) -> bool {
1991 self.preconditions.has_at_most_one_distinct_kind()
1992 }
1993
1994 /// `true` iff [`Self::postconditions`] carries AT MOST ONE
1995 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
1996 /// the (precondition, postcondition, condition-union) cardinality
1997 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
1998 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
1999 /// over [`Self::postconditions`].
2000 ///
2001 /// Peer of
2002 /// [`crate::boundary::Boundary::has_at_most_one_distinct_postcondition_kind`]
2003 /// on the point-domain surface. See
2004 /// [`Self::has_at_most_one_distinct_precondition_kind`] for the
2005 /// full rationale — the two methods share ONE lift motivation,
2006 /// ONE fail-before-pass-after composition-law pin, and ONE two-
2007 /// surface parity contract with the point-domain
2008 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
2009 #[must_use]
2010 pub fn has_at_most_one_distinct_postcondition_kind(&self) -> bool {
2011 self.postconditions.has_at_most_one_distinct_kind()
2012 }
2013
2014 /// `true` iff `preconditions ∪ postconditions` carries NO
2015 /// [`ConditionKind::ALL`] variant — the peer of
2016 /// [`crate::boundary::Boundary::is_condition_kind_empty`] on the
2017 /// [`EphemeralSpec`] sugar surface. Names the cardinality zero-
2018 /// endpoint on the closed-set-inversion axis at the union struct
2019 /// layer.
2020 ///
2021 /// # Composed body — byte-identical to
2022 /// [`crate::boundary::Boundary::is_condition_kind_empty`]
2023 ///
2024 /// `!self.has_any_distinct_condition_kind()` — a definitional
2025 /// negation of the at-least-one halfspace union primitive. Byte-
2026 /// identical to the peer method on the point-domain
2027 /// [`crate::boundary::Boundary`] surface — both compose against
2028 /// the SAME slice-level substrate primitive
2029 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] via the
2030 /// two-slice union so a regression at the per-slice zero-endpoint
2031 /// short-circuit fails at that primitive's tests rather than as
2032 /// silent drift at either struct-level empty caller.
2033 ///
2034 /// # Sibling to [`Self::is_condition_kind_saturated`]
2035 ///
2036 /// Axis-parity mirror of the closed-set-complement saturation-
2037 /// endpoint peer at the union struct layer — where
2038 /// `is_condition_kind_saturated` tests "every kind PRESENT across
2039 /// the union", this primitive tests "no kind PRESENT across the
2040 /// union". Both name a cardinality-endpoint on their respective
2041 /// axis under the same union struct layer.
2042 ///
2043 /// # Sibling to [`Self::distinct_condition_kinds`] /
2044 /// [`Self::distinct_condition_kind_count`]
2045 ///
2046 /// Cardinality zero-endpoint Boolean projection of the widened +
2047 /// scalar closed-set-inversion primitives on the ephemeral-union
2048 /// surface — where those primitives return the FULL distinct SET
2049 /// and its cardinality, `is_condition_kind_empty` collapses either
2050 /// the widened primitive to its emptiness Boolean or the scalar to
2051 /// its `== 0` cardinality-endpoint Boolean.
2052 ///
2053 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2054 /// preserves proofs — the cardinality zero-endpoint projection on
2055 /// the distinct axis composes the SAME definitional negation of
2056 /// the at-least-one halfspace short-circuit walk on both this
2057 /// ephemeral surface and the point-domain
2058 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2059 /// (generation over composition — a new [`ConditionKind`] variant
2060 /// reaches both surfaces' cardinality zero-endpoint triads
2061 /// mechanically through the delegated union primitive).
2062 #[must_use]
2063 pub fn is_condition_kind_empty(&self) -> bool {
2064 !self.has_any_distinct_condition_kind()
2065 }
2066
2067 /// `true` iff [`Self::preconditions`] carries NO
2068 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2069 /// the (precondition, postcondition, condition-union) cardinality
2070 /// zero-endpoint triad on [`EphemeralSpec`]. Thin typed delegate to
2071 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over
2072 /// [`Self::preconditions`].
2073 ///
2074 /// Peer of
2075 /// [`crate::boundary::Boundary::is_precondition_kind_empty`] on the
2076 /// point-domain surface — both peers compose against the SAME
2077 /// slice-level substrate primitive so a regression at the per-slice
2078 /// zero-endpoint short-circuit fails at that primitive's tests
2079 /// rather than as silent drift at either struct-level arm.
2080 #[must_use]
2081 pub fn is_precondition_kind_empty(&self) -> bool {
2082 self.preconditions.is_kind_empty()
2083 }
2084
2085 /// `true` iff [`Self::postconditions`] carries NO
2086 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2087 /// the (precondition, postcondition, condition-union) cardinality
2088 /// zero-endpoint triad on [`EphemeralSpec`]. Thin typed delegate to
2089 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over
2090 /// [`Self::postconditions`].
2091 ///
2092 /// Peer of
2093 /// [`crate::boundary::Boundary::is_postcondition_kind_empty`] on
2094 /// the point-domain surface. See
2095 /// [`Self::is_precondition_kind_empty`] for the full rationale —
2096 /// the two methods share ONE lift motivation, ONE fail-before-pass-
2097 /// after composition-law pin, and ONE two-surface parity contract
2098 /// with the point-domain [`crate::boundary::Boundary`] cardinality
2099 /// zero-endpoint peer methods.
2100 #[must_use]
2101 pub fn is_postcondition_kind_empty(&self) -> bool {
2102 self.postconditions.is_kind_empty()
2103 }
2104
2105 /// `true` iff `preconditions ∪ postconditions` carries AT LEAST ONE
2106 /// [`ConditionKind::ALL`] variant AND is MISSING AT LEAST ONE
2107 /// [`ConditionKind::ALL`] variant — the peer of
2108 /// [`crate::boundary::Boundary::is_condition_kind_partially_covered`]
2109 /// on the [`EphemeralSpec`] sugar surface. Names the parent-state
2110 /// middle-arm on the closed-set partition at the union struct
2111 /// layer, closing the trichotomy (empty, partially covered,
2112 /// saturated) alongside [`Self::is_condition_kind_empty`] and
2113 /// [`Self::is_condition_kind_saturated`].
2114 ///
2115 /// # Composed body — byte-identical to
2116 /// [`crate::boundary::Boundary::is_condition_kind_partially_covered`]
2117 ///
2118 /// `self.has_any_distinct_condition_kind() && self.has_any_missing_condition_kind()`
2119 /// — the paired at-least-one-halfspace composition. Byte-identical
2120 /// to the peer method on the point-domain
2121 /// [`crate::boundary::Boundary`] surface — both compose against the
2122 /// SAME slice-level substrate primitive
2123 /// [`crate::boundary::ConditionSliceExt::is_kind_partially_covered`]
2124 /// via the two-slice union so a regression at the per-slice fused
2125 /// short-circuit walk fails at that primitive's tests rather than
2126 /// as silent drift at either struct-level middle-arm caller.
2127 ///
2128 /// # Sibling to [`Self::is_condition_kind_empty`] / [`Self::is_condition_kind_saturated`]
2129 ///
2130 /// Third and final arm of the parent-state trichotomy on the
2131 /// closed-set partition at the ephemeral-union struct layer,
2132 /// closing the natural partition alongside `is_condition_kind_empty`
2133 /// (=0 zero-endpoint on the distinct axis) and
2134 /// `is_condition_kind_saturated` (=0 zero-endpoint on the missing
2135 /// axis). Every ephemeral spec satisfies EXACTLY ONE of the three
2136 /// Boolean projections on any `N ≥ 1` closed set.
2137 ///
2138 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2139 /// preserves proofs — the parent-state middle-arm projection
2140 /// composes the SAME paired-halfspace body on both this ephemeral
2141 /// surface and the point-domain [`crate::boundary::Boundary`]
2142 /// surface). THEORY.md §VI.1 (generation over composition — a new
2143 /// [`ConditionKind`] variant reaches both surfaces' parent-state
2144 /// middle-arm triads mechanically through the delegated union
2145 /// primitive).
2146 #[must_use]
2147 pub fn is_condition_kind_partially_covered(&self) -> bool {
2148 self.has_any_distinct_condition_kind() && self.has_any_missing_condition_kind()
2149 }
2150
2151 /// `true` iff [`Self::preconditions`] carries AT LEAST ONE
2152 /// [`ConditionKind::ALL`] variant AND is MISSING AT LEAST ONE
2153 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2154 /// the (precondition, postcondition, condition-union) parent-state
2155 /// middle-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2156 /// [`crate::boundary::ConditionSliceExt::is_kind_partially_covered`]
2157 /// over [`Self::preconditions`].
2158 ///
2159 /// Peer of
2160 /// [`crate::boundary::Boundary::is_precondition_kind_partially_covered`]
2161 /// on the point-domain surface — both peers compose against the
2162 /// SAME slice-level substrate primitive so a regression at the
2163 /// per-slice fused short-circuit walk fails at that primitive's
2164 /// tests rather than as silent drift at either struct-level arm.
2165 #[must_use]
2166 pub fn is_precondition_kind_partially_covered(&self) -> bool {
2167 self.preconditions.is_kind_partially_covered()
2168 }
2169
2170 /// `true` iff [`Self::postconditions`] carries AT LEAST ONE
2171 /// [`ConditionKind::ALL`] variant AND is MISSING AT LEAST ONE
2172 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2173 /// the (precondition, postcondition, condition-union) parent-state
2174 /// middle-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2175 /// [`crate::boundary::ConditionSliceExt::is_kind_partially_covered`]
2176 /// over [`Self::postconditions`].
2177 ///
2178 /// Peer of
2179 /// [`crate::boundary::Boundary::is_postcondition_kind_partially_covered`]
2180 /// on the point-domain surface. See
2181 /// [`Self::is_precondition_kind_partially_covered`] for the full
2182 /// rationale — the two methods share ONE lift motivation, ONE
2183 /// fail-before-pass-after composition-law pin, and ONE two-surface
2184 /// parity contract with the point-domain
2185 /// [`crate::boundary::Boundary`] parent-state middle-arm peer
2186 /// methods.
2187 #[must_use]
2188 pub fn is_postcondition_kind_partially_covered(&self) -> bool {
2189 self.postconditions.is_kind_partially_covered()
2190 }
2191
2192 /// `true` iff `preconditions ∪ postconditions` is MISSING EXACTLY
2193 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
2194 /// (precondition, postcondition, condition-union) cardinality-
2195 /// mid-endpoint triad on [`EphemeralSpec`] closing the near-
2196 /// saturation-endpoint on the union of the two condition slots.
2197 /// The Boolean cardinality-mid-endpoint fast-path peer of
2198 /// [`Self::is_condition_kind_saturated`]: where the saturation-
2199 /// endpoint predicate answers "is the union covered by every ALL
2200 /// variant?", `has_unique_missing_condition_kind` answers "is the
2201 /// union one kind away from covered?".
2202 ///
2203 /// Composed body: constructs a two-step-short-circuit walk over
2204 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
2205 /// union primitive negated — the first missing union arm surfaces,
2206 /// then the walk short-circuits at the second. Byte-for-byte peer
2207 /// of
2208 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2209 /// one slice-layer down, lifted to compose against
2210 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2211 /// against a single slice's `has_kind`.
2212 ///
2213 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
2214 ///
2215 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2216 /// two-step short-circuit body composed against the point-domain
2217 /// surface's own union primitive. Both methods compose against
2218 /// the SAME slice-level substrate primitive
2219 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2220 /// via the two-slice union — a regression at the per-slice
2221 /// near-saturation-endpoint walk fails at that primitive's tests
2222 /// rather than as silent drift at either struct-level near-
2223 /// saturation caller.
2224 ///
2225 /// # Sibling to [`Self::missing_condition_kinds`] /
2226 /// [`Self::missing_condition_kind_count`]
2227 ///
2228 /// Cardinality-mid-endpoint Boolean projection of the widened +
2229 /// scalar closed-set-complement primitives on the ephemeral-union
2230 /// surface — where those primitives return the FULL missing SET
2231 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2232 /// in `0..=ConditionKind::ALL.len()`),
2233 /// `has_unique_missing_condition_kind` collapses either the
2234 /// widened primitive to its unit-length Boolean or the scalar to
2235 /// its `== 1` cardinality-mid-endpoint Boolean. Strictly cheaper
2236 /// than either widened primitive on every arm with `≥ 2` missing
2237 /// kinds because the negation short-circuits at the second
2238 /// missing kind rather than allocating the closed-set-complement
2239 /// scan or walking every slot to build the scalar cardinality.
2240 ///
2241 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2242 /// preserves proofs — the cardinality-mid-endpoint projection on
2243 /// the missing axis composes the SAME two-step short-circuit walk
2244 /// under a two-slice union negation on both this ephemeral
2245 /// surface and the point-domain
2246 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2247 /// (generation over composition — a new [`ConditionKind`]
2248 /// variant reaches both surfaces' cardinality-mid-endpoint triads
2249 /// mechanically through the delegated union primitive).
2250 #[must_use]
2251 pub fn has_unique_missing_condition_kind(&self) -> bool {
2252 let mut it = ConditionKind::ALL
2253 .iter()
2254 .copied()
2255 .filter(|k| !self.has_condition_kind(*k));
2256 it.next().is_some() && it.next().is_none()
2257 }
2258
2259 /// `true` iff [`Self::preconditions`] is MISSING EXACTLY ONE
2260 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2261 /// the (precondition, postcondition, condition-union)
2262 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
2263 /// typed delegate to
2264 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2265 /// over [`Self::preconditions`].
2266 ///
2267 /// Peer of
2268 /// [`crate::boundary::Boundary::has_unique_missing_precondition_kind`]
2269 /// on the point-domain surface — both peers compose against the
2270 /// SAME slice-level substrate primitive so a regression at the
2271 /// per-slice two-step short-circuit walk under negation fails at
2272 /// that primitive's tests rather than as silent drift at either
2273 /// struct-level arm.
2274 #[must_use]
2275 pub fn has_unique_missing_precondition_kind(&self) -> bool {
2276 self.preconditions.has_unique_missing_kind()
2277 }
2278
2279 /// `true` iff [`Self::postconditions`] is MISSING EXACTLY ONE
2280 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2281 /// the (precondition, postcondition, condition-union)
2282 /// cardinality-mid-endpoint triad on [`EphemeralSpec`]. Thin
2283 /// typed delegate to
2284 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
2285 /// over [`Self::postconditions`].
2286 ///
2287 /// Peer of
2288 /// [`crate::boundary::Boundary::has_unique_missing_postcondition_kind`]
2289 /// on the point-domain surface. See
2290 /// [`Self::has_unique_missing_precondition_kind`] for the full
2291 /// rationale — the two methods share ONE lift motivation, ONE
2292 /// fail-before-pass-after composition-law pin, and ONE two-surface
2293 /// parity contract with the point-domain
2294 /// [`crate::boundary::Boundary`] cardinality-mid-endpoint peer
2295 /// methods.
2296 #[must_use]
2297 pub fn has_unique_missing_postcondition_kind(&self) -> bool {
2298 self.postconditions.has_unique_missing_kind()
2299 }
2300
2301 /// The SOLE [`ConditionKind::ALL`] variant ABSENT from
2302 /// `preconditions ∪ postconditions`, or `None` when the union is
2303 /// missing 0 or ≥ 2 kinds — the peer of
2304 /// [`crate::boundary::Boundary::unique_missing_condition_kind`]
2305 /// on the [`EphemeralSpec`] sugar surface.
2306 ///
2307 /// # Composed body — byte-identical to
2308 /// [`crate::boundary::Boundary::unique_missing_condition_kind`]
2309 ///
2310 /// A two-step-short-circuit walk over [`ConditionKind::ALL`] under
2311 /// a NEGATED [`Self::has_condition_kind`] union primitive — pull
2312 /// the first hit; return `Some(first)` iff the second hit is
2313 /// [`None`], else `None`. Byte-identical to the peer method on the
2314 /// point-domain [`crate::boundary::Boundary`] surface — both
2315 /// compose against the SAME slice-level substrate primitive
2316 /// [`crate::boundary::ConditionSliceExt::unique_missing_kind`] via
2317 /// the two-slice union so a regression at the per-slice near-
2318 /// saturation witnessing walk fails at that primitive's tests
2319 /// rather than as silent drift at either struct-level near-
2320 /// saturation caller.
2321 ///
2322 /// # Sibling to [`Self::has_unique_missing_condition_kind`]
2323 ///
2324 /// Witnessing scalar peer of the Boolean cardinality-mid-endpoint
2325 /// predicate on the missing axis at the SAME two-step short-
2326 /// circuit shape — where `has_unique_missing_condition_kind`
2327 /// returns `true` iff the union is one kind AWAY from covered,
2328 /// `unique_missing_condition_kind` returns `Some(k)` naming that
2329 /// SOLE remaining hole (composition law
2330 /// `unique_missing_condition_kind().is_some() ==
2331 /// has_unique_missing_condition_kind()` binds the two).
2332 ///
2333 /// # Compounding
2334 ///
2335 /// An operator-facing "one dependency still unfulfilled: X" gap-
2336 /// analysis diagnostic on an ephemeral env reads
2337 /// `spec.unique_missing_condition_kind()` at ONE call site — the
2338 /// WITNESS + the exactly-one predicate composed at ONE short-
2339 /// circuit walk, rather than pairing the Boolean
2340 /// [`Self::has_unique_missing_condition_kind`] with
2341 /// [`Self::first_missing_condition_kind`] at TWO independent
2342 /// walks.
2343 ///
2344 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2345 /// preserves proofs — the complement-exactly-one-hit witnessing
2346 /// projection composes the SAME two-step short-circuit walk on
2347 /// both this ephemeral surface and the point-domain
2348 /// [`crate::boundary::Boundary`] surface under a negated predicate).
2349 /// THEORY.md §VI.1 (generation over composition — a future
2350 /// [`ConditionKind`] variant added to `ALL` reaches both surfaces'
2351 /// unique-missing-kind triads mechanically through the SAME two-
2352 /// step short-circuit walk).
2353 #[must_use]
2354 pub fn unique_missing_condition_kind(&self) -> Option<ConditionKind> {
2355 let mut it = ConditionKind::ALL
2356 .iter()
2357 .copied()
2358 .filter(|k| !self.has_condition_kind(*k));
2359 let first = it.next()?;
2360 match it.next() {
2361 None => Some(first),
2362 Some(_) => None,
2363 }
2364 }
2365
2366 /// The SOLE [`ConditionKind::ALL`] variant ABSENT from
2367 /// [`Self::preconditions`], or `None` when preconditions are
2368 /// missing 0 or ≥ 2 kinds — the precondition-side arm of the
2369 /// (precondition, postcondition, condition-union) exactly-one-
2370 /// missing witnessing triad on [`EphemeralSpec`]. Thin typed
2371 /// delegate to
2372 /// [`crate::boundary::ConditionSliceExt::unique_missing_kind`]
2373 /// over [`Self::preconditions`].
2374 ///
2375 /// Peer of
2376 /// [`crate::boundary::Boundary::unique_missing_precondition_kind`]
2377 /// on the point-domain surface — both peers compose against the
2378 /// SAME slice-level substrate primitive so a regression at the
2379 /// per-slice two-step short-circuit witnessing walk under negation
2380 /// fails at that primitive's tests rather than as silent drift at
2381 /// either struct-level arm.
2382 #[must_use]
2383 pub fn unique_missing_precondition_kind(&self) -> Option<ConditionKind> {
2384 self.preconditions.unique_missing_kind()
2385 }
2386
2387 /// The SOLE [`ConditionKind::ALL`] variant ABSENT from
2388 /// [`Self::postconditions`], or `None` when postconditions are
2389 /// missing 0 or ≥ 2 kinds — the postcondition-side arm of the
2390 /// (precondition, postcondition, condition-union) exactly-one-
2391 /// missing witnessing triad on [`EphemeralSpec`]. Thin typed
2392 /// delegate to
2393 /// [`crate::boundary::ConditionSliceExt::unique_missing_kind`]
2394 /// over [`Self::postconditions`].
2395 ///
2396 /// Peer of
2397 /// [`crate::boundary::Boundary::unique_missing_postcondition_kind`]
2398 /// on the point-domain surface. See
2399 /// [`Self::unique_missing_precondition_kind`] for the full
2400 /// rationale — the two methods share ONE lift motivation, ONE
2401 /// fail-before-pass-after composition-law pin, and ONE two-surface
2402 /// parity contract with the point-domain
2403 /// [`crate::boundary::Boundary`] unique-missing-kind peer methods.
2404 #[must_use]
2405 pub fn unique_missing_postcondition_kind(&self) -> Option<ConditionKind> {
2406 self.postconditions.unique_missing_kind()
2407 }
2408
2409 /// `true` iff `preconditions ∪ postconditions` is MISSING AT
2410 /// LEAST TWO [`ConditionKind::ALL`] variants — the union arm of
2411 /// the (precondition, postcondition, condition-union) cardinality-
2412 /// many-arm triad on [`EphemeralSpec`] closing the "≥ 2 holes
2413 /// remaining" arm on the union of the two condition slots. The
2414 /// Boolean cardinality many-arm fast-path peer of
2415 /// [`Self::has_unique_missing_condition_kind`] (=1 arm) and
2416 /// [`Self::is_condition_kind_saturated`] (=0 arm): closes the
2417 /// {0, 1, ≥2} trichotomy on the missing axis at the ephemeral
2418 /// union struct layer.
2419 ///
2420 /// Composed body: constructs a two-step-short-circuit walk over
2421 /// [`ConditionKind::ALL`] under the [`Self::has_condition_kind`]
2422 /// union primitive negated — pulls up to two hits off the
2423 /// filtered iterator; the primitive returns `true` iff BOTH the
2424 /// first and the second are [`Some`]. Byte-for-byte peer of
2425 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2426 /// one slice-layer down, lifted to compose against
2427 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2428 /// against a single slice's `has_kind`.
2429 ///
2430 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
2431 ///
2432 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2433 /// two-step short-circuit body composed against the point-domain
2434 /// surface's own union primitive. Both methods compose against
2435 /// the SAME slice-level substrate primitive
2436 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2437 /// via the two-slice union — a regression at the per-slice many-
2438 /// arm walk fails at that primitive's tests rather than as silent
2439 /// drift at either struct-level many-missing caller.
2440 ///
2441 /// # Sibling to [`Self::missing_condition_kinds`] /
2442 /// [`Self::missing_condition_kind_count`]
2443 ///
2444 /// Cardinality-many-arm Boolean projection of the widened +
2445 /// scalar closed-set-complement primitives on the ephemeral-union
2446 /// surface — where those primitives return the FULL missing SET
2447 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2448 /// in `0..=ConditionKind::ALL.len()`),
2449 /// `has_multiple_missing_condition_kind` collapses either the
2450 /// widened primitive to its ≥ 2-length Boolean or the scalar to
2451 /// its `>= 2` cardinality-many-arm Boolean. Strictly cheaper than
2452 /// either widened primitive on every arm with `≥ 2` missing kinds
2453 /// because the negation short-circuits at the second missing kind
2454 /// rather than allocating the closed-set-complement scan or
2455 /// walking every slot to build the scalar cardinality.
2456 ///
2457 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2458 /// preserves proofs — the cardinality-many-arm projection on the
2459 /// missing axis composes the SAME two-step short-circuit walk
2460 /// under a two-slice union negation on both this ephemeral
2461 /// surface and the point-domain
2462 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2463 /// (generation over composition — a new [`ConditionKind`]
2464 /// variant reaches both surfaces' cardinality-many-arm triads
2465 /// mechanically through the delegated union primitive).
2466 #[must_use]
2467 pub fn has_multiple_missing_condition_kind(&self) -> bool {
2468 let mut it = ConditionKind::ALL
2469 .iter()
2470 .copied()
2471 .filter(|k| !self.has_condition_kind(*k));
2472 it.next().is_some() && it.next().is_some()
2473 }
2474
2475 /// `true` iff [`Self::preconditions`] is MISSING AT LEAST TWO
2476 /// [`ConditionKind::ALL`] variants — the precondition-side arm of
2477 /// the (precondition, postcondition, condition-union) cardinality-
2478 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2479 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2480 /// over [`Self::preconditions`].
2481 ///
2482 /// Peer of
2483 /// [`crate::boundary::Boundary::has_multiple_missing_precondition_kind`]
2484 /// on the point-domain surface — both peers compose against the
2485 /// SAME slice-level substrate primitive so a regression at the
2486 /// per-slice two-step short-circuit walk under negation fails at
2487 /// that primitive's tests rather than as silent drift at either
2488 /// struct-level arm.
2489 #[must_use]
2490 pub fn has_multiple_missing_precondition_kind(&self) -> bool {
2491 self.preconditions.has_multiple_missing_kinds()
2492 }
2493
2494 /// `true` iff [`Self::postconditions`] is MISSING AT LEAST TWO
2495 /// [`ConditionKind::ALL`] variants — the postcondition-side arm of
2496 /// the (precondition, postcondition, condition-union) cardinality-
2497 /// many-arm triad on [`EphemeralSpec`]. Thin typed delegate to
2498 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
2499 /// over [`Self::postconditions`].
2500 ///
2501 /// Peer of
2502 /// [`crate::boundary::Boundary::has_multiple_missing_postcondition_kind`]
2503 /// on the point-domain surface. See
2504 /// [`Self::has_multiple_missing_precondition_kind`] for the full
2505 /// rationale — the two methods share ONE lift motivation, ONE
2506 /// fail-before-pass-after composition-law pin, and ONE two-surface
2507 /// parity contract with the point-domain
2508 /// [`crate::boundary::Boundary`] cardinality-many-arm peer
2509 /// methods.
2510 #[must_use]
2511 pub fn has_multiple_missing_postcondition_kind(&self) -> bool {
2512 self.postconditions.has_multiple_missing_kinds()
2513 }
2514
2515 /// `true` iff `preconditions ∪ postconditions` is MISSING AT MOST
2516 /// ONE [`ConditionKind::ALL`] variant — the union arm of the
2517 /// (precondition, postcondition, condition-union) cardinality
2518 /// "≤ 1" triad on [`EphemeralSpec`] closing the "at most one hole
2519 /// remaining" arm on the union of the two condition slots. The
2520 /// Boolean cardinality "≤ 1" negation peer of
2521 /// [`Self::has_multiple_missing_condition_kind`] (≥ 2 many-arm)
2522 /// under the definitional negation
2523 /// `!has_multiple_missing_condition_kind`, and the trichotomy-
2524 /// union peer of [`Self::is_condition_kind_saturated`] (=0
2525 /// zero-arm) OR [`Self::has_unique_missing_condition_kind`] (=1
2526 /// mid-endpoint) — names the arrangement space where the
2527 /// ephemeral spec is SATURATED-OR-NEAR-SATURATED on the union
2528 /// (zero or exactly one kind missing across the union of the two
2529 /// slices).
2530 ///
2531 /// Composed body: `!self.has_multiple_missing_condition_kind()`
2532 /// — a definitional negation of the many-arm union primitive.
2533 /// Short-circuits transitively through
2534 /// [`Self::has_multiple_missing_condition_kind`]'s two-step short-
2535 /// circuit walk over [`ConditionKind::ALL`] under negated
2536 /// [`Self::has_condition_kind`]. Byte-for-byte peer of
2537 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2538 /// one slice-layer down, lifted to compose against
2539 /// [`Self::has_condition_kind`]'s pre-OR-post union rather than
2540 /// against a single slice's `has_kind`.
2541 ///
2542 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
2543 ///
2544 /// Byte-identical signature `(&Self) -> bool`, byte-identical
2545 /// definitional-negation body composed against the point-domain
2546 /// surface's own many-arm union primitive. Both methods compose
2547 /// against the SAME slice-level substrate primitive
2548 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2549 /// via the two-slice union — a regression at the per-slice "≤ 1"
2550 /// negation fails at that primitive's tests rather than as silent
2551 /// drift at either struct-level near-saturation-or-saturated
2552 /// caller.
2553 ///
2554 /// # Sibling to [`Self::missing_condition_kinds`] /
2555 /// [`Self::missing_condition_kind_count`]
2556 ///
2557 /// Cardinality "≤ 1" Boolean projection of the widened + scalar
2558 /// closed-set-complement primitives on the ephemeral-union
2559 /// surface — where those primitives return the FULL missing SET
2560 /// (a `Vec` of every absent kind) and its cardinality (a `usize`
2561 /// in `0..=ConditionKind::ALL.len()`),
2562 /// `has_at_most_one_missing_condition_kind` collapses either the
2563 /// widened primitive to its `≤ 1`-length Boolean or the scalar
2564 /// to its `<= 1` cardinality-negation Boolean. Strictly cheaper
2565 /// than either widened primitive on every arm because the
2566 /// underlying many-arm walk short-circuits at the second missing
2567 /// kind — a subsequent bit-flip surfaces at ONE substrate call
2568 /// with no allocation.
2569 ///
2570 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2571 /// preserves proofs — the cardinality "≤ 1" projection on the
2572 /// missing axis composes the SAME definitional negation of the
2573 /// many-arm two-step short-circuit walk on both this ephemeral
2574 /// surface and the point-domain [`crate::boundary::Boundary`]
2575 /// surface). THEORY.md §VI.1 (generation over composition — a
2576 /// new [`ConditionKind`] variant reaches both surfaces'
2577 /// cardinality "≤ 1" triads mechanically through the delegated
2578 /// union primitive).
2579 #[must_use]
2580 pub fn has_at_most_one_missing_condition_kind(&self) -> bool {
2581 !self.has_multiple_missing_condition_kind()
2582 }
2583
2584 /// `true` iff [`Self::preconditions`] is MISSING AT MOST ONE
2585 /// [`ConditionKind::ALL`] variant — the precondition-side arm of
2586 /// the (precondition, postcondition, condition-union) cardinality
2587 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
2588 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2589 /// over [`Self::preconditions`].
2590 ///
2591 /// Peer of
2592 /// [`crate::boundary::Boundary::has_at_most_one_missing_precondition_kind`]
2593 /// on the point-domain surface — both peers compose against the
2594 /// SAME slice-level substrate primitive so a regression at the
2595 /// per-slice "≤ 1" negation fails at that primitive's tests
2596 /// rather than as silent drift at either struct-level arm.
2597 #[must_use]
2598 pub fn has_at_most_one_missing_precondition_kind(&self) -> bool {
2599 self.preconditions.has_at_most_one_missing_kind()
2600 }
2601
2602 /// `true` iff [`Self::postconditions`] is MISSING AT MOST ONE
2603 /// [`ConditionKind::ALL`] variant — the postcondition-side arm of
2604 /// the (precondition, postcondition, condition-union) cardinality
2605 /// "≤ 1" triad on [`EphemeralSpec`]. Thin typed delegate to
2606 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
2607 /// over [`Self::postconditions`].
2608 ///
2609 /// Peer of
2610 /// [`crate::boundary::Boundary::has_at_most_one_missing_postcondition_kind`]
2611 /// on the point-domain surface. See
2612 /// [`Self::has_at_most_one_missing_precondition_kind`] for the
2613 /// full rationale — the two methods share ONE lift motivation,
2614 /// ONE fail-before-pass-after composition-law pin, and ONE two-
2615 /// surface parity contract with the point-domain
2616 /// [`crate::boundary::Boundary`] cardinality "≤ 1" peer methods.
2617 #[must_use]
2618 pub fn has_at_most_one_missing_postcondition_kind(&self) -> bool {
2619 self.postconditions.has_at_most_one_missing_kind()
2620 }
2621
2622 /// `true` iff `preconditions ∪ postconditions` carries NO
2623 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2624 /// — the peer of
2625 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
2626 /// [`EphemeralSpec`] sugar surface.
2627 ///
2628 /// # Composed body — byte-identical to
2629 /// [`crate::boundary::Boundary::lacks_condition_kind`]
2630 ///
2631 /// `!self.has_condition_kind(kind)` — the definitional negation of
2632 /// the two-slice union primitive [`Self::has_condition_kind`].
2633 /// Byte-identical to the peer method on the point-domain
2634 /// [`crate::boundary::Boundary`] surface — both compose against
2635 /// the SAME slice-level substrate primitive
2636 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] via the
2637 /// two-slice union so a regression at the per-slice negation
2638 /// fails at that primitive's tests rather than as silent drift at
2639 /// either struct-level complement caller.
2640 ///
2641 /// # Sibling to [`Self::missing_condition_kinds`] /
2642 /// [`Self::missing_condition_kind_count`]
2643 ///
2644 /// Per-kind Boolean projection of the widened + scalar closed-set-
2645 /// complement primitives on the ephemeral-union surface — where
2646 /// those primitives return the FULL missing SET (a `Vec` of every
2647 /// absent kind) and its cardinality (a `usize`),
2648 /// `lacks_condition_kind` collapses the missing SET to its
2649 /// per-kind membership Boolean for ONE addressed kind. Strictly
2650 /// cheaper than reaching for the widened primitive on every
2651 /// per-kind question because the negation short-circuits through
2652 /// [`Self::has_condition_kind`] rather than allocating the
2653 /// closed-set-complement scan.
2654 ///
2655 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2656 /// preserves proofs — the per-kind closed-set-complement
2657 /// projection composes the SAME two-slice union negation on both
2658 /// this ephemeral surface and the point-domain
2659 /// [`crate::boundary::Boundary`] surface under definitional
2660 /// negation). THEORY.md §VI.1 (generation over composition — a
2661 /// future [`ConditionKind`] variant reaches both surfaces'
2662 /// per-kind-complement triads mechanically through the delegated
2663 /// union primitive).
2664 #[must_use]
2665 pub fn lacks_condition_kind(&self, kind: ConditionKind) -> bool {
2666 !self.has_condition_kind(kind)
2667 }
2668
2669 /// `true` iff [`Self::preconditions`] carries NO
2670 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2671 /// — the precondition-side arm of the (precondition, postcondition,
2672 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2673 /// Thin typed delegate to
2674 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2675 /// [`Self::preconditions`].
2676 ///
2677 /// Peer of
2678 /// [`crate::boundary::Boundary::lacks_precondition_kind`] on the
2679 /// point-domain surface — both peers compose against the SAME
2680 /// slice-level substrate primitive so a regression at the
2681 /// per-slice negation fails at that primitive's tests rather than
2682 /// as silent drift at either struct-level arm.
2683 #[must_use]
2684 pub fn lacks_precondition_kind(&self, kind: ConditionKind) -> bool {
2685 self.preconditions.lacks_kind(kind)
2686 }
2687
2688 /// `true` iff [`Self::postconditions`] carries NO
2689 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2690 /// — the postcondition-side arm of the (precondition, postcondition,
2691 /// condition-union) per-kind-complement triad on [`EphemeralSpec`].
2692 /// Thin typed delegate to
2693 /// [`crate::boundary::ConditionSliceExt::lacks_kind`] over
2694 /// [`Self::postconditions`].
2695 ///
2696 /// Peer of
2697 /// [`crate::boundary::Boundary::lacks_postcondition_kind`] on the
2698 /// point-domain surface. See [`Self::lacks_precondition_kind`] for
2699 /// the full rationale — the two methods share ONE lift motivation,
2700 /// ONE fail-before-pass-after composition-law pin, and ONE
2701 /// two-surface parity contract with the point-domain
2702 /// [`crate::boundary::Boundary`] per-kind-complement peer methods.
2703 #[must_use]
2704 pub fn lacks_postcondition_kind(&self, kind: ConditionKind) -> bool {
2705 self.postconditions.lacks_kind(kind)
2706 }
2707
2708 /// `true` iff `preconditions ∪ postconditions` carries at least
2709 /// one [`crate::boundary::Condition`] with the given
2710 /// [`ConditionKind`] AND carries no [`crate::boundary::Condition`]
2711 /// whose kind is anything OTHER than `kind` — the union arm of
2712 /// the (precondition, postcondition, condition-union) kind-scoped
2713 /// strict-refinement triad on [`EphemeralSpec`], byte-for-byte
2714 /// peer of the point-domain
2715 /// [`crate::boundary::Boundary::has_only_condition_kind`] under
2716 /// the same fused-closed-set-walk body.
2717 ///
2718 /// # Composed body
2719 ///
2720 /// A FUSED short-circuit closed-set walk over
2721 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2722 /// returns `false` at the EARLIEST kind whose presence spans
2723 /// either slice's populated set and is NOT `kind`, and returns
2724 /// `true` iff the sweep completes with `kind` seen as the sole
2725 /// distinct populated kind. Strictly cheaper than the widened
2726 /// composition
2727 /// `self.distinct_condition_kinds() == vec![kind]` (which
2728 /// allocates the distinct-kind Vec before the equality test) or
2729 /// the (pre, post) AND-of-strict-refinement
2730 /// `self.preconditions.has_only_kind(kind)
2731 /// && self.postconditions.has_only_kind(kind)` (which is TOO
2732 /// STRICT — a single-slice-populated arrangement whose empty side
2733 /// returns `false` fails this AND but IS well-formed on the
2734 /// union).
2735 ///
2736 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::has_only_condition_kind`]
2737 ///
2738 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2739 /// byte-identical fused-closed-set-walk body, on the point-domain
2740 /// surface whose pre/post condition vectors live inside a
2741 /// [`crate::boundary::Boundary`] slot. Both methods compose
2742 /// against the SAME slice-level substrate primitive
2743 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] via the
2744 /// two-slice union composed through [`Self::has_condition_kind`]
2745 /// — a regression at the per-slice fused walk fails at that
2746 /// primitive's tests rather than as silent drift at either
2747 /// struct-level kind-scoped-strict-refinement caller.
2748 ///
2749 /// # Compounding
2750 ///
2751 /// A future coherence check verifying "every ephemeral spec whose
2752 /// postconditions carry ONLY `ClosedLoopAuth` (no `JobAttested`,
2753 /// no `Cel`, ...) is a well-formed closed-loop probe" reads
2754 /// `spec.has_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2755 /// at ONE call site rather than restating either widened
2756 /// composition. A `has-only-<kind>` require-tag classifier arm on
2757 /// the ephemeral surface reaches this primitive at ONE substrate
2758 /// call — byte-for-byte peer of the tagged-union
2759 /// `has-only-<kind>` classifier one struct-layer up under the
2760 /// SAME fused short-circuit walk shape.
2761 ///
2762 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2763 /// preserves proofs — the kind-scoped strict-refinement projection
2764 /// composes the SAME fused short-circuit closed-set walk under
2765 /// [`Self::has_condition_kind`] on both this ephemeral surface
2766 /// and the point-domain [`crate::boundary::Boundary`] surface).
2767 /// THEORY.md §VI.1 (generation over composition — a future
2768 /// [`ConditionKind`] variant reaches both surfaces' kind-scoped
2769 /// strict-refinement triads mechanically through the delegated
2770 /// union primitive).
2771 #[must_use]
2772 pub fn has_only_condition_kind(&self, kind: ConditionKind) -> bool {
2773 let mut saw_kind = false;
2774 for k in ConditionKind::ALL {
2775 if !self.has_condition_kind(k) {
2776 continue;
2777 }
2778 if k == kind {
2779 saw_kind = true;
2780 } else {
2781 return false;
2782 }
2783 }
2784 saw_kind
2785 }
2786
2787 /// `true` iff [`Self::preconditions`] carries at least one
2788 /// [`crate::boundary::Condition`] with the given
2789 /// [`ConditionKind`] AND carries no
2790 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2791 /// than `kind` — the precondition-side arm of the (precondition,
2792 /// postcondition, condition-union) kind-scoped strict-refinement
2793 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2794 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2795 /// [`Self::preconditions`].
2796 ///
2797 /// Peer of
2798 /// [`crate::boundary::Boundary::has_only_precondition_kind`] on
2799 /// the point-domain surface — both peers compose against the SAME
2800 /// slice-level substrate primitive so a regression at the per-
2801 /// slice fused walk fails at that primitive's tests rather than
2802 /// as silent drift at either struct-level arm.
2803 #[must_use]
2804 pub fn has_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2805 self.preconditions.has_only_kind(kind)
2806 }
2807
2808 /// `true` iff [`Self::postconditions`] carries at least one
2809 /// [`crate::boundary::Condition`] with the given
2810 /// [`ConditionKind`] AND carries no
2811 /// [`crate::boundary::Condition`] whose kind is anything OTHER
2812 /// than `kind` — the postcondition-side arm of the (precondition,
2813 /// postcondition, condition-union) kind-scoped strict-refinement
2814 /// triad on [`EphemeralSpec`]. Thin typed delegate to
2815 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] over
2816 /// [`Self::postconditions`].
2817 ///
2818 /// Peer of
2819 /// [`crate::boundary::Boundary::has_only_postcondition_kind`] on
2820 /// the point-domain surface. See [`Self::has_only_precondition_kind`]
2821 /// for the full rationale — the two methods share ONE lift
2822 /// motivation, ONE fail-before-pass-after composition-law pin,
2823 /// and ONE two-surface parity contract with the point-domain
2824 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement
2825 /// peer methods.
2826 #[must_use]
2827 pub fn has_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2828 self.postconditions.has_only_kind(kind)
2829 }
2830
2831 /// `true` iff `preconditions ∪ postconditions` carries NO
2832 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2833 /// AND carries at least one [`crate::boundary::Condition`] for
2834 /// every OTHER [`ConditionKind`] — the union arm of the
2835 /// (precondition, postcondition, condition-union) kind-scoped
2836 /// strict-refinement-on-missing triad on [`EphemeralSpec`], byte-
2837 /// for-byte peer of the point-domain
2838 /// [`crate::boundary::Boundary::lacks_only_condition_kind`] under
2839 /// the same fused-closed-set-walk body on the missing axis.
2840 ///
2841 /// # Composed body
2842 ///
2843 /// A FUSED short-circuit closed-set walk over
2844 /// [`ConditionKind::ALL`] under [`Self::has_condition_kind`] that
2845 /// skips every populated kind, returns `false` at the EARLIEST
2846 /// kind whose absence spans both slices' missing sets and is NOT
2847 /// `kind`, and returns `true` iff the sweep completes with `kind`
2848 /// seen as the sole missing kind. Strictly cheaper than the
2849 /// widened composition
2850 /// `self.missing_condition_kinds() == vec![kind]` (which allocates
2851 /// the missing-kind Vec before the equality test) or the
2852 /// (pre AND post) AND-of-strict-refinement
2853 /// `self.preconditions.lacks_only_kind(kind)
2854 /// && self.postconditions.lacks_only_kind(kind)` (which is TOO
2855 /// STRICT — a single-slice-populated arrangement whose empty side
2856 /// returns `false` fails this AND but IS well-formed on the
2857 /// union).
2858 ///
2859 /// # Peer on the point-domain surface — [`crate::boundary::Boundary::lacks_only_condition_kind`]
2860 ///
2861 /// Byte-identical signature `(&Self, ConditionKind) -> bool`,
2862 /// byte-identical fused-closed-set-walk body under complement, on
2863 /// the point-domain surface whose pre/post condition vectors live
2864 /// inside a [`crate::boundary::Boundary`] slot. Both methods
2865 /// compose against the SAME slice-level substrate primitive
2866 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] via
2867 /// the two-slice union composed through
2868 /// [`Self::has_condition_kind`] — a regression at the per-slice
2869 /// fused walk under complement fails at that primitive's tests
2870 /// rather than as silent drift at either struct-level kind-scoped-
2871 /// strict-refinement-on-missing caller.
2872 ///
2873 /// # Compounding
2874 ///
2875 /// A future coherence check verifying "every partially-attested
2876 /// ephemeral closed-loop probe is missing ONLY the
2877 /// `ClosedLoopAuth` postcondition" reads
2878 /// `spec.lacks_only_condition_kind(ConditionKind::ClosedLoopAuth)`
2879 /// at ONE call site rather than restating either widened
2880 /// composition. A `lacks-only-<kind>` require-tag classifier arm
2881 /// on the ephemeral surface reaches this primitive at ONE
2882 /// substrate call — byte-for-byte peer of the tagged-union
2883 /// `lacks-only-<kind>` classifier one struct-layer up under the
2884 /// SAME fused short-circuit walk shape.
2885 ///
2886 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
2887 /// preserves proofs — the kind-scoped strict-refinement projection
2888 /// on the missing axis composes the SAME fused short-circuit
2889 /// closed-set walk under [`Self::has_condition_kind`] on both this
2890 /// ephemeral surface and the point-domain
2891 /// [`crate::boundary::Boundary`] surface). THEORY.md §VI.1
2892 /// (generation over composition — a future [`ConditionKind`]
2893 /// variant reaches both surfaces' kind-scoped-strict-refinement-
2894 /// on-missing triads mechanically through the delegated union
2895 /// primitive).
2896 #[must_use]
2897 pub fn lacks_only_condition_kind(&self, kind: ConditionKind) -> bool {
2898 let mut saw_kind = false;
2899 for k in ConditionKind::ALL {
2900 if self.has_condition_kind(k) {
2901 continue;
2902 }
2903 if k == kind {
2904 saw_kind = true;
2905 } else {
2906 return false;
2907 }
2908 }
2909 saw_kind
2910 }
2911
2912 /// `true` iff [`Self::preconditions`] carries NO
2913 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2914 /// AND carries at least one [`crate::boundary::Condition`] for
2915 /// every OTHER [`ConditionKind`] — the precondition-side arm of
2916 /// the (precondition, postcondition, condition-union) kind-scoped-
2917 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2918 /// typed delegate to
2919 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2920 /// [`Self::preconditions`].
2921 ///
2922 /// Peer of
2923 /// [`crate::boundary::Boundary::lacks_only_precondition_kind`] on
2924 /// the point-domain surface — both peers compose against the SAME
2925 /// slice-level substrate primitive so a regression at the per-
2926 /// slice fused walk under complement fails at that primitive's
2927 /// tests rather than as silent drift at either struct-level arm.
2928 #[must_use]
2929 pub fn lacks_only_precondition_kind(&self, kind: ConditionKind) -> bool {
2930 self.preconditions.lacks_only_kind(kind)
2931 }
2932
2933 /// `true` iff [`Self::postconditions`] carries NO
2934 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
2935 /// AND carries at least one [`crate::boundary::Condition`] for
2936 /// every OTHER [`ConditionKind`] — the postcondition-side arm of
2937 /// the (precondition, postcondition, condition-union) kind-scoped-
2938 /// strict-refinement-on-missing triad on [`EphemeralSpec`]. Thin
2939 /// typed delegate to
2940 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] over
2941 /// [`Self::postconditions`].
2942 ///
2943 /// Peer of
2944 /// [`crate::boundary::Boundary::lacks_only_postcondition_kind`] on
2945 /// the point-domain surface. See [`Self::lacks_only_precondition_kind`]
2946 /// for the full rationale — the two methods share ONE lift
2947 /// motivation, ONE fail-before-pass-after composition-law pin,
2948 /// and ONE two-surface parity contract with the point-domain
2949 /// [`crate::boundary::Boundary`] kind-scoped-strict-refinement-
2950 /// on-missing peer methods.
2951 #[must_use]
2952 pub fn lacks_only_postcondition_kind(&self, kind: ConditionKind) -> bool {
2953 self.postconditions.lacks_only_kind(kind)
2954 }
2955
2956 /// `true` iff `preconditions ∪ postconditions` carries AT LEAST
2957 /// TWO [`crate::boundary::Condition`] values with the given
2958 /// [`ConditionKind`] — the union arm of the (precondition,
2959 /// postcondition, condition-union) per-kind cardinality "≥ 2"
2960 /// many-arm triad on [`EphemeralSpec`]. Composes a two-step-
2961 /// short-circuit walk over the chained per-kind iterator
2962 /// [`Self::iter_condition_kind`], which itself chains
2963 /// [`crate::boundary::ConditionSliceExt::iter_kind`] over
2964 /// [`Self::preconditions`] then [`Self::postconditions`].
2965 ///
2966 /// Peer of
2967 /// [`crate::boundary::Boundary::has_multiple_of_condition_kind`]
2968 /// on the point-domain surface — both peers compose against the
2969 /// SAME slice-level substrate primitive
2970 /// [`crate::boundary::ConditionSliceExt::has_multiple_of_kind`]
2971 /// via the two-slice chain, so a regression at the per-slice
2972 /// two-step short-circuit walk fails at that primitive's tests
2973 /// rather than as silent drift at either struct-level arm.
2974 #[must_use]
2975 pub fn has_multiple_of_condition_kind(&self, kind: ConditionKind) -> bool {
2976 let mut it = self.iter_condition_kind(kind);
2977 it.next().is_some() && it.next().is_some()
2978 }
2979
2980 /// `true` iff [`Self::preconditions`] carries AT LEAST TWO
2981 /// [`crate::boundary::Condition`] values with the given
2982 /// [`ConditionKind`] — the precondition-side arm of the
2983 /// (precondition, postcondition, condition-union) per-kind
2984 /// cardinality "≥ 2" many-arm triad on [`EphemeralSpec`]. Thin
2985 /// typed delegate to
2986 /// [`crate::boundary::ConditionSliceExt::has_multiple_of_kind`]
2987 /// over [`Self::preconditions`].
2988 ///
2989 /// Peer of
2990 /// [`crate::boundary::Boundary::has_multiple_of_precondition_kind`]
2991 /// on the point-domain surface — both peers compose against the
2992 /// SAME slice-level substrate primitive so a regression at the
2993 /// per-slice two-step short-circuit walk fails at that
2994 /// primitive's tests rather than as silent drift at either
2995 /// struct-level arm.
2996 #[must_use]
2997 pub fn has_multiple_of_precondition_kind(&self, kind: ConditionKind) -> bool {
2998 self.preconditions.has_multiple_of_kind(kind)
2999 }
3000
3001 /// `true` iff [`Self::postconditions`] carries AT LEAST TWO
3002 /// [`crate::boundary::Condition`] values with the given
3003 /// [`ConditionKind`] — the postcondition-side arm of the
3004 /// (precondition, postcondition, condition-union) per-kind
3005 /// cardinality "≥ 2" many-arm triad on [`EphemeralSpec`]. Thin
3006 /// typed delegate to
3007 /// [`crate::boundary::ConditionSliceExt::has_multiple_of_kind`]
3008 /// over [`Self::postconditions`].
3009 ///
3010 /// Peer of
3011 /// [`crate::boundary::Boundary::has_multiple_of_postcondition_kind`]
3012 /// on the point-domain surface. See
3013 /// [`Self::has_multiple_of_precondition_kind`] for the full
3014 /// rationale — the two methods share ONE lift motivation, ONE
3015 /// fail-before-pass-after composition-law pin, and ONE two-
3016 /// surface parity contract with the point-domain
3017 /// [`crate::boundary::Boundary`] per-kind-many-arm peer methods.
3018 #[must_use]
3019 pub fn has_multiple_of_postcondition_kind(&self, kind: ConditionKind) -> bool {
3020 self.postconditions.has_multiple_of_kind(kind)
3021 }
3022
3023 /// `true` iff `preconditions ∪ postconditions` carries EXACTLY
3024 /// ONE [`crate::boundary::Condition`] with the given
3025 /// [`ConditionKind`] — the union arm of the (precondition,
3026 /// postcondition, condition-union) per-kind cardinality "= 1"
3027 /// mid-endpoint triad on [`EphemeralSpec`]. Composes a two-step-
3028 /// short-circuit walk over the chained per-kind iterator
3029 /// [`Self::iter_condition_kind`], which itself chains
3030 /// [`crate::boundary::ConditionSliceExt::iter_kind`] over
3031 /// [`Self::preconditions`] then [`Self::postconditions`].
3032 ///
3033 /// Peer of
3034 /// [`crate::boundary::Boundary::has_unique_of_condition_kind`]
3035 /// on the point-domain surface — both peers compose against the
3036 /// SAME slice-level substrate primitive
3037 /// [`crate::boundary::ConditionSliceExt::has_unique_of_kind`]
3038 /// via the two-slice chain, so a regression at the per-slice
3039 /// two-step short-circuit walk fails at that primitive's tests
3040 /// rather than as silent drift at either struct-level arm.
3041 /// Middle arm of the {= 0, = 1, ≥ 2} per-kind cardinality
3042 /// Boolean trichotomy at the union level; alongside
3043 /// [`Self::lacks_condition_kind`] (= 0) and
3044 /// [`Self::has_multiple_of_condition_kind`] (≥ 2), the three
3045 /// Booleans PARTITION every non-negative multiplicity.
3046 #[must_use]
3047 pub fn has_unique_of_condition_kind(&self, kind: ConditionKind) -> bool {
3048 let mut it = self.iter_condition_kind(kind);
3049 it.next().is_some() && it.next().is_none()
3050 }
3051
3052 /// `true` iff [`Self::preconditions`] carries EXACTLY ONE
3053 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
3054 /// — the precondition-side arm of the (precondition,
3055 /// postcondition, condition-union) per-kind cardinality "= 1"
3056 /// mid-endpoint triad on [`EphemeralSpec`]. Thin typed delegate
3057 /// to [`crate::boundary::ConditionSliceExt::has_unique_of_kind`]
3058 /// over [`Self::preconditions`].
3059 ///
3060 /// Peer of
3061 /// [`crate::boundary::Boundary::has_unique_of_precondition_kind`]
3062 /// on the point-domain surface — both peers compose against the
3063 /// SAME slice-level substrate primitive so a regression at the
3064 /// per-slice two-step short-circuit walk fails at that
3065 /// primitive's tests rather than as silent drift at either
3066 /// struct-level arm.
3067 #[must_use]
3068 pub fn has_unique_of_precondition_kind(&self, kind: ConditionKind) -> bool {
3069 self.preconditions.has_unique_of_kind(kind)
3070 }
3071
3072 /// `true` iff [`Self::postconditions`] carries EXACTLY ONE
3073 /// [`crate::boundary::Condition`] with the given [`ConditionKind`]
3074 /// — the postcondition-side arm of the (precondition,
3075 /// postcondition, condition-union) per-kind cardinality "= 1"
3076 /// mid-endpoint triad on [`EphemeralSpec`]. Thin typed delegate
3077 /// to [`crate::boundary::ConditionSliceExt::has_unique_of_kind`]
3078 /// over [`Self::postconditions`].
3079 ///
3080 /// Peer of
3081 /// [`crate::boundary::Boundary::has_unique_of_postcondition_kind`]
3082 /// on the point-domain surface. See
3083 /// [`Self::has_unique_of_precondition_kind`] for the full
3084 /// rationale — the two methods share ONE lift motivation, ONE
3085 /// fail-before-pass-after composition-law pin, and ONE two-
3086 /// surface parity contract with the point-domain
3087 /// [`crate::boundary::Boundary`] per-kind-mid-endpoint peer
3088 /// methods.
3089 #[must_use]
3090 pub fn has_unique_of_postcondition_kind(&self, kind: ConditionKind) -> bool {
3091 self.postconditions.has_unique_of_kind(kind)
3092 }
3093
3094 /// `true` iff `preconditions ∪ postconditions` carries AT MOST
3095 /// ONE [`crate::boundary::Condition`] with the given
3096 /// [`ConditionKind`] — the union arm of the (precondition,
3097 /// postcondition, condition-union) per-kind cardinality "≤ 1"
3098 /// negation triad on [`EphemeralSpec`]. Closes the {= 0, = 1,
3099 /// ≥ 1, ≥ 2, ≤ 1} Boolean-cardinality grid on the per-kind axis
3100 /// at the union level on the ephemeral sugar surface alongside
3101 /// its sibling [`Self::has_multiple_of_condition_kind`] (≥ 2
3102 /// many-arm) under the definitional negation
3103 /// `!(≥ 2) == (≤ 1)`. Composes against the chained per-kind
3104 /// iterator [`Self::iter_condition_kind`] via the definitional
3105 /// negation `!self.has_multiple_of_condition_kind(kind)`.
3106 ///
3107 /// Peer of
3108 /// [`crate::boundary::Boundary::has_at_most_one_of_condition_kind`]
3109 /// on the point-domain surface — both peers compose against the
3110 /// SAME slice-level substrate primitive
3111 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_of_kind`]
3112 /// via the two-slice chain, so a regression at the per-slice
3113 /// definitional-negation walk fails at that primitive's tests
3114 /// rather than as silent drift at either struct-level arm.
3115 /// Trichotomy-union arm of the per-kind Boolean tetrachotomy
3116 /// on the ephemeral union: alongside `lacks_condition_kind`
3117 /// (= 0) and `has_unique_of_condition_kind` (= 1),
3118 /// `has_at_most_one_of_condition_kind` equals their disjunction
3119 /// (`lacks ∨ has_unique`) on every arm, byte-for-byte with
3120 /// `!has_multiple_of_condition_kind`.
3121 #[must_use]
3122 pub fn has_at_most_one_of_condition_kind(&self, kind: ConditionKind) -> bool {
3123 !self.has_multiple_of_condition_kind(kind)
3124 }
3125
3126 /// `true` iff [`Self::preconditions`] carries AT MOST ONE
3127 /// [`crate::boundary::Condition`] with the given
3128 /// [`ConditionKind`] — the precondition-side arm of the
3129 /// (precondition, postcondition, condition-union) per-kind
3130 /// cardinality "≤ 1" negation triad on [`EphemeralSpec`]. Thin
3131 /// typed delegate to
3132 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_of_kind`]
3133 /// over [`Self::preconditions`].
3134 ///
3135 /// Peer of
3136 /// [`crate::boundary::Boundary::has_at_most_one_of_precondition_kind`]
3137 /// on the point-domain surface — both peers compose against the
3138 /// SAME slice-level substrate primitive so a regression at the
3139 /// per-slice definitional-negation walk fails at that
3140 /// primitive's tests rather than as silent drift at either
3141 /// struct-level arm.
3142 #[must_use]
3143 pub fn has_at_most_one_of_precondition_kind(&self, kind: ConditionKind) -> bool {
3144 self.preconditions.has_at_most_one_of_kind(kind)
3145 }
3146
3147 /// `true` iff [`Self::postconditions`] carries AT MOST ONE
3148 /// [`crate::boundary::Condition`] with the given
3149 /// [`ConditionKind`] — the postcondition-side arm of the
3150 /// (precondition, postcondition, condition-union) per-kind
3151 /// cardinality "≤ 1" negation triad on [`EphemeralSpec`]. Thin
3152 /// typed delegate to
3153 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_of_kind`]
3154 /// over [`Self::postconditions`].
3155 ///
3156 /// Peer of
3157 /// [`crate::boundary::Boundary::has_at_most_one_of_postcondition_kind`]
3158 /// on the point-domain surface. See
3159 /// [`Self::has_at_most_one_of_precondition_kind`] for the full
3160 /// rationale — the two methods share ONE lift motivation, ONE
3161 /// fail-before-pass-after composition-law pin, and ONE two-
3162 /// surface parity contract with the point-domain
3163 /// [`crate::boundary::Boundary`] per-kind-"≤ 1" peer methods.
3164 #[must_use]
3165 pub fn has_at_most_one_of_postcondition_kind(&self, kind: ConditionKind) -> bool {
3166 self.postconditions.has_at_most_one_of_kind(kind)
3167 }
3168
3169 /// True iff this ephemeral spec's stored [`TeardownPolicy`] equals
3170 /// `kind` — the substrate primitive that owns the
3171 /// (`&EphemeralSpec`, [`TeardownPolicy`]) → `bool` presence-probe
3172 /// shape on the sugar-surface type.
3173 ///
3174 /// # Peer to [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
3175 ///
3176 /// [`EphemeralLifetime::has_teardown_policy`] carries the same
3177 /// `(&self, TeardownPolicy) -> bool` signature on the point-surface
3178 /// carrier ([`ProcessSpec`]'s nested [`crate::lifetime::Lifetime`]
3179 /// slot reached through
3180 /// [`crate::lifetime::Lifetime::resolved_ephemeral`]); this peer
3181 /// composes byte-identical `==` semantics on
3182 /// [`EphemeralSpec`]'s direct `teardown: TeardownPolicy` scalar
3183 /// slot, so both surfaces' `teardown-policy-<kind>` require-tag
3184 /// families ([`crate::lifetime::EphemeralLifetime::has_teardown_policy`]
3185 /// on the point surface, this peer on the ephemeral surface) route
3186 /// through the SAME scalar `==` shape. A future normalization at
3187 /// the probe shape (a widened return carrying a `TerminatePolicy`
3188 /// disambiguator, a debug-build assertion on operator-set vs
3189 /// defaulted overrides, a fleet-wide warn on `Never` combined with
3190 /// short TTLs) lands at ONE site per surface and every downstream
3191 /// `teardown-policy-<kind>` require-tag family + closed-set audit
3192 /// dispatcher picks it up mechanically.
3193 ///
3194 /// # Semantics — VARIANT match, not POPULATED slot
3195 ///
3196 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
3197 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
3198 /// absent state to detect. `has_teardown_policy(kind)` returns
3199 /// `true` iff `self.teardown == kind`. On a hand-authored
3200 /// [`EphemeralSpec`] that omits `:teardown` from the
3201 /// `(defephemeral …)` form (or a Rust builder that reaches
3202 /// [`TeardownPolicy::default`]) the probe returns `true` for
3203 /// [`TeardownPolicy::Always`] and `false` for every other variant
3204 /// — distinct from the Option-slot axis where a default carrier
3205 /// returns `false` for EVERY kind. An operator who left
3206 /// `:teardown` at the substrate default IS configured for
3207 /// `Always`, and a `:requires (teardown-policy-Always)` check
3208 /// should pass; only an operator who deliberately overrode the
3209 /// policy to `OnAttested` / `OnFailed` / `Never` fails the tag on
3210 /// this axis.
3211 ///
3212 /// # Corner — (required-scalar-child)
3213 ///
3214 /// Fresh corner on the ephemeral surface's presence-probe algebra:
3215 /// [`EphemeralSpec`] has no Option-parent hop between the sugar
3216 /// struct and the `teardown` scalar (the point surface reaches
3217 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
3218 /// through the Option-parent `resolved_ephemeral()` gate), so the
3219 /// probe body is a bare scalar `==` on a required field. Distinct
3220 /// from [`Self::has_condition_kind`] on this same surface, which
3221 /// walks a `Vec<Condition>` slice-child.
3222 ///
3223 /// # Compounding
3224 ///
3225 /// The ephemeral require-tag classifier composes this primitive
3226 /// with the closed-set `FromStr` autoderived on [`TeardownPolicy`]
3227 /// through the `strip_and_classify_prefixed_kind` substrate to
3228 /// publish a `teardown-policy-<kind>` prefix family byte-for-byte
3229 /// symmetrical with the point surface's family via
3230 /// [`crate::lifetime::EphemeralLifetime::has_teardown_policy`]. A
3231 /// future fifth [`TeardownPolicy`] variant added to `ALL` (a
3232 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
3233 /// reaches BOTH surfaces' `teardown-policy-<kind>` prefix families
3234 /// through the SAME closed-set walk with no per-caller edit — the
3235 /// two-surface symmetry means adding a variant on the closed set
3236 /// publishes it in lockstep across every downstream consumer.
3237 ///
3238 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
3239 /// preserves proofs — the scalar-carrier presence-probe body lives
3240 /// at ONE substrate site per surface so every downstream
3241 /// (`teardown-policy-<kind>` require-tag families on both surfaces
3242 /// in tatara-check, closed-set audit dispatchers, future variant
3243 /// additions on [`TeardownPolicy`]) binds through the SAME
3244 /// `has(kind)` shape rather than restating the `<eph>.teardown ==
3245 /// kind` closure body at each call site). THEORY.md §VI.1
3246 /// (generation over composition — a future variant lands at ONE
3247 /// `ALL` entry + one `as_str` arm on the closed set and the probe
3248 /// picks it up mechanically without further per-consumer edits).
3249 #[must_use]
3250 pub fn has_teardown_policy(&self, kind: TeardownPolicy) -> bool {
3251 self.teardown == kind
3252 }
3253
3254 /// Derived-bool-predicate presence probe on the stored
3255 /// [`Self::teardown`] slot — `true` iff this ephemeral sugar's
3256 /// [`TeardownPolicy`] would auto-SIGTERM the Process on the
3257 /// queried [`ProcessPhase`] transition (as read through
3258 /// [`TeardownPolicy::should_teardown_on`]).
3259 ///
3260 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
3261 ///
3262 /// Same shape, same axis, one refinement lower: the point-surface
3263 /// peer on [`crate::lifetime::EphemeralLifetime`] composes the SAME
3264 /// [`TeardownPolicy::should_teardown_on`] predicate against the
3265 /// SAME stored `teardown_policy` slot; this method composes the
3266 /// same predicate against the sugar surface's flattened
3267 /// [`Self::teardown`] slot. Both bodies delegate to the ONE
3268 /// substrate owner [`TeardownPolicy::should_teardown_on`], so a
3269 /// regression at the (policy, phase) → bool truth table surfaces
3270 /// at THAT primitive's tests rather than as silent drift at
3271 /// either struct-level caller.
3272 ///
3273 /// # Corner — (required-scalar-parent × derived-bool-predicate-child)
3274 ///
3275 /// [`EphemeralSpec::teardown`] is a required, defaulted scalar
3276 /// ([`TeardownPolicy::Always`] via `#[default]`); there is no
3277 /// Option-parent hop between the sugar struct and the `teardown`
3278 /// scalar (the point surface reaches
3279 /// [`crate::lifetime::EphemeralLifetime::teardown_policy`]
3280 /// through the Option-parent `resolved_ephemeral()` gate). The
3281 /// probe body is a bare predicate application on a required
3282 /// field. Distinct from [`Self::has_teardown_policy`] on this
3283 /// same surface, which reads the raw stored variant for equality
3284 /// (`self.teardown == kind`) rather than the derived firing-arm
3285 /// predicate against a [`ProcessPhase`] argument.
3286 ///
3287 /// # Compounding
3288 ///
3289 /// The ephemeral require-tag classifier composes this primitive
3290 /// with the closed-set [`crate::phase::ProcessPhase`]'s
3291 /// autoderived `FromStr` through the
3292 /// `strip_and_classify_prefixed_kind` substrate to publish a
3293 /// `teardown-fires-on-<phase>` prefix family byte-for-byte
3294 /// symmetrical with the point surface's family via
3295 /// [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`].
3296 /// A future fifth [`TeardownPolicy`] variant added to `ALL` (a
3297 /// hypothetical `OnTimeout` for "tear down only on TTL expiry")
3298 /// reaches BOTH surfaces' `teardown-fires-on-<phase>` prefix
3299 /// families through the SAME
3300 /// [`TeardownPolicy::should_teardown_on`] match with no per-
3301 /// caller edit — the two-surface symmetry means adding a variant
3302 /// on the closed set publishes it in lockstep across every
3303 /// downstream consumer.
3304 ///
3305 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
3306 /// preserves proofs — the derived-bool-predicate presence-probe
3307 /// body lives at ONE substrate site per surface, both composing
3308 /// the SAME [`TeardownPolicy::should_teardown_on`] projection, so
3309 /// every downstream (`teardown-fires-on-<phase>` require-tag
3310 /// families on both surfaces in tatara-check, closed-set audit
3311 /// dispatchers, future variant additions on either
3312 /// [`TeardownPolicy`] or [`crate::phase::ProcessPhase`]) binds
3313 /// through the SAME `has_teardown_firing_on(phase)` shape rather
3314 /// than restating the `<eph>.teardown.should_teardown_on(phase)`
3315 /// closure body at each call site). THEORY.md §VI.1 (generation
3316 /// over composition — a future variant lands at ONE `ALL` entry +
3317 /// one `as_str` arm + one `should_teardown_on` arm on the closed
3318 /// set and the probe picks it up mechanically without further
3319 /// per-consumer edits).
3320 #[must_use]
3321 pub const fn has_teardown_firing_on(&self, phase: ProcessPhase) -> bool {
3322 self.teardown.should_teardown_on(phase)
3323 }
3324
3325 /// Resolve the operator-authored [`Self::classification`] slot to
3326 /// the concrete [`Classification`] the point surface sees, filling
3327 /// `None` through the same [`default_ephemeral_class`] baseline the
3328 /// `From<EphemeralSpec> for ProcessSpec` lowering uses when the
3329 /// operator omits `:classification` from the `(defephemeral …)`
3330 /// form. Returns [`Cow::Borrowed`] on the populated arm (zero
3331 /// allocation), else [`Cow::Owned`] with the workspace-baseline
3332 /// `(Gate, Compute, Bounded, Monotone, Internal)` value the sibling
3333 /// primitive [`Classification::gate_compute`] owns.
3334 ///
3335 /// # ONE substrate primitive for `Option<Classification>` resolution
3336 ///
3337 /// This is the ONE `EphemeralSpec`-inherent primitive that owns the
3338 /// `Option<Classification>` → resolved-[`Classification`] walk.
3339 /// Every downstream classification-axis presence probe on the
3340 /// [`EphemeralSpec`] surface ([`Self::has_point_type`],
3341 /// [`Self::has_substrate`], [`Self::has_calm`],
3342 /// [`Self::has_data_classification`], [`Self::has_horizon_kind`],
3343 /// [`Self::has_optimization_direction`], [`Self::has_input_arity`],
3344 /// [`Self::has_output_arity`]) routes through THIS
3345 /// primitive so the "`None` fills through
3346 /// [`default_ephemeral_class`]" resolution lives at ONE site rather
3347 /// than being restated in each per-axis probe body. A future
3348 /// regression on the fill-through (a shift from the `(Gate,
3349 /// Compute, …)` baseline to a different `default_ephemeral_class`
3350 /// body, a shift from the `Option`-carrier shape to a
3351 /// serde-defaulted required-field carrier, an eventual audit hook
3352 /// naming the resolved-vs-authored provenance) lands at ONE site
3353 /// and every downstream axis-probe on the ephemeral surface picks
3354 /// it up mechanically.
3355 ///
3356 /// # Sibling to the `From<EphemeralSpec>` lowering
3357 ///
3358 /// The lowering `From<EphemeralSpec> for ProcessSpec` fills
3359 /// [`ProcessSpec::classification`] through the SAME
3360 /// `.unwrap_or_else(default_ephemeral_class)` walk that this
3361 /// primitive owns on the borrow-friendly `Cow` return. Both sites
3362 /// resolve the same operator-authored slot through the same default
3363 /// so a future two-surface parity contract on the classification
3364 /// axes (`point-type-<kind>` on both surfaces, `substrate-<kind>`
3365 /// on both surfaces, …) reads identically through the sibling
3366 /// point-surface probe [`Classification::has_<axis>`] on the
3367 /// lowered `ProcessSpec` and through THIS primitive on the same
3368 /// authored [`EphemeralSpec`].
3369 ///
3370 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3371 /// preserves proofs; the `Option<Classification>` resolution body
3372 /// lives at ONE substrate primitive on the ephemeral surface so
3373 /// every downstream classification-axis probe binds through the
3374 /// SAME `resolved_classification()` shape rather than restating
3375 /// the `self.classification.as_ref().unwrap_or(&default_…)`
3376 /// closure body at each callsite. THEORY.md §VI.1 — generation
3377 /// over composition; a future classification-axis peer
3378 /// (`has_substrate`, `has_calm`, …) lands as ONE inherent method
3379 /// that delegates through the resolver's `has_<axis>(kind)` call
3380 /// on the sibling [`Classification`] closed-set primitive with no
3381 /// per-axis restatement of the fill-through logic.
3382 #[must_use]
3383 pub fn resolved_classification(&self) -> Cow<'_, Classification> {
3384 match &self.classification {
3385 Some(c) => Cow::Borrowed(c),
3386 None => Cow::Owned(default_ephemeral_class()),
3387 }
3388 }
3389
3390 /// Overlay a single [`ClassificationAxis`] variant onto this
3391 /// ephemeral spec's authored [`Self::classification`] slot, filling
3392 /// `None` through [`Classification::gate_compute`] before the
3393 /// overlay so the resulting slot carries `Some(_)` regardless of
3394 /// the pre-call state. Fluent chaining primitive: the peer of
3395 /// [`ProcessSpec::gate_compute_with_axis`] (fresh-spec × axis
3396 /// overlay) and [`Classification::with_axis`] (arbitrary-base ×
3397 /// axis overlay) on the ephemeral sugar surface.
3398 ///
3399 /// # Substrate ergonomics
3400 ///
3401 /// Pre-lift the four-line shape `let mut classification =
3402 /// Classification::gate_compute(); classification.<axis> =
3403 /// populated; let spec = EphemeralSpec { classification:
3404 /// Some(classification), ..ephemeral_fixture() };` (and its newer
3405 /// three-line peer `let classification =
3406 /// Classification::gate_compute_with_axis(populated); let spec =
3407 /// EphemeralSpec { classification: Some(classification),
3408 /// ..ephemeral_fixture() };`) recurred at THIRTY-SIX hand-authored
3409 /// callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger
3410 /// inside `tatara-reconciler::bin::tatara-check`'s
3411 /// `evaluate_ephemeral_require_tag_*` classifier-facing test
3412 /// module. Post-lift each callsite reads
3413 /// `let spec = ephemeral_fixture().with_classification_axis(populated);`
3414 /// — one line, one immutable binding, and every per-axis loop
3415 /// dispatches its per-iteration axis mutation through the SAME
3416 /// [`ClassificationAxis::overlay`] trait rather than by directly
3417 /// poking a `classification.<axis>` field or restating the
3418 /// `Some(_)` wrap.
3419 ///
3420 /// # Fluent chaining semantics
3421 ///
3422 /// * `EphemeralSpec { classification: None, .. }
3423 /// .with_classification_axis(axis)` produces
3424 /// `EphemeralSpec { classification:
3425 /// Some(Classification::gate_compute_with_axis(axis)), .. }` —
3426 /// the `None`-arm short-circuit fills through
3427 /// [`Classification::gate_compute`] identically to the sibling
3428 /// [`Self::resolved_classification`] resolver on the read side.
3429 /// * `EphemeralSpec { classification: Some(prior), .. }
3430 /// .with_classification_axis(axis)` produces
3431 /// `EphemeralSpec { classification: Some(prior.with_axis(axis)),
3432 /// .. }` — the axis overlay composes onto the existing carrier
3433 /// via [`ClassificationAxis::overlay`], preserving every other
3434 /// axis slot on `prior`. Chained calls
3435 /// `.with_classification_axis(a).with_classification_axis(b)`
3436 /// compose arbitrary N-axis conjunctions on the ephemeral
3437 /// sugar surface with the same order-independence guarantee
3438 /// [`Classification::with_axis`] carries on distinct-slot axes.
3439 ///
3440 /// # Sibling to [`ProcessSpec::gate_compute_with_axis`]
3441 ///
3442 /// Same (spec-carrier × axis) shape, one refinement lower on
3443 /// the composition-depth axis: `ProcessSpec::gate_compute_with_axis`
3444 /// owns the (fresh-`gate_compute_defaults`-spec × axis-overlay)
3445 /// construction on the point-surface carrier;
3446 /// [`Self::with_classification_axis`] owns the
3447 /// (arbitrary-`EphemeralSpec` × axis-overlay-onto-authored-classification)
3448 /// construction on the ephemeral sugar-surface carrier. Both
3449 /// primitives compose through the SAME
3450 /// [`ClassificationAxis::overlay`] trait so a regression on any
3451 /// axis's overlay surfaces at both composer owners' pin sets
3452 /// simultaneously.
3453 ///
3454 /// # Compounding
3455 ///
3456 /// A future SIXTH classification axis lands as ONE peer
3457 /// `impl ClassificationAxis` — every ephemeral-surface fixture
3458 /// that binds through this primitive picks up the sixth axis
3459 /// mechanically without a `classification.<new-axis> = value;`
3460 /// restatement per site. A future audit dispatcher walking the
3461 /// (ephemeral-surface × axis-loop) shape (per-axis matrix
3462 /// generator, closed-set-sweep sagas, per-axis-XOR-partition-
3463 /// witness synthesis on the ephemeral side) binds through the
3464 /// SAME composer regardless of which axis it targets. Directly
3465 /// benefits the P1 caixa-tatara renderer target
3466 /// (`(defaplicacao …)` → `Process` mechanical lowering test
3467 /// fixtures that construct authored classifications through the
3468 /// ephemeral sugar surface) and future ephemeral-surface XOR-
3469 /// partition landmark tests peer to the point-surface pins in
3470 /// `tatara-check.rs`.
3471 ///
3472 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3473 /// preserves proofs; the [`ClassificationAxis::overlay`] trait
3474 /// owns the axis-dispatch proof at ONE site and this primitive
3475 /// extends the ONE-site guarantee to the (ephemeral-spec ×
3476 /// authored-classification × axis-overlay) construction shape.
3477 /// THEORY.md §VI.1 — generation over composition; the 3-to-4-line
3478 /// hand-authored classification-then-wrap shape recurred at ≥ 36
3479 /// hand-authored callsites past the ★★ PRIME-DIRECTIVE ≥ 2
3480 /// duplication threshold and is lifted onto ONE substrate owner
3481 /// here.
3482 #[must_use]
3483 pub fn with_classification_axis<A: ClassificationAxis>(mut self, axis: A) -> Self {
3484 let mut c = self
3485 .classification
3486 .take()
3487 .unwrap_or_else(Classification::gate_compute);
3488 axis.overlay(&mut c);
3489 self.classification = Some(c);
3490 self
3491 }
3492
3493 /// True iff the resolved [`Classification`] carries the given
3494 /// [`ConvergencePointType`] on its `point_type` slot — byte-for-
3495 /// byte peer of [`Classification::has_point_type`] wrapped through
3496 /// the [`Self::resolved_classification`] resolver so an
3497 /// operator-omitted `:classification` slot reads as the
3498 /// [`default_ephemeral_class`] baseline the sibling
3499 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3500 ///
3501 /// # Two-surface parity contract
3502 ///
3503 /// A given [`EphemeralSpec`] classifies identically through this
3504 /// primitive AND through
3505 /// `<eph.clone().into::<ProcessSpec>>().classification.has_point_type(kind)`
3506 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3507 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3508 /// the lowering side both dereference the same
3509 /// `default_ephemeral_class()` value on `None` and the same
3510 /// authored value on `Some(_)`. This means the ephemeral-surface
3511 /// `point-type-<kind>` `:requires` family in
3512 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3513 /// truth on the SAME authored spec as the point-surface family
3514 /// on the mechanically-lowered `ProcessSpec`.
3515 ///
3516 /// # Sibling to the seven other classification axes
3517 ///
3518 /// FIRST classification-axis peer on the [`EphemeralSpec`]
3519 /// surface. Six future sibling axes on the SAME `Cow`-resolver
3520 /// carrier ([`Self::has_substrate`] opened the SECOND,
3521 /// [`Self::has_calm`] the THIRD,
3522 /// [`Self::has_data_classification`] the FOURTH,
3523 /// [`Self::has_horizon_kind`] the FIFTH,
3524 /// [`Self::has_optimization_direction`] the SIXTH; then
3525 /// `has_input_arity`, `has_output_arity`) land as one-line
3526 /// wrappers around the SAME resolver + the sibling
3527 /// [`Classification`] closed-set primitive, so a future variant
3528 /// added to [`ConvergencePointType`] (or any of the seven other
3529 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3530 /// families through the SAME closed-set walk with no per-caller
3531 /// edit.
3532 ///
3533 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3534 /// preserves proofs; the classification-axis presence-probe body
3535 /// composes ONE resolver primitive
3536 /// ([`Self::resolved_classification`]) with ONE closed-set
3537 /// primitive ([`Classification::has_point_type`]) so every
3538 /// downstream (`point-type-<kind>` require-tag families on both
3539 /// surfaces in tatara-check, closed-set audit dispatchers, future
3540 /// variant additions on [`ConvergencePointType`]) binds through
3541 /// the SAME `has(kind)` shape rather than restating either the
3542 /// resolver walk or the closed-set equality at the callsite.
3543 #[must_use]
3544 pub fn has_point_type(&self, kind: ConvergencePointType) -> bool {
3545 self.resolved_classification().has_point_type(kind)
3546 }
3547
3548 /// True iff the resolved [`Classification`] carries the given
3549 /// [`SubstrateType`] on its `substrate` slot — byte-for-byte peer
3550 /// of [`Classification::has_substrate`] wrapped through the
3551 /// [`Self::resolved_classification`] resolver so an operator-
3552 /// omitted `:classification` slot reads as the
3553 /// [`default_ephemeral_class`] baseline the sibling
3554 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3555 ///
3556 /// # Two-surface parity contract
3557 ///
3558 /// A given [`EphemeralSpec`] classifies identically through this
3559 /// primitive AND through
3560 /// `<eph.clone().into::<ProcessSpec>>().classification.has_substrate(kind)`
3561 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3562 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3563 /// the lowering side both dereference the same
3564 /// `default_ephemeral_class()` value on `None` and the same
3565 /// authored value on `Some(_)`. This means the ephemeral-surface
3566 /// `substrate-<kind>` `:requires` family in
3567 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3568 /// truth on the SAME authored spec as the point-surface family
3569 /// on the mechanically-lowered `ProcessSpec`.
3570 ///
3571 /// # SECOND classification-axis peer on the ephemeral surface
3572 ///
3573 /// Peer of [`Self::has_point_type`] — both route through the SAME
3574 /// [`Self::resolved_classification`] resolver, so the operator-
3575 /// omitted `:classification` slot's fill-through logic lives at
3576 /// ONE substrate primitive rather than being restated in each
3577 /// per-axis probe body. Five future sibling axes on the SAME
3578 /// `Cow`-resolver carrier ([`Self::has_calm`] opened the THIRD,
3579 /// [`Self::has_data_classification`] the FOURTH,
3580 /// [`Self::has_horizon_kind`] the FIFTH,
3581 /// [`Self::has_optimization_direction`] the SIXTH; then
3582 /// `has_input_arity`, `has_output_arity`) land as one-line
3583 /// wrappers around the SAME resolver + the sibling
3584 /// [`Classification`] closed-set primitive, so a future variant
3585 /// added to [`SubstrateType`] (or any of the six other closed
3586 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3587 /// through the SAME closed-set walk with no per-caller edit.
3588 ///
3589 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3590 /// preserves proofs; the classification-axis presence-probe body
3591 /// composes ONE resolver primitive
3592 /// ([`Self::resolved_classification`]) with ONE closed-set
3593 /// primitive ([`Classification::has_substrate`]) so every
3594 /// downstream (`substrate-<kind>` require-tag families on both
3595 /// surfaces in tatara-check, closed-set audit dispatchers, future
3596 /// variant additions on [`SubstrateType`]) binds through the
3597 /// SAME `has(kind)` shape rather than restating either the
3598 /// resolver walk or the closed-set equality at the callsite.
3599 #[must_use]
3600 pub fn has_substrate(&self, kind: SubstrateType) -> bool {
3601 self.resolved_classification().has_substrate(kind)
3602 }
3603
3604 /// True iff the resolved [`Classification`] carries the given
3605 /// [`CalmClassification`] on its `calm` slot — byte-for-byte peer
3606 /// of [`Classification::has_calm`] wrapped through the
3607 /// [`Self::resolved_classification`] resolver so an operator-
3608 /// omitted `:classification` slot reads as the
3609 /// [`default_ephemeral_class`] baseline the sibling
3610 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3611 ///
3612 /// # Two-surface parity contract
3613 ///
3614 /// A given [`EphemeralSpec`] classifies identically through this
3615 /// primitive AND through
3616 /// `<eph.clone().into::<ProcessSpec>>().classification.has_calm(kind)`
3617 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3618 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3619 /// the lowering side both dereference the same
3620 /// `default_ephemeral_class()` value on `None` and the same
3621 /// authored value on `Some(_)`. This means the ephemeral-surface
3622 /// `calm-<kind>` `:requires` family in
3623 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3624 /// truth on the SAME authored spec as the point-surface family
3625 /// on the mechanically-lowered `ProcessSpec`.
3626 ///
3627 /// # THIRD classification-axis peer on the ephemeral surface
3628 ///
3629 /// Peer of [`Self::has_point_type`] and [`Self::has_substrate`] —
3630 /// all three route through the SAME
3631 /// [`Self::resolved_classification`] resolver, so the operator-
3632 /// omitted `:classification` slot's fill-through logic lives at
3633 /// ONE substrate primitive rather than being restated in each
3634 /// per-axis probe body. FIRST occupant on the (Option-parent ×
3635 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3636 /// of the ephemeral-surface presence-probe algebra — distinct
3637 /// from the (Option-parent × NON-DEFAULT-scalar-child) corner
3638 /// the first two classification-axis peers opened, since
3639 /// [`CalmClassification`] carries `#[default] = Monotone` on the
3640 /// closed set. The default-arm short-circuit on the absent-
3641 /// classification arm reads `true` on the [`CalmClassification`]
3642 /// child's `#[default]` variant precisely because BOTH the parent
3643 /// Option's fill-through baseline (`default_ephemeral_class`) AND
3644 /// the child's own `#[default]` land on the SAME variant
3645 /// ([`CalmClassification::Monotone`]) — a two-defaults
3646 /// composition property distinct from the NON-DEFAULT-scalar
3647 /// peers, whose absent-classification arm defaults through a
3648 /// specific chosen baseline (`ConvergencePointType::Gate`,
3649 /// `SubstrateType::Compute`) rather than through the child's own
3650 /// `#[default]`. Four future sibling axes on the SAME
3651 /// `Cow`-resolver carrier ([`Self::has_data_classification`]
3652 /// opened the FOURTH, [`Self::has_horizon_kind`] the FIFTH,
3653 /// [`Self::has_optimization_direction`] the SIXTH; then
3654 /// `has_input_arity`, `has_output_arity`) land as one-line
3655 /// wrappers around the SAME resolver + the sibling
3656 /// [`Classification`] closed-set primitive, so a future variant
3657 /// added to [`CalmClassification`] (or any of the five other
3658 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3659 /// families through the SAME closed-set walk with no per-caller
3660 /// edit.
3661 ///
3662 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3663 /// preserves proofs; the classification-axis presence-probe body
3664 /// composes ONE resolver primitive
3665 /// ([`Self::resolved_classification`]) with ONE closed-set
3666 /// primitive ([`Classification::has_calm`]) so every downstream
3667 /// (`calm-<kind>` require-tag families on both surfaces in
3668 /// tatara-check, closed-set audit dispatchers, future variant
3669 /// additions on [`CalmClassification`]) binds through the SAME
3670 /// `has(kind)` shape rather than restating either the resolver
3671 /// walk or the closed-set equality at the callsite.
3672 #[must_use]
3673 pub fn has_calm(&self, kind: CalmClassification) -> bool {
3674 self.resolved_classification().has_calm(kind)
3675 }
3676
3677 /// True iff the resolved [`Classification`] carries the given
3678 /// [`DataClassification`] on its `data_classification` slot —
3679 /// byte-for-byte peer of [`Classification::has_data_classification`]
3680 /// wrapped through the [`Self::resolved_classification`] resolver
3681 /// so an operator-omitted `:classification` slot reads as the
3682 /// [`default_ephemeral_class`] baseline the sibling
3683 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3684 ///
3685 /// # Two-surface parity contract
3686 ///
3687 /// A given [`EphemeralSpec`] classifies identically through this
3688 /// primitive AND through
3689 /// `<eph.clone().into::<ProcessSpec>>().classification.has_data_classification(kind)`
3690 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3691 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3692 /// the lowering side both dereference the same
3693 /// `default_ephemeral_class()` value on `None` and the same
3694 /// authored value on `Some(_)`. This means the ephemeral-surface
3695 /// `data-classification-<kind>` `:requires` family in
3696 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3697 /// truth on the SAME authored spec as the point-surface family
3698 /// on the mechanically-lowered `ProcessSpec`.
3699 ///
3700 /// # FOURTH classification-axis peer on the ephemeral surface
3701 ///
3702 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`], and
3703 /// [`Self::has_calm`] — all four route through the SAME
3704 /// [`Self::resolved_classification`] resolver, so the operator-
3705 /// omitted `:classification` slot's fill-through logic lives at
3706 /// ONE substrate primitive rather than being restated in each
3707 /// per-axis probe body. SECOND occupant on the (Option-parent ×
3708 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner
3709 /// of the ephemeral-surface presence-probe algebra alongside
3710 /// [`Self::has_calm`] — both probe REQUIRED [`Classification`]
3711 /// sub-slots whose child closed set carries its own `#[default]`
3712 /// ([`DataClassification::Internal`] here,
3713 /// [`CalmClassification::Monotone`] on the peer), so the
3714 /// default-arm short-circuit on the absent-classification arm
3715 /// reads `true` on the [`DataClassification`] child's
3716 /// `#[default]` variant precisely because BOTH the parent
3717 /// Option's fill-through baseline (`default_ephemeral_class`)
3718 /// AND the child's own `#[default]` land on the SAME variant
3719 /// ([`DataClassification::Internal`]). The two-defaults
3720 /// composition property now walks TWO independent defaulted-
3721 /// scalar-child slots on the SAME ephemeral resolver — a
3722 /// regression that promoted a different [`DataClassification`]
3723 /// variant to `#[default]` (or wired the arm to a fixed variant
3724 /// answer) fails HERE at ONE narrow substrate site before
3725 /// drifting through every unadorned ephemeral spec's baseline
3726 /// data-classification answer. Distinct from the FIRST + SECOND
3727 /// peers on the (Option-parent × NON-DEFAULT-scalar-child)
3728 /// corner, whose absent-classification arm defaults through a
3729 /// specific chosen baseline (`ConvergencePointType::Gate`,
3730 /// `SubstrateType::Compute`) rather than through the child's own
3731 /// `#[default]`. Four future sibling axes on the SAME
3732 /// `Cow`-resolver carrier ([`Self::has_horizon_kind`] opened the
3733 /// FIFTH, [`Self::has_optimization_direction`] the SIXTH; then
3734 /// `has_input_arity`, `has_output_arity`) land as one-line
3735 /// wrappers around the SAME resolver + the sibling
3736 /// [`Classification`] closed-set primitive, so a future variant
3737 /// added to [`DataClassification`] (or any of the four other
3738 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3739 /// families through the SAME closed-set walk with no per-caller
3740 /// edit.
3741 ///
3742 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3743 /// preserves proofs; the classification-axis presence-probe body
3744 /// composes ONE resolver primitive
3745 /// ([`Self::resolved_classification`]) with ONE closed-set
3746 /// primitive ([`Classification::has_data_classification`]) so
3747 /// every downstream (`data-classification-<kind>` require-tag
3748 /// families on both surfaces in tatara-check, closed-set audit
3749 /// dispatchers, future variant additions on
3750 /// [`DataClassification`]) binds through the SAME `has(kind)`
3751 /// shape rather than restating either the resolver walk or the
3752 /// closed-set equality at the callsite.
3753 #[must_use]
3754 pub fn has_data_classification(&self, kind: DataClassification) -> bool {
3755 self.resolved_classification().has_data_classification(kind)
3756 }
3757
3758 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3759 /// carries the given [`HorizonKind`] discriminator on its
3760 /// `horizon.kind` slot — byte-for-byte peer of
3761 /// [`Classification::has_horizon_kind`] wrapped through the
3762 /// [`Self::resolved_classification`] resolver so an operator-
3763 /// omitted `:classification` slot reads as the
3764 /// [`default_ephemeral_class`] baseline the sibling
3765 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3766 ///
3767 /// # Two-surface parity contract
3768 ///
3769 /// A given [`EphemeralSpec`] classifies identically through this
3770 /// primitive AND through
3771 /// `<eph.clone().into::<ProcessSpec>>().classification.has_horizon_kind(kind)`
3772 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3773 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3774 /// the lowering side both dereference the same
3775 /// `default_ephemeral_class()` value on `None` and the same
3776 /// authored value on `Some(_)`. This means the ephemeral-surface
3777 /// `horizon-<kind>` `:requires` family in
3778 /// `tatara-reconciler::bin::tatara-check` publishes the SAME
3779 /// truth on the SAME authored spec as the point-surface family
3780 /// on the mechanically-lowered `ProcessSpec`.
3781 ///
3782 /// # FIFTH classification-axis peer on the ephemeral surface
3783 ///
3784 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3785 /// [`Self::has_calm`], and [`Self::has_data_classification`] — all
3786 /// five route through the SAME [`Self::resolved_classification`]
3787 /// resolver, so the operator-omitted `:classification` slot's
3788 /// fill-through logic lives at ONE substrate primitive rather
3789 /// than being restated in each per-axis probe body. OPENS a fresh
3790 /// (Option-parent × NESTED-STRUCT-scalar-child ×
3791 /// operator-resolvable-baseline) corner on the ephemeral-surface
3792 /// presence-probe algebra — the four prior peers on this surface
3793 /// all read the closed-set discriminator DIRECTLY off a scalar
3794 /// [`Classification`] slot (`point_type`, `substrate`, `calm`,
3795 /// `data_classification`); this probe instead threads through a
3796 /// NESTED-STRUCT intermediary ([`Horizon`], the defaulted nested
3797 /// struct owning the `horizon` axis) to reach a scalar
3798 /// [`HorizonKind`] discriminator on `horizon.kind`. The
3799 /// default-arm short-circuit on the absent-classification arm
3800 /// reads `true` on the [`HorizonKind`] child's `#[default]`
3801 /// variant precisely because BOTH the parent Option's fill-
3802 /// through baseline ([`default_ephemeral_class`], which fills
3803 /// `horizon: Horizon::default()`) AND the child's own `#[default]`
3804 /// land on the SAME variant ([`HorizonKind::Bounded`]). A
3805 /// regression that dropped `#[default]` on [`HorizonKind`], or
3806 /// promoted `Asymptotic` to `#[default]`, or wired the arm to a
3807 /// fixed variant answer, or crossed the wires through the wrong
3808 /// nested struct fails HERE at ONE narrow substrate site before
3809 /// drifting through every unadorned ephemeral spec's baseline
3810 /// horizon answer. Distinct from the FIRST + SECOND peers on the
3811 /// (Option-parent × NON-DEFAULT-scalar-child) corner
3812 /// (`has_point_type`, `has_substrate`) whose absent-classification
3813 /// arm defaults through a specific chosen baseline
3814 /// (`ConvergencePointType::Gate`, `SubstrateType::Compute`), AND
3815 /// distinct from the THIRD + FOURTH peers on the (Option-parent ×
3816 /// DEFAULTED-scalar-child) corner (`has_calm`,
3817 /// `has_data_classification`) which reach a defaulted scalar
3818 /// DIRECTLY off the parent without a nested-struct hop. Three
3819 /// future sibling axes on the SAME `Cow`-resolver carrier
3820 /// ([`Self::has_optimization_direction`] opened the SIXTH; then
3821 /// `has_input_arity`, `has_output_arity`) land as one-line
3822 /// wrappers around the SAME resolver + the sibling
3823 /// [`Classification`] closed-set primitive, so a future variant
3824 /// added to [`HorizonKind`] (or any of the three other closed
3825 /// sets) reaches BOTH surfaces' `<axis>-<kind>` prefix families
3826 /// through the SAME closed-set walk with no per-caller edit.
3827 ///
3828 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3829 /// preserves proofs; the classification-axis presence-probe body
3830 /// composes ONE resolver primitive
3831 /// ([`Self::resolved_classification`]) with ONE closed-set
3832 /// primitive ([`Classification::has_horizon_kind`]) so every
3833 /// downstream (`horizon-<kind>` require-tag families on both
3834 /// surfaces in tatara-check, closed-set audit dispatchers, future
3835 /// variant additions on [`HorizonKind`]) binds through the SAME
3836 /// `has(kind)` shape rather than restating either the resolver
3837 /// walk or the closed-set equality at the callsite.
3838 #[must_use]
3839 pub fn has_horizon_kind(&self, kind: HorizonKind) -> bool {
3840 self.resolved_classification().has_horizon_kind(kind)
3841 }
3842
3843 /// True iff the resolved [`Classification`]'s nested [`Horizon`]
3844 /// carries the given [`OptimizationDirection`] discriminator on its
3845 /// `horizon.direction` slot (with the substrate
3846 /// `Option::unwrap_or_default` treating `None` as the closed set's
3847 /// `#[default] Minimize`) — byte-for-byte peer of
3848 /// [`Classification::has_optimization_direction`] wrapped through
3849 /// the [`Self::resolved_classification`] resolver so an operator-
3850 /// omitted `:classification` slot reads as the
3851 /// [`default_ephemeral_class`] baseline the sibling
3852 /// `From<EphemeralSpec> for ProcessSpec` lowering fills.
3853 ///
3854 /// # Two-surface parity contract
3855 ///
3856 /// A given [`EphemeralSpec`] classifies identically through this
3857 /// primitive AND through
3858 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
3859 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3860 /// resolver on this side and the `.unwrap_or_else(...)` fill on
3861 /// the lowering side both dereference the same
3862 /// `default_ephemeral_class()` value on `None` and the same
3863 /// authored value on `Some(_)`, and the sibling
3864 /// [`Classification::has_optimization_direction`] applies the same
3865 /// `Option::unwrap_or_default` collapse on the inner
3866 /// `horizon.direction` slot on both sides. This means the
3867 /// ephemeral-surface `optimization-direction-<kind>` `:requires`
3868 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3869 /// SAME truth on the SAME authored spec as the point-surface
3870 /// family on the mechanically-lowered `ProcessSpec`.
3871 ///
3872 /// # SIXTH classification-axis peer on the ephemeral surface
3873 ///
3874 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3875 /// [`Self::has_calm`], [`Self::has_data_classification`], and
3876 /// [`Self::has_horizon_kind`] — all six route through the SAME
3877 /// [`Self::resolved_classification`] resolver, so the operator-
3878 /// omitted `:classification` slot's fill-through logic lives at
3879 /// ONE substrate primitive rather than being restated in each per-
3880 /// axis probe body. SECOND occupant on the (Option-parent ×
3881 /// NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
3882 /// corner alongside [`Self::has_horizon_kind`] — both probes thread
3883 /// through the SAME nested [`Horizon`] intermediary to reach a
3884 /// scalar discriminator on the six-axis classification lattice, but
3885 /// this method additionally traverses an `Option`-slot with
3886 /// `unwrap_or_default` so a Process filled through
3887 /// [`crate::classification::Horizon::default`] (leaves `direction:
3888 /// None`) still reads `true` on the closed set's default arm
3889 /// ([`OptimizationDirection::Minimize`]). The corner therefore
3890 /// admits BOTH direct nested-scalar shapes ([`Self::has_horizon_kind`]
3891 /// walks `horizon.kind: HorizonKind` directly) AND Option-nested-
3892 /// scalar shapes (this method walks `horizon.direction:
3893 /// Option<OptimizationDirection>` through `unwrap_or_default`),
3894 /// pinning the corner as a proven-repeatable primitive shape on the
3895 /// ephemeral surface rather than a single-example curiosity. The
3896 /// two-defaults composition property (parent Option's fill-through
3897 /// baseline via `default_ephemeral_class` AND child's closed-set
3898 /// `#[default]` land on the SAME variant) reaches through TWO
3899 /// hops here: the parent Option's `.unwrap_or_else(default_…)`
3900 /// AND the inner Option's `.unwrap_or_default()` both dereference
3901 /// to the same [`OptimizationDirection::Minimize`] baseline the
3902 /// closed set publishes. A regression that flipped
3903 /// [`OptimizationDirection`]'s `#[default]` off `Minimize` (which
3904 /// would silently invert every unadorned `Asymptotic` Process's
3905 /// rate-window evaluator polarity), or that dropped the resolver
3906 /// hop, or that wired the arm to a fixed variant answer, fails
3907 /// HERE at ONE narrow substrate site before drifting through every
3908 /// unadorned ephemeral spec's baseline direction answer. Two future
3909 /// sibling axes on the SAME `Cow`-resolver carrier
3910 /// (`has_input_arity`, `has_output_arity`) land as one-line
3911 /// wrappers around the SAME resolver + the sibling
3912 /// [`Classification`] closed-set primitive, so a future variant
3913 /// added to [`OptimizationDirection`] (or any of the two other
3914 /// closed sets) reaches BOTH surfaces' `<axis>-<kind>` prefix
3915 /// families through the SAME closed-set walk with no per-caller
3916 /// edit.
3917 ///
3918 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
3919 /// preserves proofs; the classification-axis presence-probe body
3920 /// composes ONE resolver primitive
3921 /// ([`Self::resolved_classification`]) with ONE closed-set
3922 /// primitive ([`Classification::has_optimization_direction`]) so
3923 /// every downstream (`optimization-direction-<kind>` require-tag
3924 /// families on both surfaces in tatara-check, closed-set audit
3925 /// dispatchers, future variant additions on
3926 /// [`OptimizationDirection`]) binds through the SAME `has(kind)`
3927 /// shape rather than restating either the resolver walk or the
3928 /// closed-set equality plus the nested-struct-Option-hop at the
3929 /// callsite.
3930 #[must_use]
3931 pub fn has_optimization_direction(&self, kind: OptimizationDirection) -> bool {
3932 self.resolved_classification()
3933 .has_optimization_direction(kind)
3934 }
3935
3936 /// True iff the resolved [`Classification`]'s nested
3937 /// [`ConvergencePointType`] projects (via the many-to-one
3938 /// [`ConvergencePointType::input_arity`] typed projection) to the
3939 /// given [`Arity`] discriminator — byte-for-byte peer of
3940 /// [`Classification::has_input_arity`] wrapped through the
3941 /// [`Self::resolved_classification`] resolver so an operator-omitted
3942 /// `:classification` slot reads as the [`default_ephemeral_class`]
3943 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
3944 /// lowering fills.
3945 ///
3946 /// # Two-surface parity contract
3947 ///
3948 /// A given [`EphemeralSpec`] classifies identically through this
3949 /// primitive AND through
3950 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
3951 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
3952 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
3953 /// lowering side both dereference the same
3954 /// `default_ephemeral_class()` value on `None` and the same
3955 /// authored value on `Some(_)`, and the sibling
3956 /// [`Classification::has_input_arity`] applies the same
3957 /// `point_type.input_arity()` typed projection on both sides. This
3958 /// means the ephemeral-surface `input-arity-<kind>` `:requires`
3959 /// family in `tatara-reconciler::bin::tatara-check` publishes the
3960 /// SAME truth on the SAME authored spec as the point-surface family
3961 /// on the mechanically-lowered `ProcessSpec`.
3962 ///
3963 /// # SEVENTH classification-axis peer on the ephemeral surface — first via a derived-typed-projection
3964 ///
3965 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
3966 /// [`Self::has_calm`], [`Self::has_data_classification`],
3967 /// [`Self::has_horizon_kind`], and
3968 /// [`Self::has_optimization_direction`] — all seven route through
3969 /// the SAME [`Self::resolved_classification`] resolver, so the
3970 /// operator-omitted `:classification` slot's fill-through logic
3971 /// lives at ONE substrate primitive rather than being restated in
3972 /// each per-axis probe body. FIRST occupant on the (Option-parent ×
3973 /// NESTED-STRUCT-scalar-child × derived-typed-projection) corner on
3974 /// the ephemeral surface — byte-for-byte symmetric with the
3975 /// derived-typed-projection precedent set by
3976 /// [`Classification::has_input_arity`] on the point surface: THAT
3977 /// peer routes through [`ConvergencePointType::input_arity`] on a
3978 /// required [`Classification`] carrier; THIS peer routes through the
3979 /// SAME projection on the `Cow`-resolver carrier so the resolver
3980 /// walk composes with the projection at ONE substrate site rather
3981 /// than being restated per surface. Distinct from the SIXTH peer
3982 /// [`Self::has_optimization_direction`] (which walks
3983 /// `horizon.direction` through an `Option::unwrap_or_default`
3984 /// collapse to reach a defaulted scalar child) and the FIFTH peer
3985 /// [`Self::has_horizon_kind`] (which walks `horizon.kind` DIRECTLY
3986 /// as a scalar without any typed-projection hop) on ONE dimension:
3987 /// this probe threads through the many-to-one closed-set typed
3988 /// projection [`ConvergencePointType::input_arity`] (`Transform |
3989 /// Fork | Broadcast | Observe → One`, `Join | Gate | Select |
3990 /// Reduce → Many`) so the child's closed set ([`Arity`]) is REACHED
3991 /// THROUGH a projection layer, not read raw off a scalar. The
3992 /// corner therefore admits three ephemeral-surface traversal
3993 /// shapes through the SAME `resolved_classification().<field>`
3994 /// walk: direct-nested-scalar
3995 /// ([`Self::has_horizon_kind`] reads `horizon.kind: HorizonKind`
3996 /// directly), Option-nested-scalar
3997 /// ([`Self::has_optimization_direction`] reads `horizon.direction:
3998 /// Option<OptimizationDirection>` through `unwrap_or_default`), and
3999 /// derived-typed-projection (this method reads
4000 /// `point_type.input_arity(): Arity` through a many-to-one
4001 /// projection). The co-tenant derived-typed-projection axis on the
4002 /// SAME `Cow`-resolver carrier ([`Self::has_output_arity`]) lands as
4003 /// a one-line wrapper around the SAME resolver + the sibling
4004 /// [`Classification`] closed-set primitive, so a future variant
4005 /// added to [`Arity`] or to [`ConvergencePointType`] reaches BOTH
4006 /// surfaces' `<axis>-<kind>` prefix families through the SAME
4007 /// closed-set walk with no per-caller edit.
4008 ///
4009 /// # Semantics — VARIANT match on the projected image
4010 ///
4011 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
4012 /// `#[default]`), so exactly ONE of the two arms answers `true` per
4013 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
4014 /// shortcut. The absent-`:classification` baseline
4015 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
4016 /// [`ConvergencePointType::input_arity`] projects `Gate → Many`, so
4017 /// the ephemeral sugar surface's `input-arity-Many` require-tag
4018 /// reads `true` on every operator-authored spec that omits the
4019 /// `:classification` slot — pinning the workspace's convergent-by-
4020 /// default point posture on the input side. The many-to-one
4021 /// projection shape means the answer is invariant under intra-
4022 /// bucket point-type swaps (`Transform ↔ Fork ↔ Broadcast ↔
4023 /// Observe` all keep `input-arity-One = true`) and flips at bucket
4024 /// boundaries (`Transform ↔ Join` flips `input-arity-One` from
4025 /// `true` to `false`). A regression that dropped the resolver hop,
4026 /// probed [`ConvergencePointType`] directly (dropping the
4027 /// `.input_arity()` call), inverted the projection (`One ↔ Many`),
4028 /// or crossed the wires with the sibling
4029 /// [`ConvergencePointType::output_arity`] projection fails HERE at
4030 /// ONE narrow substrate site before drifting through every
4031 /// unadorned ephemeral spec's baseline input-arity answer.
4032 ///
4033 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4034 /// preserves proofs; the classification-axis presence-probe body
4035 /// composes ONE resolver primitive
4036 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
4037 /// ([`Classification::has_input_arity`]) so every downstream
4038 /// (`input-arity-<kind>` require-tag families on both surfaces in
4039 /// tatara-check, closed-set audit dispatchers, future variant
4040 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
4041 /// through the SAME `has(kind)` shape rather than restating either
4042 /// the resolver walk or the closed-set equality plus the typed-
4043 /// projection hop at the callsite.
4044 #[must_use]
4045 pub fn has_input_arity(&self, kind: Arity) -> bool {
4046 self.resolved_classification().has_input_arity(kind)
4047 }
4048
4049 /// True iff the resolved [`Classification`]'s nested
4050 /// [`ConvergencePointType`] projects (via the many-to-one
4051 /// [`ConvergencePointType::output_arity`] typed projection) to the
4052 /// given [`Arity`] discriminator — byte-for-byte peer of
4053 /// [`Classification::has_output_arity`] wrapped through the
4054 /// [`Self::resolved_classification`] resolver so an operator-omitted
4055 /// `:classification` slot reads as the [`default_ephemeral_class`]
4056 /// baseline the sibling `From<EphemeralSpec> for ProcessSpec`
4057 /// lowering fills.
4058 ///
4059 /// # Two-surface parity contract
4060 ///
4061 /// A given [`EphemeralSpec`] classifies identically through this
4062 /// primitive AND through
4063 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
4064 /// on the lowered `ProcessSpec` — the `Cow<'_, Classification>`
4065 /// resolver on this side and the `.unwrap_or_else(...)` fill on the
4066 /// lowering side both dereference the same
4067 /// `default_ephemeral_class()` value on `None` and the same
4068 /// authored value on `Some(_)`, and the sibling
4069 /// [`Classification::has_output_arity`] applies the same
4070 /// `point_type.output_arity()` typed projection on both sides. This
4071 /// means the ephemeral-surface `output-arity-<kind>` `:requires`
4072 /// family in `tatara-reconciler::bin::tatara-check` publishes the
4073 /// SAME truth on the SAME authored spec as the point-surface family
4074 /// on the mechanically-lowered `ProcessSpec`.
4075 ///
4076 /// # EIGHTH classification-axis peer — closes the ephemeral-side DAG-composition arity pair
4077 ///
4078 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
4079 /// [`Self::has_calm`], [`Self::has_data_classification`],
4080 /// [`Self::has_horizon_kind`], [`Self::has_optimization_direction`],
4081 /// and [`Self::has_input_arity`] — all eight route through the SAME
4082 /// [`Self::resolved_classification`] resolver, so the operator-
4083 /// omitted `:classification` slot's fill-through logic lives at ONE
4084 /// substrate primitive rather than being restated in each per-axis
4085 /// probe body. SECOND occupant on the (Option-parent × NESTED-
4086 /// STRUCT-scalar-child × derived-typed-projection) corner on the
4087 /// ephemeral surface — co-tenant with [`Self::has_input_arity`] on
4088 /// the SAME `point_type` scalar carrier through the SAME [`Arity`]
4089 /// closed set but through the sibling many-to-one typed projection
4090 /// [`ConvergencePointType::output_arity`] (`Transform | Join | Gate
4091 /// | Select | Reduce | Observe → One`, `Fork | Broadcast → Many`).
4092 /// Closes the DAG-composition arity pair on the ephemeral side —
4093 /// the two projections DISAGREE on the diffusive arms `Fork |
4094 /// Broadcast` (input `One` vs. output `Many`) and on the convergent
4095 /// arms `Join | Gate | Select | Reduce` (input `Many` vs. output
4096 /// `One`), and AGREE on the endomorphic arms `Transform | Observe`
4097 /// (both `One`). Byte-for-byte symmetric with the DAG-composition
4098 /// arity pair on the point surface ([`Classification::has_input_arity`] +
4099 /// [`Classification::has_output_arity`]) — THAT pair walks a required
4100 /// [`Classification`] carrier; THIS pair walks the SAME projection
4101 /// pair on the `Cow`-resolver carrier so the resolver walk composes
4102 /// with the projection at ONE substrate site rather than being
4103 /// restated per surface.
4104 ///
4105 /// # Semantics — VARIANT match on the projected image
4106 ///
4107 /// [`Arity`] carries no `Default` impl (the 2-arm bare enum with no
4108 /// `#[default]`), so exactly ONE of the two arms answers `true` per
4109 /// well-formed [`EphemeralSpec`], with no default-arm short-circuit
4110 /// shortcut. The absent-`:classification` baseline
4111 /// [`default_ephemeral_class`] fills `point_type: Gate`, and
4112 /// [`ConvergencePointType::output_arity`] projects `Gate → One`, so
4113 /// the ephemeral sugar surface's `output-arity-One` require-tag
4114 /// reads `true` on every operator-authored spec that omits the
4115 /// `:classification` slot — pinning the workspace's convergent-by-
4116 /// default point posture on the output side. The many-to-one
4117 /// projection shape means the answer is invariant under intra-
4118 /// bucket point-type swaps (`Fork ↔ Broadcast` both keep
4119 /// `output-arity-Many = true`; `Transform ↔ Join ↔ Gate ↔ Select ↔
4120 /// Reduce ↔ Observe` all keep `output-arity-One = true`) and flips
4121 /// at bucket boundaries (`Fork ↔ Transform` flips `output-arity-
4122 /// Many` from `true` to `false`). A regression that dropped the
4123 /// resolver hop, probed [`ConvergencePointType`] directly (dropping
4124 /// the `.output_arity()` call), inverted the projection (`One ↔
4125 /// Many`), or crossed the wires with the sibling
4126 /// [`ConvergencePointType::input_arity`] projection fails HERE at
4127 /// ONE narrow substrate site before drifting through every
4128 /// unadorned ephemeral spec's baseline output-arity answer.
4129 ///
4130 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4131 /// preserves proofs; the classification-axis presence-probe body
4132 /// composes ONE resolver primitive
4133 /// ([`Self::resolved_classification`]) with ONE closed-set primitive
4134 /// ([`Classification::has_output_arity`]) so every downstream
4135 /// (`output-arity-<kind>` require-tag families on both surfaces in
4136 /// tatara-check, closed-set audit dispatchers, future variant
4137 /// additions on [`Arity`] or on [`ConvergencePointType`]) binds
4138 /// through the SAME `has(kind)` shape rather than restating either
4139 /// the resolver walk or the closed-set equality plus the typed-
4140 /// projection hop at the callsite.
4141 #[must_use]
4142 pub fn has_output_arity(&self, kind: Arity) -> bool {
4143 self.resolved_classification().has_output_arity(kind)
4144 }
4145
4146 /// Derived-boolean predicate — does this ephemeral spec's
4147 /// resolved [`Classification`]'s [`Horizon`] project to `true`
4148 /// under [`crate::classification::HorizonKind::terminates`]?
4149 /// Byte-for-byte peer of
4150 /// [`Classification::horizon_terminates`] wrapped through the
4151 /// [`Self::resolved_classification`] resolver so an operator-
4152 /// omitted `:classification` slot on `(defephemeral …)` still
4153 /// answers via the substrate default. The ONE ephemeral-surface
4154 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4155 /// derived-nullary-boolean walk on the classification-horizon
4156 /// axis.
4157 ///
4158 /// # Two-surface parity — resolver hop + Classification primitive
4159 ///
4160 /// Peer of [`Self::has_point_type`], [`Self::has_substrate`],
4161 /// [`Self::has_calm`], [`Self::has_data_classification`],
4162 /// [`Self::has_horizon_kind`],
4163 /// [`Self::has_optimization_direction`],
4164 /// [`Self::has_input_arity`], and [`Self::has_output_arity`] on
4165 /// the (resolver-hop × [`Classification`] presence primitive)
4166 /// axis: all nine methods route through the SAME
4167 /// [`Self::resolved_classification`] resolver, and each composes
4168 /// against ONE [`Classification`] primitive. This method
4169 /// distinguishes itself by targeting the [`Classification`]
4170 /// primitive [`Classification::horizon_terminates`] which is the
4171 /// FIRST derived-nullary-boolean (no closed-set argument)
4172 /// primitive on the [`Classification`] surface — every prior
4173 /// peer probe on [`Classification`] admits a closed-set `kind`
4174 /// argument and answers a variant-equality question, while this
4175 /// probe collapses [`HorizonKind::ALL`] onto a single boolean
4176 /// via the closed set's own [`HorizonKind::terminates`]
4177 /// predicate.
4178 ///
4179 /// # Semantics — resolver hop + derived-nullary-boolean
4180 ///
4181 /// `horizon_terminates()` returns `true` iff
4182 /// `self.resolved_classification().horizon_terminates()`. The
4183 /// resolver returns the authored [`Classification`] when
4184 /// present and the substrate default
4185 /// [`Classification::gate_compute`] on absence. Because
4186 /// [`Classification::gate_compute`] uses [`Horizon::default`]
4187 /// (whose `kind` field defaults to [`HorizonKind::Bounded`] via
4188 /// `#[default]`), a bare ephemeral spec with no `:classification`
4189 /// slot answers `true` — the default-arm short-circuit
4190 /// propagates through THREE layers of `Default`
4191 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
4192 /// [`HorizonKind::default`]) to this predicate's answer, matching
4193 /// the default-arm shortcut every prior defaulted-child probe
4194 /// on this surface publishes. A regression that dropped the
4195 /// resolver hop, probed [`Classification::has_horizon_kind`]
4196 /// directly (dropping the `.terminates()` projection), or
4197 /// crossed the wires with the antisymmetric partner
4198 /// [`HorizonKind::requires_metric_axes`] fails HERE at ONE
4199 /// narrow substrate site before drifting through every
4200 /// unadorned ephemeral spec's baseline horizon-terminates
4201 /// answer.
4202 ///
4203 /// # Compounding
4204 ///
4205 /// The ephemeral require-tag classifier composes this primitive
4206 /// as a fixed tag `terminating-horizon` on
4207 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4208 /// surface's `terminating-horizon` fixed tag on
4209 /// `POINT_FIXED_TAG_ARMS` via [`Classification::horizon_terminates`]
4210 /// directly. The two-surface parity contract holds by
4211 /// construction: both surfaces route through the SAME
4212 /// [`Classification::horizon_terminates`] primitive after the
4213 /// ephemeral surface pays ONE resolver hop — a future
4214 /// [`HorizonKind`] variant or a future normalization at the
4215 /// substrate primitive lands at ONE site and both surfaces'
4216 /// `terminating-horizon` fixed tags inherit the shift
4217 /// mechanically. A future co-tenant peer on this surface (a
4218 /// hypothetical `horizon_requires_metric_axes` composing the
4219 /// antisymmetric partner [`HorizonKind::requires_metric_axes`]
4220 /// through the SAME resolver hop) lands as ONE peer inherent
4221 /// method with the same nullary-derived body.
4222 ///
4223 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4224 /// preserves proofs; the classification-axis derived-nullary-
4225 /// boolean probe body composes ONE resolver primitive
4226 /// ([`Self::resolved_classification`]) with ONE
4227 /// [`Classification`] primitive
4228 /// ([`Classification::horizon_terminates`]) so every downstream
4229 /// (`terminating-horizon` fixed tags on both surfaces in
4230 /// tatara-check, future scheduler / termination-shape
4231 /// validators, future variant additions on [`HorizonKind`])
4232 /// binds through the SAME `horizon_terminates()` shape rather
4233 /// than restating either the resolver walk or the closed-set
4234 /// projection composition at the callsite. THEORY.md §VI.1 —
4235 /// generation over composition; a future [`HorizonKind`]
4236 /// variant lands at ONE `ALL` entry + ONE `terminates` arm on
4237 /// the closed set and both surfaces pick it up mechanically.
4238 #[must_use]
4239 pub fn horizon_terminates(&self) -> bool {
4240 self.resolved_classification().horizon_terminates()
4241 }
4242
4243 /// Derived-boolean predicate — does this ephemeral spec's
4244 /// resolved [`Classification`]'s [`Horizon`] project to `true`
4245 /// under [`crate::classification::HorizonKind::requires_metric_axes`]?
4246 /// Byte-for-byte peer of
4247 /// [`Classification::horizon_requires_metric_axes`] wrapped
4248 /// through the [`Self::resolved_classification`] resolver so an
4249 /// operator-omitted `:classification` slot on `(defephemeral …)`
4250 /// still answers via the substrate default. The ONE ephemeral-
4251 /// surface substrate primitive that owns the
4252 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on
4253 /// the metric-axes-required question over the classification-
4254 /// horizon axis.
4255 ///
4256 /// # Antisymmetric peer of [`Self::horizon_terminates`]
4257 ///
4258 /// Byte-for-byte antisymmetric peer of [`Self::horizon_terminates`]
4259 /// via the SAME [`Self::resolved_classification`] resolver hop
4260 /// and the SAME closed set [`crate::classification::HorizonKind`]:
4261 /// [`Self::horizon_terminates`] composes
4262 /// [`Classification::horizon_terminates`] (walking
4263 /// [`crate::classification::HorizonKind::terminates`]); this
4264 /// method composes the ANTISYMMETRIC partner
4265 /// [`Classification::horizon_requires_metric_axes`] (walking
4266 /// [`crate::classification::HorizonKind::requires_metric_axes`]).
4267 /// The closed set pins the XOR contract
4268 /// `terminates() ^ requires_metric_axes()` on every variant, so
4269 /// exactly ONE of these two ephemeral-surface derived-nullary
4270 /// probes answers `true` per resolved [`Classification`] and the
4271 /// two probes together partition the resolver's output space into
4272 /// two disjoint buckets on every ephemeral spec — authored or
4273 /// defaulted.
4274 ///
4275 /// # Semantics — resolver hop + derived-nullary-boolean
4276 ///
4277 /// `horizon_requires_metric_axes()` returns `true` iff
4278 /// `self.resolved_classification().horizon_requires_metric_axes()`.
4279 /// The resolver returns the authored [`Classification`] when
4280 /// present and the substrate default
4281 /// [`Classification::gate_compute`] on absence. Because
4282 /// [`Classification::gate_compute`] uses [`Horizon::default`]
4283 /// (whose `kind` field defaults to
4284 /// [`crate::classification::HorizonKind::Bounded`] via
4285 /// `#[default]`), a bare ephemeral spec with no `:classification`
4286 /// slot answers `false` — the default-arm short-circuit
4287 /// propagates through THREE layers of `Default`
4288 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
4289 /// [`crate::classification::HorizonKind::default`]) to this
4290 /// predicate's answer, the mirror image of
4291 /// [`Self::horizon_terminates`]'s default-arm `true` answer. A
4292 /// regression that dropped the resolver hop, probed
4293 /// [`Classification::has_horizon_kind`] directly (dropping the
4294 /// `.requires_metric_axes()` projection), or crossed the wires
4295 /// with the antisymmetric partner
4296 /// [`crate::classification::HorizonKind::terminates`] fails HERE
4297 /// at ONE narrow substrate site before drifting through every
4298 /// unadorned ephemeral spec's baseline metric-provisioning
4299 /// answer.
4300 ///
4301 /// # Compounding
4302 ///
4303 /// The ephemeral require-tag classifier composes this primitive
4304 /// as a fixed tag `metric-axes-required` on
4305 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4306 /// surface's `metric-axes-required` fixed tag on
4307 /// `POINT_FIXED_TAG_ARMS` via
4308 /// [`Classification::horizon_requires_metric_axes`] directly. The
4309 /// two-surface parity contract holds by construction: both
4310 /// surfaces route through the SAME
4311 /// [`Classification::horizon_requires_metric_axes`] primitive
4312 /// after the ephemeral surface pays ONE resolver hop — a future
4313 /// [`crate::classification::HorizonKind`] variant or a future
4314 /// normalization at the substrate primitive lands at ONE site and
4315 /// both surfaces' `metric-axes-required` fixed tags inherit the
4316 /// shift mechanically.
4317 ///
4318 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4319 /// preserves proofs; the classification-axis derived-nullary-
4320 /// boolean probe body composes ONE resolver primitive
4321 /// ([`Self::resolved_classification`]) with ONE
4322 /// [`Classification`] primitive
4323 /// ([`Classification::horizon_requires_metric_axes`]) so every
4324 /// downstream (`metric-axes-required` fixed tags on both
4325 /// surfaces in tatara-check, future scheduler / metric-
4326 /// provisioning validators, future variant additions on
4327 /// [`crate::classification::HorizonKind`]) binds through the
4328 /// SAME `horizon_requires_metric_axes()` shape rather than
4329 /// restating either the resolver walk or the closed-set
4330 /// projection composition at the callsite. THEORY.md §VI.1 —
4331 /// generation over composition; a future
4332 /// [`crate::classification::HorizonKind`] variant lands at ONE
4333 /// `ALL` entry + ONE `requires_metric_axes` arm on the closed
4334 /// set and both surfaces pick it up mechanically.
4335 #[must_use]
4336 pub fn horizon_requires_metric_axes(&self) -> bool {
4337 self.resolved_classification()
4338 .horizon_requires_metric_axes()
4339 }
4340
4341 /// Derived-boolean predicate — does this ephemeral spec's
4342 /// resolved [`Classification`]'s [`crate::classification::CalmClassification`]
4343 /// project to `true` under
4344 /// [`crate::classification::CalmClassification::requires_coordination`]?
4345 /// Byte-for-byte peer of
4346 /// [`Classification::calm_requires_coordination`] wrapped through
4347 /// the [`Self::resolved_classification`] resolver so an operator-
4348 /// omitted `:classification` slot on `(defephemeral …)` still
4349 /// answers via the substrate default. The ONE ephemeral-surface
4350 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4351 /// derived-nullary-boolean walk on the coordination-required
4352 /// question over the classification-calm axis.
4353 ///
4354 /// # Third derived-nullary-boolean peer on the ephemeral surface
4355 ///
4356 /// Peer of [`Self::horizon_terminates`] and
4357 /// [`Self::horizon_requires_metric_axes`] on the ephemeral
4358 /// surface's (resolver-hop × derived-nullary-bool) shape — the
4359 /// FIRST peer threading the classification-calm axis rather than
4360 /// the classification-horizon axis. Distinct from both prior
4361 /// derived-nullary peers by ONE structural degree at the underlying
4362 /// [`Classification`] primitive: [`Self::horizon_terminates`] +
4363 /// [`Self::horizon_requires_metric_axes`] both walk the nested
4364 /// `.horizon.kind` sub-slot's derived projection, while this probe
4365 /// walks the direct scalar `.calm` field's derived projection.
4366 /// The resolver-hop shape is byte-identical.
4367 ///
4368 /// # Semantics — resolver hop + derived-nullary-boolean
4369 ///
4370 /// `calm_requires_coordination()` returns `true` iff
4371 /// `self.resolved_classification().calm_requires_coordination()`.
4372 /// The resolver returns the authored [`Classification`] when
4373 /// present and the substrate default
4374 /// [`Classification::gate_compute`] on absence. Because
4375 /// [`Classification::gate_compute`] carries
4376 /// [`crate::classification::CalmClassification::default = Monotone`],
4377 /// a bare ephemeral spec with no `:classification` slot answers
4378 /// `false` — the default-arm short-circuit propagates through TWO
4379 /// layers of `Default` ([`Classification::gate_compute`] →
4380 /// [`crate::classification::CalmClassification::default`]) to this
4381 /// predicate's answer. Distinct from the two `horizon_*` peers on
4382 /// this surface, which short-circuit through THREE layers of
4383 /// `Default` ([`Classification::gate_compute`] → [`Horizon::default`]
4384 /// → [`HorizonKind::default`]) because the horizon axis has a
4385 /// nested-struct wrapper between the classification field and the
4386 /// closed-set discriminator. A regression that dropped the
4387 /// resolver hop, probed [`Classification::has_calm`] directly
4388 /// (dropping the `.requires_coordination()` projection), or
4389 /// inverted the projection (silently promoting the Monotone
4390 /// baseline to "requires coordination") fails HERE at ONE narrow
4391 /// substrate site before drifting through every unadorned
4392 /// ephemeral spec's baseline coordination-mode answer.
4393 ///
4394 /// # Compounding
4395 ///
4396 /// The ephemeral require-tag classifier composes this primitive
4397 /// as a fixed tag `coordination-required` on
4398 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4399 /// surface's `coordination-required` fixed tag on
4400 /// `POINT_FIXED_TAG_ARMS` via
4401 /// [`Classification::calm_requires_coordination`] directly. The
4402 /// two-surface parity contract holds by construction: both
4403 /// surfaces route through the SAME
4404 /// [`Classification::calm_requires_coordination`] primitive after
4405 /// the ephemeral surface pays ONE resolver hop — a future
4406 /// [`crate::classification::CalmClassification`] variant or a
4407 /// future normalization at the substrate primitive lands at ONE
4408 /// site and both surfaces' `coordination-required` fixed tags
4409 /// inherit the shift mechanically.
4410 ///
4411 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4412 /// preserves proofs; the classification-axis derived-nullary-
4413 /// boolean probe body composes ONE resolver primitive
4414 /// ([`Self::resolved_classification`]) with ONE
4415 /// [`Classification`] primitive
4416 /// ([`Classification::calm_requires_coordination`]) so every
4417 /// downstream (`coordination-required` fixed tags on both
4418 /// surfaces in tatara-check, future scheduler / coordination-mode
4419 /// validators, future variant additions on
4420 /// [`crate::classification::CalmClassification`]) binds through
4421 /// the SAME `calm_requires_coordination()` shape rather than
4422 /// restating either the resolver walk or the closed-set
4423 /// projection composition at the callsite. THEORY.md §VI.1 —
4424 /// generation over composition; a future
4425 /// [`crate::classification::CalmClassification`] variant lands at
4426 /// ONE `ALL` entry + ONE `requires_coordination` arm on the
4427 /// closed set and both surfaces pick it up mechanically.
4428 #[must_use]
4429 pub fn calm_requires_coordination(&self) -> bool {
4430 self.resolved_classification().calm_requires_coordination()
4431 }
4432
4433 /// Derived-boolean predicate — does this ephemeral spec's
4434 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
4435 /// project to `true` under
4436 /// [`crate::classification::DataClassification::is_regulated`]?
4437 /// Byte-for-byte peer of
4438 /// [`Classification::data_is_regulated`] wrapped through the
4439 /// [`Self::resolved_classification`] resolver so an operator-
4440 /// omitted `:classification` slot on `(defephemeral …)` still
4441 /// answers via the substrate default. The ONE ephemeral-surface
4442 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4443 /// derived-nullary-boolean walk on the regulated-data question
4444 /// over the classification-data axis.
4445 ///
4446 /// # Fourth derived-nullary-boolean peer on the ephemeral surface
4447 ///
4448 /// Peer of [`Self::horizon_terminates`],
4449 /// [`Self::horizon_requires_metric_axes`], and
4450 /// [`Self::calm_requires_coordination`] on the ephemeral surface's
4451 /// (resolver-hop × derived-nullary-bool) shape — the FIRST peer
4452 /// threading the classification-data axis rather than the horizon
4453 /// or calm axes. Structural byte-for-byte peer of
4454 /// [`Self::calm_requires_coordination`]: both walk a DIRECT scalar
4455 /// closed-set field's derived projection on the resolved
4456 /// [`Classification`] (`.calm.requires_coordination()` /
4457 /// `.data_classification.is_regulated()`) — TWO layers of
4458 /// `Default` short-circuit ([`Classification::gate_compute`] →
4459 /// the direct scalar child's `#[default]`) — distinct from the
4460 /// two `horizon_*` peers which walk a NESTED-STRUCT projection
4461 /// (`.horizon.kind`) with THREE layers of `Default`. The resolver-
4462 /// hop shape is byte-identical across all four peers.
4463 ///
4464 /// # Semantics — resolver hop + derived-nullary-boolean
4465 ///
4466 /// `data_is_regulated()` returns `true` iff
4467 /// `self.resolved_classification().data_is_regulated()`. The
4468 /// resolver returns the authored [`Classification`] when present
4469 /// and the substrate default [`Classification::gate_compute`] on
4470 /// absence. Because [`Classification::gate_compute`] carries
4471 /// [`crate::classification::DataClassification::default = Internal`],
4472 /// a bare ephemeral spec with no `:classification` slot answers
4473 /// `false` — the default-arm short-circuit propagates through TWO
4474 /// layers of `Default` ([`Classification::gate_compute`] →
4475 /// [`crate::classification::DataClassification::default`]) to
4476 /// this predicate's answer, mirror-image of
4477 /// [`Self::calm_requires_coordination`]'s Monotone-default
4478 /// short-circuit through the same structural depth. Distinct
4479 /// from the two `horizon_*` peers on this surface which short-
4480 /// circuit through THREE layers of `Default` because the horizon
4481 /// axis has a nested-struct wrapper. A regression that dropped
4482 /// the resolver hop, probed [`Classification::has_data_classification`]
4483 /// directly (dropping the `.is_regulated()` projection), or
4484 /// inverted the projection (silently promoting the Internal
4485 /// baseline to "regulated") fails HERE at ONE narrow substrate
4486 /// site before drifting through every unadorned ephemeral spec's
4487 /// baseline regulatory-regime answer.
4488 ///
4489 /// # Compounding
4490 ///
4491 /// The ephemeral require-tag classifier composes this primitive
4492 /// as a fixed tag `data-regulated` on `EPHEMERAL_FIXED_TAG_ARMS`
4493 /// — byte-for-byte peer of the point surface's `data-regulated`
4494 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4495 /// [`Classification::data_is_regulated`] directly. The two-
4496 /// surface parity contract holds by construction: both surfaces
4497 /// route through the SAME
4498 /// [`Classification::data_is_regulated`] primitive after the
4499 /// ephemeral surface pays ONE resolver hop — a future
4500 /// [`crate::classification::DataClassification`] variant or a
4501 /// future normalization at the substrate primitive lands at ONE
4502 /// site and both surfaces' `data-regulated` fixed tags inherit
4503 /// the shift mechanically.
4504 ///
4505 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4506 /// preserves proofs; the classification-data-axis derived-nullary-
4507 /// boolean probe body composes ONE resolver primitive
4508 /// ([`Self::resolved_classification`]) with ONE
4509 /// [`Classification`] primitive
4510 /// ([`Classification::data_is_regulated`]) so every downstream
4511 /// (`data-regulated` fixed tags on both surfaces in tatara-check,
4512 /// future compliance-baseline / regulatory-regime validators,
4513 /// future variant additions on
4514 /// [`crate::classification::DataClassification`]) binds through
4515 /// the SAME `data_is_regulated()` shape rather than restating
4516 /// either the resolver walk or the closed-set projection
4517 /// composition at the callsite. THEORY.md §VI.1 — generation
4518 /// over composition; a future
4519 /// [`crate::classification::DataClassification`] variant lands
4520 /// at ONE `ALL` entry + ONE `is_regulated` arm on the closed set
4521 /// and both surfaces pick it up mechanically.
4522 #[must_use]
4523 pub fn data_is_regulated(&self) -> bool {
4524 self.resolved_classification().data_is_regulated()
4525 }
4526
4527 /// Derived-boolean predicate — does this ephemeral spec's
4528 /// resolved [`Classification`]'s [`crate::classification::DataClassification`]
4529 /// project to `true` under
4530 /// [`crate::classification::DataClassification::is_restricted`]?
4531 /// Byte-for-byte peer of
4532 /// [`Classification::data_is_restricted`] wrapped through the
4533 /// [`Self::resolved_classification`] resolver so an operator-
4534 /// omitted `:classification` slot on `(defephemeral …)` still
4535 /// answers via the substrate default. The ONE ephemeral-surface
4536 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4537 /// derived-nullary-boolean walk on the restricted-data question
4538 /// over the classification-data axis.
4539 ///
4540 /// # Fifth derived-nullary-boolean peer on the ephemeral surface
4541 ///
4542 /// Peer of [`Self::horizon_terminates`],
4543 /// [`Self::horizon_requires_metric_axes`],
4544 /// [`Self::calm_requires_coordination`], and
4545 /// [`Self::data_is_regulated`] on the ephemeral surface's
4546 /// (resolver-hop × derived-nullary-bool) shape — the SECOND peer
4547 /// threading the classification-data axis after
4548 /// [`Self::data_is_regulated`] opened it, pinning the data axis
4549 /// as a proven-repeatable structural sub-corner across TWO sibling
4550 /// closed-set projections (`is_regulated` / `is_restricted`).
4551 /// Structural byte-for-byte peer of
4552 /// [`Self::data_is_regulated`]: both walk the SAME DIRECT scalar
4553 /// closed-set field's derived projection on the resolved
4554 /// [`Classification`] (`.data_classification.is_regulated()` /
4555 /// `.is_restricted()`) — TWO layers of `Default` short-circuit
4556 /// ([`Classification::gate_compute`] → [`crate::classification::DataClassification::default = Internal`])
4557 /// — distinct from the two `horizon_*` peers which walk a NESTED-
4558 /// STRUCT projection (`.horizon.kind`) with THREE layers of
4559 /// `Default`. The resolver-hop shape is byte-identical across all
4560 /// five peers.
4561 ///
4562 /// # Semantics — resolver hop + derived-nullary-boolean
4563 ///
4564 /// `data_is_restricted()` returns `true` iff
4565 /// `self.resolved_classification().data_is_restricted()`. The
4566 /// resolver returns the authored [`Classification`] when present
4567 /// and the substrate default [`Classification::gate_compute`] on
4568 /// absence. Because [`Classification::gate_compute`] carries
4569 /// [`crate::classification::DataClassification::default = Internal`],
4570 /// a bare ephemeral spec with no `:classification` slot answers
4571 /// `true` — the default-arm short-circuit propagates through TWO
4572 /// layers of `Default` ([`Classification::gate_compute`] →
4573 /// [`crate::classification::DataClassification::default`]) to
4574 /// this predicate's answer. FIRST direct-scalar ephemeral-surface
4575 /// peer whose absent-classification default answers `true`, not
4576 /// `false` (`data_is_regulated` and `calm_requires_coordination`
4577 /// both project `false` on the same absent classification),
4578 /// mirror-image of [`Self::horizon_terminates`]'s `Bounded`-default
4579 /// `true` baseline on the nested-struct sub-corner. A regression
4580 /// that dropped the resolver hop, probed
4581 /// [`Classification::has_data_classification`] directly (dropping
4582 /// the `.is_restricted()` projection), or inverted the projection
4583 /// (silently demoting the Internal baseline to "unrestricted")
4584 /// fails HERE at ONE narrow substrate site before drifting
4585 /// through every unadorned ephemeral spec's baseline access-
4586 /// control-mandatory answer.
4587 ///
4588 /// # Compounding
4589 ///
4590 /// The ephemeral require-tag classifier composes this primitive
4591 /// as a fixed tag `data-restricted` on `EPHEMERAL_FIXED_TAG_ARMS`
4592 /// — byte-for-byte peer of the point surface's `data-restricted`
4593 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4594 /// [`Classification::data_is_restricted`] directly. The two-
4595 /// surface parity contract holds by construction: both surfaces
4596 /// route through the SAME
4597 /// [`Classification::data_is_restricted`] primitive after the
4598 /// ephemeral surface pays ONE resolver hop — a future
4599 /// [`crate::classification::DataClassification`] variant or a
4600 /// future normalization at the substrate primitive lands at ONE
4601 /// site and both surfaces' `data-restricted` fixed tags inherit
4602 /// the shift mechanically. The closed-set-internal implication
4603 /// `is_regulated() ⇒ is_restricted()` composes through the
4604 /// resolver hop to
4605 /// `data_is_regulated() ⇒ data_is_restricted()` at this surface
4606 /// too.
4607 ///
4608 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4609 /// preserves proofs; the classification-data-axis derived-nullary-
4610 /// boolean probe body composes ONE resolver primitive
4611 /// ([`Self::resolved_classification`]) with ONE
4612 /// [`Classification`] primitive
4613 /// ([`Classification::data_is_restricted`]) so every downstream
4614 /// (`data-restricted` fixed tags on both surfaces in tatara-check,
4615 /// future compliance-baseline / access-control-mandatory
4616 /// validators, future variant additions on
4617 /// [`crate::classification::DataClassification`]) binds through
4618 /// the SAME `data_is_restricted()` shape rather than restating
4619 /// either the resolver walk or the closed-set projection
4620 /// composition at the callsite. THEORY.md §VI.1 — generation
4621 /// over composition; a future
4622 /// [`crate::classification::DataClassification`] variant lands
4623 /// at ONE `ALL` entry + ONE `is_restricted` arm on the closed set
4624 /// and both surfaces pick it up mechanically.
4625 #[must_use]
4626 pub fn data_is_restricted(&self) -> bool {
4627 self.resolved_classification().data_is_restricted()
4628 }
4629
4630 /// Derived-boolean predicate — does this ephemeral spec's
4631 /// resolved [`Classification`]'s
4632 /// [`crate::classification::ConvergencePointType`] project to
4633 /// `true` under
4634 /// [`crate::classification::ConvergencePointType::is_endomorphic`]?
4635 /// Byte-for-byte peer of
4636 /// [`Classification::point_is_endomorphic`] wrapped through the
4637 /// [`Self::resolved_classification`] resolver so an operator-
4638 /// omitted `:classification` slot on `(defephemeral …)` still
4639 /// answers via the substrate default. The ONE ephemeral-surface
4640 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4641 /// derived-nullary-boolean walk on the 1→1 topology-bucket
4642 /// question over the classification-`point_type` axis.
4643 ///
4644 /// # Sixth derived-nullary-boolean peer on the ephemeral surface
4645 ///
4646 /// Peer of [`Self::horizon_terminates`],
4647 /// [`Self::horizon_requires_metric_axes`],
4648 /// [`Self::calm_requires_coordination`],
4649 /// [`Self::data_is_regulated`], and [`Self::data_is_restricted`]
4650 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
4651 /// shape — the FIRST peer threading the classification-`point_type`
4652 /// axis after the two `horizon_*`, one `calm_*`, and two `data_*`
4653 /// peers populated the horizon, calm, and data axes. Direct-scalar
4654 /// peer of the sibling `data_*` and `calm_*` arms but distinct by
4655 /// ONE structural degree at the underlying [`Classification`]
4656 /// primitive: [`crate::classification::ConvergencePointType`] has
4657 /// NO [`Default`] impl, so the absent-`:classification` baseline
4658 /// answers `false` via the resolver's substrate default
4659 /// [`Classification::gate_compute`] carrying its chosen
4660 /// `point_type: Gate` field (not via a `#[default]` short-circuit
4661 /// on the point-type axis itself). The resolver-hop shape is
4662 /// byte-identical across all six peers.
4663 ///
4664 /// # Semantics — resolver hop + derived-nullary-boolean
4665 ///
4666 /// `point_is_endomorphic()` returns `true` iff
4667 /// `self.resolved_classification().point_is_endomorphic()`. The
4668 /// resolver returns the authored [`Classification`] when present
4669 /// and the substrate default [`Classification::gate_compute`] on
4670 /// absence. Because [`Classification::gate_compute`] carries
4671 /// [`crate::classification::ConvergencePointType::Gate`] (a
4672 /// convergent barrier point, not a 1→1 endomorphism), a bare
4673 /// ephemeral spec with no `:classification` slot answers `false`.
4674 /// A regression that dropped the resolver hop, probed the wrong
4675 /// closed-set arm, or inverted the projection fails HERE at ONE
4676 /// narrow substrate site before drifting through every unadorned
4677 /// ephemeral spec's DAG-composition answer.
4678 ///
4679 /// # Compounding
4680 ///
4681 /// The ephemeral require-tag classifier composes this primitive
4682 /// as a fixed tag `endomorphic-point` on
4683 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4684 /// surface's `endomorphic-point` fixed tag on
4685 /// `POINT_FIXED_TAG_ARMS` via
4686 /// [`Classification::point_is_endomorphic`] directly. The two-
4687 /// surface parity contract holds by construction: both surfaces
4688 /// route through the SAME
4689 /// [`Classification::point_is_endomorphic`] primitive after the
4690 /// ephemeral surface pays ONE resolver hop — a future
4691 /// [`crate::classification::ConvergencePointType`] variant or a
4692 /// future normalization at the substrate primitive lands at ONE
4693 /// site and both surfaces' `endomorphic-point` fixed tags inherit
4694 /// the shift mechanically. Sibling projections
4695 /// [`crate::classification::ConvergencePointType::is_diffusive`]
4696 /// and [`crate::classification::ConvergencePointType::is_convergent`]
4697 /// compose byte-identically as future seventh + eighth ephemeral-
4698 /// surface peers; when all three land the three-way partition
4699 /// contract sealed on the closed set by
4700 /// `convergence_point_type_buckets_cover_every_variant` composes
4701 /// through the resolver-hop layer as a substrate-wide theorem.
4702 ///
4703 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4704 /// preserves proofs; the classification-`point_type`-axis derived-
4705 /// nullary-boolean probe body composes ONE resolver primitive
4706 /// ([`Self::resolved_classification`]) with ONE
4707 /// [`Classification`] primitive
4708 /// ([`Classification::point_is_endomorphic`]) so every downstream
4709 /// (`endomorphic-point` fixed tags on both surfaces in tatara-check,
4710 /// future DAG composition / edge-cardinality validators, future
4711 /// variant additions on
4712 /// [`crate::classification::ConvergencePointType`]) binds through
4713 /// the SAME `point_is_endomorphic()` shape rather than restating
4714 /// either the resolver walk or the closed-set projection
4715 /// composition at the callsite. THEORY.md §VI.1 — generation over
4716 /// composition; a future
4717 /// [`crate::classification::ConvergencePointType`] variant lands
4718 /// at ONE `ALL` entry + ONE `is_endomorphic` arm on the closed
4719 /// set and both surfaces pick it up mechanically.
4720 #[must_use]
4721 pub fn point_is_endomorphic(&self) -> bool {
4722 self.resolved_classification().point_is_endomorphic()
4723 }
4724
4725 /// Derived-boolean predicate — does this ephemeral spec's
4726 /// resolved [`Classification`]'s
4727 /// [`crate::classification::ConvergencePointType`] project to
4728 /// `true` under
4729 /// [`crate::classification::ConvergencePointType::is_diffusive`]?
4730 /// Byte-for-byte peer of
4731 /// [`Classification::point_is_diffusive`] wrapped through the
4732 /// [`Self::resolved_classification`] resolver so an operator-
4733 /// omitted `:classification` slot on `(defephemeral …)` still
4734 /// answers via the substrate default. The ONE ephemeral-surface
4735 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4736 /// derived-nullary-boolean walk on the 1→N fan-out topology-bucket
4737 /// question over the classification-`point_type` axis.
4738 ///
4739 /// # Seventh derived-nullary-boolean peer on the ephemeral surface
4740 ///
4741 /// Peer of [`Self::horizon_terminates`],
4742 /// [`Self::horizon_requires_metric_axes`],
4743 /// [`Self::calm_requires_coordination`],
4744 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`], and
4745 /// [`Self::point_is_endomorphic`] on the ephemeral surface's
4746 /// (resolver-hop × derived-nullary-bool) shape — the SEVENTH peer
4747 /// overall and the SECOND peer threading the classification-
4748 /// `point_type` axis. Direct-scalar peer of
4749 /// [`Self::point_is_endomorphic`]: both compose the SAME resolver
4750 /// hop and the SAME closed-set carrier through the SAME chosen-
4751 /// field baseline discipline (`Gate.is_diffusive() = false`,
4752 /// mirror-image of `Gate.is_endomorphic() = false`). The
4753 /// resolver-hop shape is byte-identical across all seven peers.
4754 ///
4755 /// # Semantics — resolver hop + derived-nullary-boolean
4756 ///
4757 /// `point_is_diffusive()` returns `true` iff
4758 /// `self.resolved_classification().point_is_diffusive()`. The
4759 /// resolver returns the authored [`Classification`] when present
4760 /// and the substrate default [`Classification::gate_compute`] on
4761 /// absence. Because [`Classification::gate_compute`] carries
4762 /// [`crate::classification::ConvergencePointType::Gate`] (a
4763 /// convergent barrier, not a fan-out), a bare ephemeral spec with
4764 /// no `:classification` slot answers `false`. A regression that
4765 /// dropped the resolver hop, probed the wrong closed-set arm, or
4766 /// inverted the projection fails HERE at ONE narrow substrate
4767 /// site before drifting through every unadorned ephemeral spec's
4768 /// DAG-composition answer.
4769 ///
4770 /// # Compounding — first ephemeral-surface corner-peer mutex on the `point_type` axis
4771 ///
4772 /// The ephemeral require-tag classifier composes this primitive
4773 /// as a fixed tag `diffusive-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4774 /// — byte-for-byte peer of the point surface's `diffusive-point`
4775 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4776 /// [`Classification::point_is_diffusive`] directly. The two-
4777 /// surface parity contract holds by construction: both surfaces
4778 /// route through the SAME
4779 /// [`Classification::point_is_diffusive`] primitive after the
4780 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4781 /// surface corner-peer pair on the `point_type` axis (with
4782 /// [`Self::point_is_endomorphic`]) whose two projections carry a
4783 /// non-trivial closed-set-internal MUTEX relationship
4784 /// (`point_is_endomorphic ⇒ ¬point_is_diffusive`), distinct from
4785 /// the sibling `data`-axis ephemeral corner-peer pair whose two
4786 /// projections carry a non-trivial IMPLICATION relationship. When
4787 /// the third sibling [`Self::point_is_convergent`] lands, the
4788 /// mutex closes into the full three-way XOR partition composed
4789 /// through the resolver-hop layer as a substrate-wide theorem.
4790 ///
4791 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4792 /// preserves proofs; the classification-`point_type`-axis derived-
4793 /// nullary-boolean probe body composes ONE resolver primitive
4794 /// ([`Self::resolved_classification`]) with ONE
4795 /// [`Classification`] primitive
4796 /// ([`Classification::point_is_diffusive`]) so every downstream
4797 /// (`diffusive-point` fixed tags on both surfaces in tatara-check,
4798 /// future DAG composition / edge-cardinality validators, future
4799 /// variant additions on
4800 /// [`crate::classification::ConvergencePointType`]) binds through
4801 /// the SAME `point_is_diffusive()` shape rather than restating
4802 /// either the resolver walk or the closed-set projection
4803 /// composition at the callsite. THEORY.md §VI.1 — generation over
4804 /// composition; a future
4805 /// [`crate::classification::ConvergencePointType`] variant lands
4806 /// at ONE `ALL` entry + ONE `is_diffusive` arm on the closed set
4807 /// and both surfaces pick it up mechanically.
4808 #[must_use]
4809 pub fn point_is_diffusive(&self) -> bool {
4810 self.resolved_classification().point_is_diffusive()
4811 }
4812
4813 /// Derived-boolean predicate — does this ephemeral spec's
4814 /// resolved [`Classification`]'s
4815 /// [`crate::classification::ConvergencePointType`] project to
4816 /// `true` under
4817 /// [`crate::classification::ConvergencePointType::is_convergent`]?
4818 /// Byte-for-byte peer of
4819 /// [`Classification::point_is_convergent`] wrapped through the
4820 /// [`Self::resolved_classification`] resolver so an operator-
4821 /// omitted `:classification` slot on `(defephemeral …)` still
4822 /// answers via the substrate default. The ONE ephemeral-surface
4823 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4824 /// derived-nullary-boolean walk on the N→1 fan-in topology-bucket
4825 /// question over the classification-`point_type` axis.
4826 ///
4827 /// # Eighth derived-nullary-boolean peer on the ephemeral surface
4828 ///
4829 /// Peer of [`Self::horizon_terminates`],
4830 /// [`Self::horizon_requires_metric_axes`],
4831 /// [`Self::calm_requires_coordination`],
4832 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4833 /// [`Self::point_is_endomorphic`], and [`Self::point_is_diffusive`]
4834 /// on the ephemeral surface's (resolver-hop × derived-nullary-
4835 /// bool) shape — the EIGHTH peer overall and the THIRD peer
4836 /// threading the classification-`point_type` axis. Direct-scalar
4837 /// peer of [`Self::point_is_endomorphic`] and
4838 /// [`Self::point_is_diffusive`]: the three compose the SAME
4839 /// resolver hop and the SAME closed-set carrier through the SAME
4840 /// chosen-field baseline discipline, but the answer flips on the
4841 /// baseline — `Gate.is_convergent() = true`, so an ephemeral spec
4842 /// with no `:classification` slot answers `true` HERE (mirror-
4843 /// inverted from the two sibling probes which answer `false`).
4844 /// The resolver-hop shape is byte-identical across all eight
4845 /// peers.
4846 ///
4847 /// # Semantics — resolver hop + derived-nullary-boolean
4848 ///
4849 /// `point_is_convergent()` returns `true` iff
4850 /// `self.resolved_classification().point_is_convergent()`. The
4851 /// resolver returns the authored [`Classification`] when present
4852 /// and the substrate default [`Classification::gate_compute`] on
4853 /// absence. Because [`Classification::gate_compute`] carries
4854 /// [`crate::classification::ConvergencePointType::Gate`] (the
4855 /// canonical convergent barrier), a bare ephemeral spec with no
4856 /// `:classification` slot answers `true` — a regression that
4857 /// dropped the resolver hop, probed the wrong closed-set arm, or
4858 /// inverted the projection fails HERE at ONE narrow substrate
4859 /// site before drifting through every unadorned ephemeral spec's
4860 /// DAG-composition answer.
4861 ///
4862 /// # Compounding — closes the three-way XOR partition on the ephemeral surface
4863 ///
4864 /// The ephemeral require-tag classifier composes this primitive
4865 /// as a fixed tag `convergent-point` on `EPHEMERAL_FIXED_TAG_ARMS`
4866 /// — byte-for-byte peer of the point surface's `convergent-point`
4867 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
4868 /// [`Classification::point_is_convergent`] directly. The two-
4869 /// surface parity contract holds by construction: both surfaces
4870 /// route through the SAME
4871 /// [`Classification::point_is_convergent`] primitive after the
4872 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
4873 /// surface peer on the `point_type` axis closing the mutex pair
4874 /// [`Self::point_is_endomorphic`] / [`Self::point_is_diffusive`]
4875 /// into the FULL three-way XOR partition contract composed
4876 /// through the resolver-hop layer as a substrate-wide theorem.
4877 ///
4878 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4879 /// preserves proofs; the classification-`point_type`-axis derived-
4880 /// nullary-boolean probe body composes ONE resolver primitive
4881 /// ([`Self::resolved_classification`]) with ONE
4882 /// [`Classification`] primitive
4883 /// ([`Classification::point_is_convergent`]) so every downstream
4884 /// (`convergent-point` fixed tags on both surfaces in tatara-check,
4885 /// future DAG composition / edge-cardinality validators, future
4886 /// variant additions on
4887 /// [`crate::classification::ConvergencePointType`]) binds through
4888 /// the SAME `point_is_convergent()` shape rather than restating
4889 /// either the resolver walk or the closed-set projection
4890 /// composition at the callsite. THEORY.md §VI.1 — generation over
4891 /// composition; a future
4892 /// [`crate::classification::ConvergencePointType`] variant lands
4893 /// at ONE `ALL` entry + ONE `is_convergent` arm on the closed set
4894 /// and both surfaces pick it up mechanically.
4895 #[must_use]
4896 pub fn point_is_convergent(&self) -> bool {
4897 self.resolved_classification().point_is_convergent()
4898 }
4899
4900 /// Derived-boolean predicate — does this ephemeral spec's
4901 /// resolved [`Classification`]'s
4902 /// [`crate::classification::SubstrateType`] project to `true`
4903 /// under [`crate::classification::SubstrateType::is_resource`]?
4904 /// Byte-for-byte peer of
4905 /// [`Classification::substrate_is_resource`] wrapped through the
4906 /// [`Self::resolved_classification`] resolver so an operator-
4907 /// omitted `:classification` slot on `(defephemeral …)` still
4908 /// answers via the substrate default. The ONE ephemeral-surface
4909 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4910 /// derived-nullary-boolean walk on the resource-plane bucket
4911 /// question over the classification-`substrate` axis.
4912 ///
4913 /// # Ninth derived-nullary-boolean peer on the ephemeral surface
4914 ///
4915 /// Peer of [`Self::horizon_terminates`],
4916 /// [`Self::horizon_requires_metric_axes`],
4917 /// [`Self::calm_requires_coordination`],
4918 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
4919 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
4920 /// and [`Self::point_is_convergent`] on the ephemeral surface's
4921 /// (resolver-hop × derived-nullary-bool) shape — the NINTH peer
4922 /// overall and the FIRST peer threading the classification-
4923 /// `substrate` axis (the fourth of six classification axes
4924 /// participating on this corner, after `horizon`, `calm`,
4925 /// `data_classification`, and `point_type`). The resolver-hop
4926 /// shape is byte-identical across all nine peers.
4927 ///
4928 /// # Semantics — resolver hop + derived-nullary-boolean
4929 ///
4930 /// `substrate_is_resource()` returns `true` iff
4931 /// `self.resolved_classification().substrate_is_resource()`. The
4932 /// resolver returns the authored [`Classification`] when present
4933 /// and the substrate default [`Classification::gate_compute`] on
4934 /// absence. Because [`Classification::gate_compute`] carries
4935 /// [`crate::classification::SubstrateType::Compute`] (the
4936 /// canonical resource-plane substrate), a bare ephemeral spec
4937 /// with no `:classification` slot answers `true` — a regression
4938 /// that dropped the resolver hop, probed the wrong closed-set
4939 /// arm, or inverted the projection fails HERE at ONE narrow
4940 /// substrate site before drifting through every unadorned
4941 /// ephemeral spec's plane-baseline answer.
4942 ///
4943 /// # Compounding — opens the substrate axis on the ephemeral surface
4944 ///
4945 /// The ephemeral require-tag classifier composes this primitive
4946 /// as a fixed tag `resource-substrate` on
4947 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
4948 /// surface's `resource-substrate` fixed tag on
4949 /// `POINT_FIXED_TAG_ARMS` via
4950 /// [`Classification::substrate_is_resource`] directly. The two-
4951 /// surface parity contract holds by construction: both surfaces
4952 /// route through the SAME
4953 /// [`Classification::substrate_is_resource`] primitive after the
4954 /// ephemeral surface pays ONE resolver hop. FIRST ephemeral-
4955 /// surface peer on the `substrate` axis — future sibling
4956 /// projections [`crate::classification::SubstrateType::is_policy`]
4957 /// and [`crate::classification::SubstrateType::is_telemetry`]
4958 /// compose byte-identically as future tenth + eleventh peers,
4959 /// closing the axis into a proven-repeatable three-peer sub-
4960 /// corner exactly as the `point_type` axis was closed on this
4961 /// surface by
4962 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
4963 ///
4964 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
4965 /// preserves proofs; the classification-`substrate`-axis derived-
4966 /// nullary-boolean probe body composes ONE resolver primitive
4967 /// ([`Self::resolved_classification`]) with ONE
4968 /// [`Classification`] primitive
4969 /// ([`Classification::substrate_is_resource`]) so every
4970 /// downstream (`resource-substrate` fixed tags on both surfaces
4971 /// in tatara-check, future plane-baseline / compliance-baseline
4972 /// selectors, future variant additions on
4973 /// [`crate::classification::SubstrateType`]) binds through the
4974 /// SAME `substrate_is_resource()` shape rather than restating
4975 /// either the resolver walk or the closed-set projection
4976 /// composition at the callsite. THEORY.md §VI.1 — generation
4977 /// over composition; a future
4978 /// [`crate::classification::SubstrateType`] variant lands at ONE
4979 /// `ALL` entry + ONE `is_resource` arm on the closed set and
4980 /// both surfaces pick it up mechanically.
4981 #[must_use]
4982 pub fn substrate_is_resource(&self) -> bool {
4983 self.resolved_classification().substrate_is_resource()
4984 }
4985
4986 /// Derived-boolean predicate — does this ephemeral spec's
4987 /// resolved [`Classification`]'s
4988 /// [`crate::classification::SubstrateType`] project to `true`
4989 /// under [`crate::classification::SubstrateType::is_policy`]?
4990 /// Byte-for-byte peer of
4991 /// [`Classification::substrate_is_policy`] wrapped through the
4992 /// [`Self::resolved_classification`] resolver so an operator-
4993 /// omitted `:classification` slot on `(defephemeral …)` still
4994 /// answers via the substrate default. The ONE ephemeral-surface
4995 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
4996 /// derived-nullary-boolean walk on the policy-plane bucket
4997 /// question over the classification-`substrate` axis.
4998 ///
4999 /// # Tenth derived-nullary-boolean peer on the ephemeral surface
5000 ///
5001 /// Peer of [`Self::horizon_terminates`],
5002 /// [`Self::horizon_requires_metric_axes`],
5003 /// [`Self::calm_requires_coordination`],
5004 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
5005 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
5006 /// [`Self::point_is_convergent`], and
5007 /// [`Self::substrate_is_resource`] on the ephemeral surface's
5008 /// (resolver-hop × derived-nullary-bool) shape — the TENTH peer
5009 /// overall and the SECOND peer threading the classification-
5010 /// `substrate` axis, promoting that axis on this surface from a
5011 /// proven-repeatable one-off to a proven-repeatable pair.
5012 /// FIRST ephemeral-surface substrate-axis corner-peer pair
5013 /// carrying a non-trivial closed-set-internal MUTEX relationship
5014 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`), structural
5015 /// twin of the sibling `point_type`-axis MUTEX pair sealed on
5016 /// this surface by
5017 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
5018 /// The resolver-hop shape is byte-identical across all ten peers.
5019 ///
5020 /// # Semantics — resolver hop + derived-nullary-boolean
5021 ///
5022 /// `substrate_is_policy()` returns `true` iff
5023 /// `self.resolved_classification().substrate_is_policy()`. The
5024 /// resolver returns the authored [`Classification`] when present
5025 /// and the substrate default [`Classification::gate_compute`] on
5026 /// absence. Because [`Classification::gate_compute`] carries
5027 /// [`crate::classification::SubstrateType::Compute`] (the
5028 /// canonical resource-plane substrate, NOT a policy plane), a
5029 /// bare ephemeral spec with no `:classification` slot answers
5030 /// `false` — a regression that dropped the resolver hop, probed
5031 /// the wrong closed-set arm, or inverted the projection fails
5032 /// HERE at ONE narrow substrate site before drifting through
5033 /// every unadorned ephemeral spec's plane-baseline answer.
5034 ///
5035 /// # Compounding — second substrate-axis peer on the ephemeral surface
5036 ///
5037 /// The ephemeral require-tag classifier composes this primitive
5038 /// as a fixed tag `policy-substrate` on
5039 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5040 /// surface's `policy-substrate` fixed tag on
5041 /// `POINT_FIXED_TAG_ARMS` via
5042 /// [`Classification::substrate_is_policy`] directly. The two-
5043 /// surface parity contract holds by construction: both surfaces
5044 /// route through the SAME
5045 /// [`Classification::substrate_is_policy`] primitive after the
5046 /// ephemeral surface pays ONE resolver hop. SECOND ephemeral-
5047 /// surface peer on the `substrate` axis — sibling projection
5048 /// [`crate::classification::SubstrateType::is_telemetry`]
5049 /// composes byte-identically as a future eleventh peer, closing
5050 /// the axis into a proven-repeatable three-peer sub-corner
5051 /// exactly as the `point_type` axis was closed on this surface
5052 /// by
5053 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5054 ///
5055 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5056 /// preserves proofs; the classification-`substrate`-axis derived-
5057 /// nullary-boolean probe body composes ONE resolver primitive
5058 /// ([`Self::resolved_classification`]) with ONE
5059 /// [`Classification`] primitive
5060 /// ([`Classification::substrate_is_policy`]) so every
5061 /// downstream (`policy-substrate` fixed tags on both surfaces
5062 /// in tatara-check, future plane-baseline / compliance-baseline
5063 /// selectors, future variant additions on
5064 /// [`crate::classification::SubstrateType`]) binds through the
5065 /// SAME `substrate_is_policy()` shape rather than restating
5066 /// either the resolver walk or the closed-set projection
5067 /// composition at the callsite. THEORY.md §VI.1 — generation
5068 /// over composition; a future
5069 /// [`crate::classification::SubstrateType`] variant lands at ONE
5070 /// `ALL` entry + ONE `is_policy` arm on the closed set and
5071 /// both surfaces pick it up mechanically.
5072 #[must_use]
5073 pub fn substrate_is_policy(&self) -> bool {
5074 self.resolved_classification().substrate_is_policy()
5075 }
5076
5077 /// Derived-boolean predicate — does this ephemeral spec's
5078 /// resolved [`Classification`]'s
5079 /// [`crate::classification::SubstrateType`] project to `true`
5080 /// under [`crate::classification::SubstrateType::is_telemetry`]?
5081 /// Byte-for-byte peer of
5082 /// [`Classification::substrate_is_telemetry`] wrapped through
5083 /// the [`Self::resolved_classification`] resolver so an operator-
5084 /// omitted `:classification` slot on `(defephemeral …)` still
5085 /// answers via the substrate default. The ONE ephemeral-surface
5086 /// substrate primitive that owns the `(&EphemeralSpec) -> bool`
5087 /// derived-nullary-boolean walk on the telemetry-plane bucket
5088 /// question over the classification-`substrate` axis.
5089 ///
5090 /// # Eleventh derived-nullary-boolean peer on the ephemeral surface — CLOSES the substrate axis
5091 ///
5092 /// Peer of [`Self::horizon_terminates`],
5093 /// [`Self::horizon_requires_metric_axes`],
5094 /// [`Self::calm_requires_coordination`],
5095 /// [`Self::data_is_regulated`], [`Self::data_is_restricted`],
5096 /// [`Self::point_is_endomorphic`], [`Self::point_is_diffusive`],
5097 /// [`Self::point_is_convergent`], [`Self::substrate_is_resource`],
5098 /// and [`Self::substrate_is_policy`] on the ephemeral surface's
5099 /// (resolver-hop × derived-nullary-bool) shape — the ELEVENTH
5100 /// peer overall and the THIRD peer threading the classification-
5101 /// `substrate` axis. This peer CLOSES the substrate axis on the
5102 /// ephemeral surface into the FULL three-way XOR partition
5103 /// contract `substrate_is_resource ⊕ substrate_is_policy ⊕
5104 /// substrate_is_telemetry` — sealed on this surface by
5105 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
5106 /// the resolver-hop peer of the parent-composed
5107 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`.
5108 /// Structural twin of the sibling `point_type`-axis ternary lift
5109 /// sealed on this surface by
5110 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5111 /// The resolver-hop shape is byte-identical across all eleven
5112 /// peers.
5113 ///
5114 /// # Semantics — resolver hop + derived-nullary-boolean
5115 ///
5116 /// `substrate_is_telemetry()` returns `true` iff
5117 /// `self.resolved_classification().substrate_is_telemetry()`.
5118 /// The resolver returns the authored [`Classification`] when
5119 /// present and the substrate default [`Classification::gate_compute`]
5120 /// on absence. Because [`Classification::gate_compute`] carries
5121 /// [`crate::classification::SubstrateType::Compute`] (the
5122 /// canonical resource-plane substrate, NOT a telemetry plane),
5123 /// a bare ephemeral spec with no `:classification` slot answers
5124 /// `false` — a regression that dropped the resolver hop, probed
5125 /// the wrong closed-set arm, or inverted the projection fails
5126 /// HERE at ONE narrow substrate site before drifting through
5127 /// every unadorned ephemeral spec's plane-baseline answer.
5128 ///
5129 /// # Compounding — CLOSES the substrate axis on the ephemeral surface
5130 ///
5131 /// The ephemeral require-tag classifier composes this primitive
5132 /// as a fixed tag `telemetry-substrate` on
5133 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5134 /// surface's `telemetry-substrate` fixed tag on
5135 /// `POINT_FIXED_TAG_ARMS` via
5136 /// [`Classification::substrate_is_telemetry`] directly. The two-
5137 /// surface parity contract holds by construction: both surfaces
5138 /// route through the SAME
5139 /// [`Classification::substrate_is_telemetry`] primitive after the
5140 /// ephemeral surface pays ONE resolver hop. THIRD ephemeral-
5141 /// surface peer on the `substrate` axis — closes the axis into a
5142 /// proven-repeatable three-peer sub-corner exactly as the
5143 /// `point_type` axis was closed on this surface by
5144 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
5145 ///
5146 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5147 /// preserves proofs; the classification-`substrate`-axis derived-
5148 /// nullary-boolean probe body composes ONE resolver primitive
5149 /// ([`Self::resolved_classification`]) with ONE
5150 /// [`Classification`] primitive
5151 /// ([`Classification::substrate_is_telemetry`]) so every
5152 /// downstream (`telemetry-substrate` fixed tags on both surfaces
5153 /// in tatara-check, future plane-baseline / compliance-baseline
5154 /// selectors, future variant additions on
5155 /// [`crate::classification::SubstrateType`]) binds through the
5156 /// SAME `substrate_is_telemetry()` shape rather than restating
5157 /// either the resolver walk or the closed-set projection
5158 /// composition at the callsite. THEORY.md §VI.1 — generation
5159 /// over composition; a future
5160 /// [`crate::classification::SubstrateType`] variant lands at ONE
5161 /// `ALL` entry + ONE `is_telemetry` arm on the closed set and
5162 /// both surfaces pick it up mechanically.
5163 #[must_use]
5164 pub fn substrate_is_telemetry(&self) -> bool {
5165 self.resolved_classification().substrate_is_telemetry()
5166 }
5167
5168 /// Derived-boolean predicate — does this ephemeral spec's
5169 /// resolved [`Classification`]'s
5170 /// [`crate::classification::CalmClassification`] project to `true`
5171 /// under [`crate::classification::CalmClassification::is_monotone`]?
5172 /// Byte-for-byte peer of [`Classification::calm_is_monotone`]
5173 /// wrapped through the [`Self::resolved_classification`] resolver
5174 /// so an operator-omitted `:classification` slot on
5175 /// `(defephemeral …)` still answers via the substrate default.
5176 /// The ONE ephemeral-surface substrate primitive that owns the
5177 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5178 /// CALM-monotone-plane question — the positive framing peer of
5179 /// [`Self::calm_requires_coordination`].
5180 ///
5181 /// # Twelfth derived-nullary-boolean peer on the ephemeral surface — CLOSES the calm axis
5182 ///
5183 /// Peer of [`Self::horizon_terminates`],
5184 /// [`Self::horizon_requires_metric_axes`],
5185 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5186 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5187 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5188 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5189 /// and [`Self::substrate_is_telemetry`] on the ephemeral
5190 /// surface's (resolver-hop × derived-nullary-bool) shape — the
5191 /// TWELFTH peer overall and the SECOND peer threading the
5192 /// classification-`calm` axis. This peer CLOSES the calm axis
5193 /// on the ephemeral surface into the FULL binary XOR partition
5194 /// contract `calm_is_monotone ⊕ calm_requires_coordination` —
5195 /// sealed on this surface by
5196 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
5197 /// the resolver-hop peer of the parent-composed
5198 /// `classification_calm_probes_form_binary_xor_partition_over_all`.
5199 /// Structural twin of the sibling horizon-axis binary XOR
5200 /// sealed on the closed set by
5201 /// `horizon_kind_terminate_xor_requires_metric_axes`, lifted
5202 /// through the resolver hop to the ephemeral surface. The
5203 /// resolver-hop shape is byte-identical across all twelve peers.
5204 ///
5205 /// # Semantics — resolver hop + derived-nullary-boolean
5206 ///
5207 /// `calm_is_monotone()` returns `true` iff
5208 /// `self.resolved_classification().calm_is_monotone()`. The
5209 /// resolver returns the authored [`Classification`] when present
5210 /// and the substrate default [`Classification::gate_compute`] on
5211 /// absence. Because [`Classification::gate_compute`] carries
5212 /// [`crate::classification::CalmClassification::default =
5213 /// Monotone`] via `#[default]`, a bare ephemeral spec with no
5214 /// `:classification` slot answers `true` — every unadorned
5215 /// `(defephemeral …)` reads as gossip-eligible under the
5216 /// positive CALM framing, safe under Hellerstein's theorem
5217 /// (monotone operations distribute without coordination). A
5218 /// regression that dropped the resolver hop, probed the wrong
5219 /// closed-set arm, or inverted the projection fails HERE at ONE
5220 /// narrow substrate site before drifting through every
5221 /// unadorned ephemeral spec's positive-CALM-framing answer.
5222 /// Mirror-inverted from the sibling
5223 /// `calm_requires_coordination_probes_false_on_absent_classification`
5224 /// (both walk the SAME defaulted `calm` field, so
5225 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
5226 /// closed set's disjoint XOR partition).
5227 ///
5228 /// # Compounding — CLOSES the calm axis on the ephemeral surface
5229 ///
5230 /// The ephemeral require-tag classifier composes this primitive
5231 /// as a fixed tag `monotone-calm` on `EPHEMERAL_FIXED_TAG_ARMS`
5232 /// — byte-for-byte peer of the point surface's `monotone-calm`
5233 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
5234 /// [`Classification::calm_is_monotone`] directly. The two-
5235 /// surface parity contract holds by construction: both surfaces
5236 /// route through the SAME [`Classification::calm_is_monotone`]
5237 /// primitive after the ephemeral surface pays ONE resolver hop.
5238 /// SECOND ephemeral-surface peer on the `calm` axis — CLOSES the
5239 /// axis into a proven-repeatable two-peer sub-corner exactly as
5240 /// the `horizon` axis is closed on the closed-set layer by
5241 /// `horizon_kind_terminate_xor_requires_metric_axes`.
5242 ///
5243 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5244 /// preserves proofs; the classification-`calm`-axis derived-
5245 /// nullary-boolean probe body composes ONE resolver primitive
5246 /// ([`Self::resolved_classification`]) with ONE
5247 /// [`Classification`] primitive
5248 /// ([`Classification::calm_is_monotone`]) so every downstream
5249 /// (`monotone-calm` fixed tags on both surfaces in tatara-check,
5250 /// future scheduler / gossip-eligibility validators reading the
5251 /// positive CALM framing, future variant additions on
5252 /// [`crate::classification::CalmClassification`]) binds through
5253 /// the SAME `calm_is_monotone()` shape rather than restating
5254 /// either the resolver walk or the closed-set projection
5255 /// composition at the callsite. THEORY.md §VI.1 — generation
5256 /// over composition; a future
5257 /// [`crate::classification::CalmClassification`] variant lands
5258 /// at ONE `ALL` entry + ONE `is_monotone` arm on the closed set
5259 /// and both surfaces pick it up mechanically.
5260 #[must_use]
5261 pub fn calm_is_monotone(&self) -> bool {
5262 self.resolved_classification().calm_is_monotone()
5263 }
5264
5265 /// Derived-boolean predicate — does this ephemeral spec's
5266 /// resolved [`Classification`]'s
5267 /// [`crate::classification::DataClassification`] project to `true`
5268 /// under [`crate::classification::DataClassification::is_public`]?
5269 /// Byte-for-byte peer of [`Classification::data_is_public`]
5270 /// wrapped through the [`Self::resolved_classification`] resolver
5271 /// so an operator-omitted `:classification` slot on
5272 /// `(defephemeral …)` still answers via the substrate default.
5273 /// The ONE ephemeral-surface substrate primitive that owns the
5274 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5275 /// freely-distributable-data question — the positive framing peer
5276 /// of [`Self::data_is_restricted`].
5277 ///
5278 /// # Thirteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the data axis
5279 ///
5280 /// Peer of [`Self::horizon_terminates`],
5281 /// [`Self::horizon_requires_metric_axes`],
5282 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5283 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5284 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5285 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5286 /// [`Self::substrate_is_telemetry`], and [`Self::calm_is_monotone`]
5287 /// on the ephemeral surface's (resolver-hop × derived-nullary-bool)
5288 /// shape — the THIRTEENTH peer overall and the THIRD peer
5289 /// threading the classification-`data_classification` axis. This
5290 /// peer CLOSES the data axis on the ephemeral surface into the
5291 /// FULL binary XOR partition contract
5292 /// `data_is_public ⊕ data_is_restricted` — sealed on this surface
5293 /// by `ephemeral_data_probes_form_binary_xor_partition_over_all`,
5294 /// the resolver-hop peer of the parent-composed
5295 /// `classification_data_probes_form_binary_xor_partition_over_all`.
5296 /// Structural twin of the sibling calm-axis binary XOR sealed on
5297 /// this surface by
5298 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
5299 /// lifted through the resolver hop from the six-variant data-axis
5300 /// closed set to the ephemeral surface. The resolver-hop shape is
5301 /// byte-identical across all thirteen peers.
5302 ///
5303 /// # Semantics — resolver hop + derived-nullary-boolean
5304 ///
5305 /// `data_is_public()` returns `true` iff
5306 /// `self.resolved_classification().data_is_public()`. The
5307 /// resolver returns the authored [`Classification`] when present
5308 /// and the substrate default [`Classification::gate_compute`] on
5309 /// absence. Because [`Classification::gate_compute`] carries
5310 /// [`crate::classification::DataClassification::default =
5311 /// Internal`] via `#[default]`, a bare ephemeral spec with no
5312 /// `:classification` slot answers `false` — every unadorned
5313 /// `(defephemeral …)` reads as access-controlled by default (safe
5314 /// under compliance baseline: an operator must deliberately opt
5315 /// the dataset into public distribution rather than the substrate
5316 /// silently promoting an unadorned Process onto the freely-
5317 /// distributable path). A regression that dropped the resolver
5318 /// hop, probed the wrong closed-set arm, or inverted the
5319 /// projection fails HERE at ONE narrow substrate site before
5320 /// drifting through every unadorned ephemeral spec's positive-
5321 /// distribution-framing answer. Mirror-inverted from the sibling
5322 /// `data_is_restricted_probes_true_on_absent_classification`
5323 /// (both walk the SAME defaulted `data_classification` field, so
5324 /// `is_restricted = true` ⇒ `is_public = false` on the closed
5325 /// set's disjoint XOR partition).
5326 ///
5327 /// # Compounding — CLOSES the data axis on the ephemeral surface
5328 ///
5329 /// The ephemeral require-tag classifier composes this primitive
5330 /// as a fixed tag `public-data` on `EPHEMERAL_FIXED_TAG_ARMS`
5331 /// — byte-for-byte peer of the point surface's `public-data`
5332 /// fixed tag on `POINT_FIXED_TAG_ARMS` via
5333 /// [`Classification::data_is_public`] directly. The two-
5334 /// surface parity contract holds by construction: both surfaces
5335 /// route through the SAME [`Classification::data_is_public`]
5336 /// primitive after the ephemeral surface pays ONE resolver hop.
5337 /// THIRD ephemeral-surface peer on the `data_classification` axis
5338 /// — CLOSES the axis into a proven-repeatable three-peer sub-
5339 /// corner (data_is_regulated, data_is_restricted, data_is_public)
5340 /// whose complementary XOR partition seals on the closed set by
5341 /// `data_classification_public_xor_restricted` and composes
5342 /// through the resolver hop as a substrate-wide theorem.
5343 ///
5344 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5345 /// preserves proofs; the classification-`data_classification`-axis
5346 /// derived-nullary-boolean probe body composes ONE resolver
5347 /// primitive ([`Self::resolved_classification`]) with ONE
5348 /// [`Classification`] primitive
5349 /// ([`Classification::data_is_public`]) so every downstream
5350 /// (`public-data` fixed tags on both surfaces in tatara-check,
5351 /// future compliance-baseline / audit-log-optional validators
5352 /// reading the positive distribution framing, future variant
5353 /// additions on
5354 /// [`crate::classification::DataClassification`]) binds through
5355 /// the SAME `data_is_public()` shape rather than restating either
5356 /// the resolver walk or the closed-set projection composition at
5357 /// the callsite. THEORY.md §VI.1 — generation over composition; a
5358 /// future [`crate::classification::DataClassification`] variant
5359 /// lands at ONE `ALL` entry + ONE `is_public` arm on the closed
5360 /// set and both surfaces pick it up mechanically.
5361 #[must_use]
5362 pub fn data_is_public(&self) -> bool {
5363 self.resolved_classification().data_is_public()
5364 }
5365
5366 /// Derived-boolean predicate — does this ephemeral spec's resolved
5367 /// [`Classification`]'s
5368 /// [`crate::classification::Horizon::direction`] slot (defaulted
5369 /// through [`crate::classification::OptimizationDirection::default =
5370 /// Minimize`] on absence) project to `true` under
5371 /// [`crate::classification::OptimizationDirection::prefers_lower`]?
5372 /// Byte-for-byte peer of
5373 /// [`crate::classification::Classification::direction_prefers_lower`]
5374 /// wrapped through the [`Self::resolved_classification`] resolver so
5375 /// an operator-omitted `:classification` slot on
5376 /// `(defephemeral …)` still answers via the substrate default. The
5377 /// ONE ephemeral-surface substrate primitive that owns the
5378 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5379 /// lower-is-better optimization-polarity question.
5380 ///
5381 /// # Fourteenth derived-nullary-boolean peer on the ephemeral surface — opens the optimization-direction axis
5382 ///
5383 /// Peer of the thirteen prior nullary-boolean substrate primitives
5384 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5385 /// [`Self::horizon_requires_metric_axes`],
5386 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5387 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5388 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5389 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5390 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5391 /// [`Self::data_is_public`]) on the ephemeral surface's
5392 /// (resolver-hop × derived-nullary-bool) shape — the FOURTEENTH
5393 /// peer overall and the FIRST peer threading the classification-
5394 /// `horizon.direction` axis on this surface. Opens the SIXTH
5395 /// classification axis into the ephemeral fixed-tag algebra after
5396 /// the horizon, calm, data, point, and substrate axes. The
5397 /// resolver-hop shape is byte-identical across all fourteen peers.
5398 ///
5399 /// # Semantics — resolver hop + derived-nullary-boolean
5400 ///
5401 /// `direction_prefers_lower()` returns `true` iff
5402 /// `self.resolved_classification().direction_prefers_lower()`. The
5403 /// resolver returns the authored [`Classification`] when present
5404 /// and the substrate default [`Classification::gate_compute`] on
5405 /// absence. Because [`Classification::gate_compute`] carries
5406 /// `horizon: Horizon::default()` whose `direction` field is `None`,
5407 /// and [`crate::classification::OptimizationDirection::default =
5408 /// Minimize`] projects `prefers_lower = true`, a bare ephemeral
5409 /// spec with no `:classification` slot answers `true` — every
5410 /// unadorned `(defephemeral …)` reads as lower-is-better under the
5411 /// substrate polarity default (safe under the asymptotic-health
5412 /// rate-window evaluator's convention: an operator must
5413 /// deliberately opt into Maximize polarity rather than the
5414 /// substrate silently flipping every unadorned Process onto the
5415 /// higher-is-better path). A regression that dropped the resolver
5416 /// hop, probed the wrong closed-set arm, or inverted the projection
5417 /// fails HERE at ONE narrow substrate site before drifting through
5418 /// every unadorned ephemeral spec's rate-window evaluator polarity.
5419 ///
5420 /// # Compounding — opens the optimization-direction axis on the ephemeral surface
5421 ///
5422 /// The ephemeral require-tag classifier composes this primitive as
5423 /// a fixed tag `prefers-lower-direction` on
5424 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5425 /// surface's `prefers-lower-direction` fixed tag on
5426 /// `POINT_FIXED_TAG_ARMS` via
5427 /// [`Classification::direction_prefers_lower`] directly. The
5428 /// two-surface parity contract holds by construction: both surfaces
5429 /// route through the SAME [`Classification::direction_prefers_lower`]
5430 /// primitive after the ephemeral surface pays ONE resolver hop.
5431 /// A future antisymmetric peer (`direction_prefers_higher`) closes
5432 /// the binary XOR partition on this axis — mirror of the calm-axis
5433 /// (`monotone-calm ⊕ coordination-required`) and data-axis
5434 /// (`public-data ⊕ data-restricted`) closures on this surface.
5435 ///
5436 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5437 /// preserves proofs; the classification-`horizon.direction`-axis
5438 /// derived-nullary-boolean probe body composes ONE resolver
5439 /// primitive ([`Self::resolved_classification`]) with ONE
5440 /// [`Classification`] primitive
5441 /// ([`Classification::direction_prefers_lower`]) so every
5442 /// downstream (the `prefers-lower-direction` fixed tags on both
5443 /// surfaces in tatara-check, future asymptotic-health rate-window
5444 /// / regression-detector evaluators, future variant additions on
5445 /// [`crate::classification::OptimizationDirection`]) binds through
5446 /// the SAME `direction_prefers_lower()` shape rather than restating
5447 /// either the resolver walk or the closed-set projection
5448 /// composition at the callsite. THEORY.md §VI.1 — generation over
5449 /// composition; a future
5450 /// [`crate::classification::OptimizationDirection`] variant lands
5451 /// at ONE `ALL` entry + ONE `prefers_lower` arm on the closed set
5452 /// and both surfaces pick it up mechanically.
5453 #[must_use]
5454 pub fn direction_prefers_lower(&self) -> bool {
5455 self.resolved_classification().direction_prefers_lower()
5456 }
5457
5458 /// POSITIVE-FRAMING PEER of [`Self::direction_prefers_lower`] —
5459 /// does this ephemeral spec's resolved [`Classification`]'s
5460 /// [`crate::classification::Horizon::direction`] slot (defaulted
5461 /// through [`crate::classification::OptimizationDirection::default =
5462 /// Minimize`] on absence) project to `true` under
5463 /// [`crate::classification::OptimizationDirection::prefers_higher`]?
5464 /// Byte-for-byte peer of
5465 /// [`crate::classification::Classification::direction_prefers_higher`]
5466 /// wrapped through the [`Self::resolved_classification`] resolver
5467 /// so an operator-omitted `:classification` slot on
5468 /// `(defephemeral …)` still answers via the substrate default. The
5469 /// ONE ephemeral-surface substrate primitive that owns the
5470 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5471 /// higher-is-better optimization-polarity question.
5472 ///
5473 /// # Fifteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the optimization-direction axis
5474 ///
5475 /// Peer of the fourteen prior nullary-boolean substrate primitives
5476 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5477 /// [`Self::horizon_requires_metric_axes`],
5478 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5479 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5480 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5481 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5482 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5483 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`]) on
5484 /// the ephemeral surface's (resolver-hop × derived-nullary-bool)
5485 /// shape — the FIFTEENTH peer overall and the SECOND peer
5486 /// threading the classification-`horizon.direction` axis on this
5487 /// surface. CLOSES the SIXTH classification axis into a binary XOR
5488 /// partition on the ephemeral surface after the horizon, calm,
5489 /// data, point, and substrate axes — completing the axis-coverage
5490 /// milestone on this surface: ALL SIX classification axes now
5491 /// have their partitions closed at the ephemeral-surface derived-
5492 /// nullary corner. The resolver-hop shape is byte-identical across
5493 /// all fifteen peers.
5494 ///
5495 /// # Semantics — resolver hop + derived-nullary-boolean
5496 ///
5497 /// `direction_prefers_higher()` returns `true` iff
5498 /// `self.resolved_classification().direction_prefers_higher()`.
5499 /// The resolver returns the authored [`Classification`] when
5500 /// present and the substrate default
5501 /// [`Classification::gate_compute`] on absence. Because
5502 /// [`Classification::gate_compute`] carries `horizon:
5503 /// Horizon::default()` whose `direction` field is `None`, and
5504 /// [`crate::classification::OptimizationDirection::default =
5505 /// Minimize`] projects `prefers_higher = false`, a bare ephemeral
5506 /// spec with no `:classification` slot answers `false` — every
5507 /// unadorned `(defephemeral …)` reads as lower-is-better under the
5508 /// substrate polarity default (safe under the asymptotic-health
5509 /// rate-window evaluator's convention: an operator must
5510 /// deliberately opt into Maximize polarity rather than the
5511 /// substrate silently flipping every unadorned Process onto the
5512 /// higher-is-better path). A regression that dropped the resolver
5513 /// hop, probed the wrong closed-set arm, or inverted the
5514 /// projection fails HERE at ONE narrow substrate site before
5515 /// drifting through every unadorned ephemeral spec's rate-window
5516 /// evaluator polarity.
5517 ///
5518 /// # Compounding — CLOSES the optimization-direction axis on the ephemeral surface
5519 ///
5520 /// The ephemeral require-tag classifier composes this primitive as
5521 /// a fixed tag `prefers-higher-direction` on
5522 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5523 /// surface's `prefers-higher-direction` fixed tag on
5524 /// `POINT_FIXED_TAG_ARMS` via
5525 /// [`Classification::direction_prefers_higher`] directly. The
5526 /// two-surface parity contract holds by construction: both
5527 /// surfaces route through the SAME
5528 /// [`Classification::direction_prefers_higher`] primitive after
5529 /// the ephemeral surface pays ONE resolver hop. SECOND
5530 /// optimization-direction-axis peer CLOSES the axis into the FULL
5531 /// binary XOR partition contract on this surface — the resolver-
5532 /// hop peer of the parent-composed
5533 /// `classification_direction_probes_form_binary_xor_partition_over_all`,
5534 /// mirror of the calm-axis (`monotone-calm ⊕ coordination-required`)
5535 /// and data-axis (`public-data ⊕ data-restricted`) closures on
5536 /// this surface.
5537 ///
5538 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5539 /// preserves proofs; the classification-`horizon.direction`-axis
5540 /// derived-nullary-boolean probe body composes ONE resolver
5541 /// primitive ([`Self::resolved_classification`]) with ONE
5542 /// [`Classification`] primitive
5543 /// ([`Classification::direction_prefers_higher`]) so every
5544 /// downstream (the `prefers-higher-direction` fixed tags on both
5545 /// surfaces in tatara-check, future asymptotic-health rate-window
5546 /// / regression-detector evaluators, future variant additions on
5547 /// [`crate::classification::OptimizationDirection`]) binds through
5548 /// the SAME `direction_prefers_higher()` shape rather than
5549 /// restating either the resolver walk or the closed-set projection
5550 /// composition at the callsite. THEORY.md §VI.1 — generation over
5551 /// composition; a future
5552 /// [`crate::classification::OptimizationDirection`] variant lands
5553 /// at ONE `ALL` entry + ONE `prefers_higher` arm on the closed set
5554 /// and both surfaces pick it up mechanically.
5555 #[must_use]
5556 pub fn direction_prefers_higher(&self) -> bool {
5557 self.resolved_classification().direction_prefers_higher()
5558 }
5559
5560 /// Derived-boolean predicate — does this ephemeral spec's resolved
5561 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5562 /// under
5563 /// [`crate::classification::ConvergencePointType::input_arity`]?
5564 /// Byte-for-byte peer of
5565 /// [`crate::classification::Classification::input_arity_is_one`]
5566 /// wrapped through the [`Self::resolved_classification`] resolver
5567 /// so an operator-omitted `:classification` slot on
5568 /// `(defephemeral …)` still answers via the substrate default. The
5569 /// ONE ephemeral-surface substrate primitive that owns the
5570 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5571 /// single-input side of the DAG-composition input-arity projection.
5572 ///
5573 /// # Sixteenth derived-nullary-boolean peer on the ephemeral surface — opens the input-arity axis
5574 ///
5575 /// Peer of the fifteen prior nullary-boolean substrate primitives
5576 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5577 /// [`Self::horizon_requires_metric_axes`],
5578 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5579 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5580 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5581 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5582 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5583 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5584 /// [`Self::direction_prefers_higher`]) on the ephemeral surface's
5585 /// (resolver-hop × derived-nullary-bool) shape — the SIXTEENTH
5586 /// peer overall and the FIRST peer threading the classification-
5587 /// `point_type`-derived input-arity axis on this surface. Opens
5588 /// the SEVENTH classification axis into the ephemeral fixed-tag
5589 /// algebra after the horizon, calm, data, point-type, substrate,
5590 /// and optimization-direction axes. First peer on the derived-
5591 /// typed-projection stratum of the ephemeral surface — composes
5592 /// an extra closed-set-level projection hop
5593 /// ([`crate::classification::ConvergencePointType::input_arity`])
5594 /// compared to the sibling `point_is_*` triple that walks the raw
5595 /// `point_type` slot through the resolver. The resolver-hop shape
5596 /// is byte-identical across all sixteen peers.
5597 ///
5598 /// # Semantics — resolver hop + derived-nullary-boolean
5599 ///
5600 /// `input_arity_is_one()` returns `true` iff
5601 /// `self.resolved_classification().input_arity_is_one()`. The
5602 /// resolver returns the authored [`Classification`] when present
5603 /// and the substrate default [`Classification::gate_compute`] on
5604 /// absence. Because [`Classification::gate_compute`] carries
5605 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5606 /// ephemeral spec with no `:classification` slot answers `false` —
5607 /// every unadorned `(defephemeral …)` lands in the multi-input
5608 /// bucket under the substrate default (`Gate` gates a
5609 /// many-to-one bucket dispatch, so the single-input bucket only
5610 /// applies to operator-authored specs on the `Transform | Fork |
5611 /// Broadcast | Observe` arms). A regression that dropped the
5612 /// resolver hop, probed the wrong closed-set arm, or crossed the
5613 /// wires with the sibling
5614 /// [`crate::classification::ConvergencePointType::output_arity`]
5615 /// projection (which disagrees on six of the eight variants) fails
5616 /// HERE at ONE narrow substrate site before drifting through
5617 /// every unadorned ephemeral spec's DAG-composition input-arity
5618 /// audit.
5619 ///
5620 /// # Compounding — opens the input-arity axis on the ephemeral surface
5621 ///
5622 /// The ephemeral require-tag classifier will compose this
5623 /// primitive as a fixed tag `single-input-arity` on
5624 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5625 /// surface's `single-input-arity` fixed tag on
5626 /// `POINT_FIXED_TAG_ARMS` via
5627 /// [`Classification::input_arity_is_one`] directly. The
5628 /// two-surface parity contract holds by construction: both
5629 /// surfaces route through the SAME
5630 /// [`Classification::input_arity_is_one`] primitive after the
5631 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5632 /// peer ([`Self::input_arity_is_many`]) closes the binary XOR
5633 /// partition on this axis — mirror of the calm-axis
5634 /// (`monotone-calm ⊕ coordination-required`), data-axis
5635 /// (`public-data ⊕ data-restricted`), and optimization-direction-
5636 /// axis (`prefers-lower-direction ⊕ prefers-higher-direction`)
5637 /// closures on this surface.
5638 ///
5639 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5640 /// preserves proofs; the classification-`point_type`-derived
5641 /// input-arity-axis derived-nullary-boolean probe body composes
5642 /// ONE resolver primitive ([`Self::resolved_classification`])
5643 /// with ONE [`Classification`] primitive
5644 /// ([`Classification::input_arity_is_one`]) so every downstream
5645 /// (the future `single-input-arity` fixed tag on the ephemeral
5646 /// surface in tatara-check, future DAG-composition input-arity
5647 /// validators keying on the single-input framing, future variant
5648 /// additions on
5649 /// [`crate::classification::ConvergencePointType`]) binds through
5650 /// the SAME `input_arity_is_one()` shape rather than restating
5651 /// either the resolver walk or the two-hop closed-set projection
5652 /// composition at the callsite. THEORY.md §VI.1 — generation over
5653 /// composition; a future
5654 /// [`crate::classification::ConvergencePointType`] variant lands
5655 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5656 /// and both surfaces pick it up mechanically.
5657 #[must_use]
5658 pub fn input_arity_is_one(&self) -> bool {
5659 self.resolved_classification().input_arity_is_one()
5660 }
5661
5662 /// ANTISYMMETRIC PEER of [`Self::input_arity_is_one`] — does
5663 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5664 /// slot project to `Arity::Many` under
5665 /// [`crate::classification::ConvergencePointType::input_arity`]?
5666 /// Byte-for-byte peer of
5667 /// [`crate::classification::Classification::input_arity_is_many`]
5668 /// wrapped through the [`Self::resolved_classification`] resolver
5669 /// so an operator-omitted `:classification` slot on
5670 /// `(defephemeral …)` still answers via the substrate default. The
5671 /// ONE ephemeral-surface substrate primitive that owns the
5672 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5673 /// multi-input side of the DAG-composition input-arity projection.
5674 ///
5675 /// # Seventeenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the input-arity axis
5676 ///
5677 /// Peer of the sixteen prior nullary-boolean substrate primitives
5678 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5679 /// [`Self::horizon_requires_metric_axes`],
5680 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5681 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5682 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5683 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5684 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5685 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5686 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`])
5687 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5688 /// bool) shape — the SEVENTEENTH peer overall and the SECOND peer
5689 /// threading the classification-`point_type`-derived input-arity
5690 /// axis on this surface. CLOSES the SEVENTH classification axis
5691 /// into the FULL binary XOR partition contract
5692 /// `input_arity_is_one ⊕ input_arity_is_many` on the ephemeral
5693 /// surface — the resolver-hop peer of the parent-composed
5694 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`.
5695 /// The resolver-hop shape is byte-identical across all seventeen
5696 /// peers.
5697 ///
5698 /// # Semantics — resolver hop + derived-nullary-boolean
5699 ///
5700 /// `input_arity_is_many()` returns `true` iff
5701 /// `self.resolved_classification().input_arity_is_many()`. The
5702 /// resolver returns the authored [`Classification`] when present
5703 /// and the substrate default [`Classification::gate_compute`] on
5704 /// absence. Because [`Classification::gate_compute`] carries
5705 /// `point_type: Gate` and `Gate.input_arity() = Many`, a bare
5706 /// ephemeral spec with no `:classification` slot answers `true` —
5707 /// every unadorned `(defephemeral …)` lands in the multi-input
5708 /// bucket under the substrate default. Direct antisymmetric
5709 /// mirror of [`Self::input_arity_is_one`] on the SAME resolver
5710 /// walk + SAME projection through the SAME closed set.
5711 ///
5712 /// # Compounding — CLOSES the input-arity axis on the ephemeral surface
5713 ///
5714 /// The ephemeral require-tag classifier will compose this
5715 /// primitive as a fixed tag `multi-input-arity` on
5716 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5717 /// surface's `multi-input-arity` fixed tag on
5718 /// `POINT_FIXED_TAG_ARMS` via
5719 /// [`Classification::input_arity_is_many`] directly. The
5720 /// two-surface parity contract holds by construction: both
5721 /// surfaces route through the SAME
5722 /// [`Classification::input_arity_is_many`] primitive after the
5723 /// ephemeral surface pays ONE resolver hop. SECOND input-arity-
5724 /// axis peer CLOSES the axis into the FULL binary XOR partition
5725 /// contract on this surface — the resolver-hop peer of the
5726 /// parent-composed
5727 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`,
5728 /// mirror of the calm-axis (`monotone-calm ⊕
5729 /// coordination-required`), data-axis (`public-data ⊕
5730 /// data-restricted`), and optimization-direction-axis
5731 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5732 /// closures on this surface — the SEVENTH classification axis to
5733 /// reach the closed XOR partition landmark on the ephemeral
5734 /// resolver-hop surface, opening the derived-typed-projection
5735 /// stratum on this surface for the first time.
5736 ///
5737 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5738 /// preserves proofs; the classification-`point_type`-derived
5739 /// input-arity-axis derived-nullary-boolean probe body composes
5740 /// ONE resolver primitive ([`Self::resolved_classification`])
5741 /// with ONE [`Classification`] primitive
5742 /// ([`Classification::input_arity_is_many`]) so every downstream
5743 /// (the future `multi-input-arity` fixed tag on the ephemeral
5744 /// surface in tatara-check, future DAG-composition input-arity
5745 /// validators keying on the multi-input framing, future variant
5746 /// additions on
5747 /// [`crate::classification::ConvergencePointType`]) binds through
5748 /// the SAME `input_arity_is_many()` shape rather than restating
5749 /// either `!self.input_arity_is_one()` or the two-hop
5750 /// `self.resolved_classification().point_type.input_arity().is_many()`
5751 /// chain at each callsite. THEORY.md §VI.1 — generation over
5752 /// composition; a future
5753 /// [`crate::classification::ConvergencePointType`] variant lands
5754 /// at ONE `ALL` entry + ONE `input_arity` arm on the closed set
5755 /// and both surfaces pick it up mechanically.
5756 #[must_use]
5757 pub fn input_arity_is_many(&self) -> bool {
5758 self.resolved_classification().input_arity_is_many()
5759 }
5760
5761 /// Derived-boolean predicate — does this ephemeral spec's resolved
5762 /// [`Classification`]'s `point_type` slot project to `Arity::One`
5763 /// under
5764 /// [`crate::classification::ConvergencePointType::output_arity`]?
5765 /// Byte-for-byte peer of
5766 /// [`crate::classification::Classification::output_arity_is_one`]
5767 /// wrapped through the [`Self::resolved_classification`] resolver
5768 /// so an operator-omitted `:classification` slot on
5769 /// `(defephemeral …)` still answers via the substrate default. The
5770 /// ONE ephemeral-surface substrate primitive that owns the
5771 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5772 /// single-output side of the DAG-composition output-arity projection.
5773 ///
5774 /// # Eighteenth derived-nullary-boolean peer on the ephemeral surface — opens the output-arity axis
5775 ///
5776 /// Peer of the seventeen prior nullary-boolean substrate primitives
5777 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5778 /// [`Self::horizon_requires_metric_axes`],
5779 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5780 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5781 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5782 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5783 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5784 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5785 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5786 /// [`Self::input_arity_is_many`]) on the ephemeral surface's
5787 /// (resolver-hop × derived-nullary-bool) shape — the EIGHTEENTH
5788 /// peer overall and the FIRST peer threading the classification-
5789 /// `point_type`-derived OUTPUT-arity axis on this surface. Opens
5790 /// the EIGHTH classification axis into the ephemeral fixed-tag
5791 /// algebra after the horizon, calm, data, point-type, substrate,
5792 /// optimization-direction, and input-arity axes. SECOND peer on
5793 /// the derived-typed-projection stratum of the ephemeral surface
5794 /// (after [`Self::input_arity_is_one`]) — composes an extra
5795 /// closed-set-level projection hop
5796 /// ([`crate::classification::ConvergencePointType::output_arity`])
5797 /// compared to the sibling `point_is_*` triple that walks the raw
5798 /// `point_type` slot through the resolver. The resolver-hop shape
5799 /// is byte-identical across all eighteen peers.
5800 ///
5801 /// # Distinctness from the input-arity axis
5802 ///
5803 /// The input-arity and output-arity axes carve the eight-variant
5804 /// [`crate::classification::ConvergencePointType`] closed set into
5805 /// DISTINCT partitions — six of the eight variants (`Fork |
5806 /// Broadcast | Join | Gate | Select | Reduce`) DISAGREE between the
5807 /// two projections, and only the two endomorphic variants
5808 /// (`Transform | Observe` — both `(One, One)`) agree. The ephemeral
5809 /// resolver-hop surface inherits this distinctness verbatim: the
5810 /// absent-classification baseline (`gate_compute` → `point_type:
5811 /// Gate`) FLIPS between the two axes — `input_arity_is_one` is
5812 /// `false` on the baseline but `output_arity_is_one` is `true`.
5813 /// So `output_arity_is_one` is NOT a redundant restatement of
5814 /// `input_arity_is_one` even after both wrap through the SAME
5815 /// resolver.
5816 ///
5817 /// # Semantics — resolver hop + derived-nullary-boolean
5818 ///
5819 /// `output_arity_is_one()` returns `true` iff
5820 /// `self.resolved_classification().output_arity_is_one()`. The
5821 /// resolver returns the authored [`Classification`] when present
5822 /// and the substrate default [`Classification::gate_compute`] on
5823 /// absence. Because [`Classification::gate_compute`] carries
5824 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5825 /// ephemeral spec with no `:classification` slot answers `true` —
5826 /// every unadorned `(defephemeral …)` lands in the single-output
5827 /// bucket under the substrate default (`Gate` gates a many-to-one
5828 /// bucket dispatch, so the multi-output bucket only applies to
5829 /// operator-authored specs on the `Fork | Broadcast` arms). A
5830 /// regression that dropped the resolver hop, probed the wrong
5831 /// closed-set arm, or crossed the wires with the sibling
5832 /// [`crate::classification::ConvergencePointType::input_arity`]
5833 /// projection (which disagrees on six of the eight variants) fails
5834 /// HERE at ONE narrow substrate site before drifting through every
5835 /// unadorned ephemeral spec's DAG-composition output-arity audit.
5836 ///
5837 /// # Compounding — opens the output-arity axis on the ephemeral surface
5838 ///
5839 /// The ephemeral require-tag classifier will compose this
5840 /// primitive as a fixed tag `single-output-arity` on
5841 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5842 /// surface's `single-output-arity` fixed tag on
5843 /// `POINT_FIXED_TAG_ARMS` via
5844 /// [`Classification::output_arity_is_one`] directly. The
5845 /// two-surface parity contract holds by construction: both
5846 /// surfaces route through the SAME
5847 /// [`Classification::output_arity_is_one`] primitive after the
5848 /// ephemeral surface pays ONE resolver hop. A future antisymmetric
5849 /// peer ([`Self::output_arity_is_many`]) closes the binary XOR
5850 /// partition on this axis — mirror of the input-arity-axis
5851 /// (`input_arity_is_one ⊕ input_arity_is_many`), the calm-axis
5852 /// (`monotone-calm ⊕ coordination-required`), the data-axis
5853 /// (`public-data ⊕ data-restricted`), and the optimization-
5854 /// direction-axis (`prefers-lower-direction ⊕
5855 /// prefers-higher-direction`) closures on this surface,
5856 /// completing the DAG-composition arity PAIR on the ephemeral
5857 /// derived-typed-projection stratum.
5858 ///
5859 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5860 /// preserves proofs; the classification-`point_type`-derived
5861 /// output-arity-axis derived-nullary-boolean probe body composes
5862 /// ONE resolver primitive ([`Self::resolved_classification`])
5863 /// with ONE [`Classification`] primitive
5864 /// ([`Classification::output_arity_is_one`]) so every downstream
5865 /// (the future `single-output-arity` fixed tag on the ephemeral
5866 /// surface in tatara-check, future DAG-composition output-arity
5867 /// validators keying on the single-output framing, future variant
5868 /// additions on
5869 /// [`crate::classification::ConvergencePointType`]) binds through
5870 /// the SAME `output_arity_is_one()` shape rather than restating
5871 /// either the resolver walk or the two-hop closed-set projection
5872 /// composition at the callsite. THEORY.md §VI.1 — generation over
5873 /// composition; a future
5874 /// [`crate::classification::ConvergencePointType`] variant lands
5875 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5876 /// and both surfaces pick it up mechanically.
5877 #[must_use]
5878 pub fn output_arity_is_one(&self) -> bool {
5879 self.resolved_classification().output_arity_is_one()
5880 }
5881
5882 /// ANTISYMMETRIC PEER of [`Self::output_arity_is_one`] — does
5883 /// this ephemeral spec's resolved [`Classification`]'s `point_type`
5884 /// slot project to `Arity::Many` under
5885 /// [`crate::classification::ConvergencePointType::output_arity`]?
5886 /// Byte-for-byte peer of
5887 /// [`crate::classification::Classification::output_arity_is_many`]
5888 /// wrapped through the [`Self::resolved_classification`] resolver
5889 /// so an operator-omitted `:classification` slot on
5890 /// `(defephemeral …)` still answers via the substrate default. The
5891 /// ONE ephemeral-surface substrate primitive that owns the
5892 /// `(&EphemeralSpec) -> bool` derived-nullary-boolean walk on the
5893 /// multi-output side of the DAG-composition output-arity projection.
5894 ///
5895 /// # Nineteenth derived-nullary-boolean peer on the ephemeral surface — CLOSES the output-arity axis
5896 ///
5897 /// Peer of the eighteen prior nullary-boolean substrate primitives
5898 /// on [`EphemeralSpec`] ([`Self::horizon_terminates`],
5899 /// [`Self::horizon_requires_metric_axes`],
5900 /// [`Self::calm_requires_coordination`], [`Self::data_is_regulated`],
5901 /// [`Self::data_is_restricted`], [`Self::point_is_endomorphic`],
5902 /// [`Self::point_is_diffusive`], [`Self::point_is_convergent`],
5903 /// [`Self::substrate_is_resource`], [`Self::substrate_is_policy`],
5904 /// [`Self::substrate_is_telemetry`], [`Self::calm_is_monotone`],
5905 /// [`Self::data_is_public`], [`Self::direction_prefers_lower`],
5906 /// [`Self::direction_prefers_higher`], [`Self::input_arity_is_one`],
5907 /// [`Self::input_arity_is_many`], [`Self::output_arity_is_one`])
5908 /// on the ephemeral surface's (resolver-hop × derived-nullary-
5909 /// bool) shape — the NINETEENTH peer overall and the SECOND peer
5910 /// threading the classification-`point_type`-derived OUTPUT-arity
5911 /// axis on this surface. CLOSES the EIGHTH classification axis
5912 /// into the FULL binary XOR partition contract
5913 /// `output_arity_is_one ⊕ output_arity_is_many` on the ephemeral
5914 /// surface — the resolver-hop peer of the parent-composed
5915 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`.
5916 /// The resolver-hop shape is byte-identical across all nineteen
5917 /// peers. Completes the DAG-composition arity PAIR on the
5918 /// ephemeral derived-typed-projection stratum
5919 /// (`input_arity_is_{one,many}` + `output_arity_is_{one,many}` on
5920 /// the SAME resolver walk through the SAME closed set).
5921 ///
5922 /// # Semantics — resolver hop + derived-nullary-boolean
5923 ///
5924 /// `output_arity_is_many()` returns `true` iff
5925 /// `self.resolved_classification().output_arity_is_many()`. The
5926 /// resolver returns the authored [`Classification`] when present
5927 /// and the substrate default [`Classification::gate_compute`] on
5928 /// absence. Because [`Classification::gate_compute`] carries
5929 /// `point_type: Gate` and `Gate.output_arity() = One`, a bare
5930 /// ephemeral spec with no `:classification` slot answers `false` —
5931 /// every unadorned `(defephemeral …)` lands in the single-output
5932 /// bucket under the substrate default. Direct antisymmetric
5933 /// mirror of [`Self::output_arity_is_one`] on the SAME resolver
5934 /// walk + SAME projection through the SAME closed set.
5935 ///
5936 /// # Compounding — CLOSES the output-arity axis on the ephemeral surface
5937 ///
5938 /// The ephemeral require-tag classifier will compose this
5939 /// primitive as a fixed tag `multi-output-arity` on
5940 /// `EPHEMERAL_FIXED_TAG_ARMS` — byte-for-byte peer of the point
5941 /// surface's `multi-output-arity` fixed tag on
5942 /// `POINT_FIXED_TAG_ARMS` via
5943 /// [`Classification::output_arity_is_many`] directly. The
5944 /// two-surface parity contract holds by construction: both
5945 /// surfaces route through the SAME
5946 /// [`Classification::output_arity_is_many`] primitive after the
5947 /// ephemeral surface pays ONE resolver hop. SECOND output-arity-
5948 /// axis peer CLOSES the axis into the FULL binary XOR partition
5949 /// contract on this surface — the resolver-hop peer of the
5950 /// parent-composed
5951 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`,
5952 /// mirror of the input-arity-axis (`input_arity_is_one ⊕
5953 /// input_arity_is_many`), the calm-axis (`monotone-calm ⊕
5954 /// coordination-required`), the data-axis (`public-data ⊕
5955 /// data-restricted`), and the optimization-direction-axis
5956 /// (`prefers-lower-direction ⊕ prefers-higher-direction`)
5957 /// closures on this surface — the EIGHTH classification axis to
5958 /// reach the closed XOR partition landmark on the ephemeral
5959 /// resolver-hop surface, completing the DAG-composition arity
5960 /// PAIR on the derived-typed-projection stratum of this surface.
5961 ///
5962 /// Theory anchor: THEORY.md §II.1 invariant 5 — composition
5963 /// preserves proofs; the classification-`point_type`-derived
5964 /// output-arity-axis derived-nullary-boolean probe body composes
5965 /// ONE resolver primitive ([`Self::resolved_classification`])
5966 /// with ONE [`Classification`] primitive
5967 /// ([`Classification::output_arity_is_many`]) so every downstream
5968 /// (the future `multi-output-arity` fixed tag on the ephemeral
5969 /// surface in tatara-check, future DAG-composition output-arity
5970 /// validators keying on the multi-output framing, future variant
5971 /// additions on
5972 /// [`crate::classification::ConvergencePointType`]) binds through
5973 /// the SAME `output_arity_is_many()` shape rather than restating
5974 /// either `!self.output_arity_is_one()` or the two-hop
5975 /// `self.resolved_classification().point_type.output_arity().is_many()`
5976 /// chain at each callsite. THEORY.md §VI.1 — generation over
5977 /// composition; a future
5978 /// [`crate::classification::ConvergencePointType`] variant lands
5979 /// at ONE `ALL` entry + ONE `output_arity` arm on the closed set
5980 /// and both surfaces pick it up mechanically.
5981 #[must_use]
5982 pub fn output_arity_is_many(&self) -> bool {
5983 self.resolved_classification().output_arity_is_many()
5984 }
5985
5986 /// True iff this ephemeral spec's [`Self::routing`] slot is
5987 /// populated AND the inner [`RoutingSpec`]'s derived
5988 /// [`RoutingForm`] equals `kind` — the substrate primitive that
5989 /// owns the (`&EphemeralSpec`, [`RoutingForm`]) → `bool` presence-
5990 /// probe shape on the sugar-surface type.
5991 ///
5992 /// # Peer to [`crate::routing::RoutingSpec::has_form`]
5993 ///
5994 /// [`RoutingSpec::has_form`] carries the same `(&self, RoutingForm)
5995 /// -> bool` signature on the inner routing carrier reached through
5996 /// the Option gate; this peer composes byte-identical semantics on
5997 /// [`EphemeralSpec`]'s direct `routing: Option<RoutingSpec>` slot,
5998 /// so both surfaces' `routing-form-<kind>` require-tag families
5999 /// route through the SAME `RoutingSpec::has_form` primitive. A
6000 /// future normalization at the probe shape (a widened return
6001 /// carrying the derived [`RoutingForm`] variant, a debug-build
6002 /// assertion on operator-set vs defaulted overrides on the
6003 /// `stable_name_claim` bool, a fleet-wide warn on `Stable`
6004 /// combined with content-hashed hostnames) lands at ONE site per
6005 /// surface and every downstream `routing-form-<kind>` require-tag
6006 /// family + closed-set audit dispatcher picks it up mechanically.
6007 ///
6008 /// # Semantics — Option-gated derived-scalar match
6009 ///
6010 /// [`EphemeralSpec::routing`] is an `Option<RoutingSpec>`: `None`
6011 /// on an in-cluster-only ephemeral env (no per-instance edges
6012 /// declared), `Some(_)` when the operator authored the
6013 /// `:routing (…)` slot. `has_routing_form(kind)` returns `true`
6014 /// iff the slot is `Some(spec)` AND `spec.has_form(kind)` — the
6015 /// Option-parent gate short-circuits `false` on `None` regardless
6016 /// of `kind`, and the reachable arm reads the DERIVED
6017 /// [`RoutingForm`] through the ONE substrate composer
6018 /// [`RoutingForm::from_is_stable`] over the child
6019 /// `stable_name_claim` bool (a `false` default projects to
6020 /// [`RoutingForm::Instance`], a `true` operator override projects
6021 /// to [`RoutingForm::Stable`]).
6022 ///
6023 /// # Corner — (Option-parent × derived-scalar-child)
6024 ///
6025 /// SAME corner as the point surface's `routing-form-<kind>`
6026 /// family (via [`crate::routing::RoutingSpec::has_form`] reached
6027 /// through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`)
6028 /// — both surfaces' Option-parent hop threads through the SAME
6029 /// `Option<RoutingSpec>` field name on their respective sugar
6030 /// structs. The [`From<EphemeralSpec>`] lowering copies
6031 /// `e.routing → ProcessSpec::routing` byte-for-byte at the
6032 /// [`From`] impl in this module (see the `routing: e.routing`
6033 /// line), so the SAME `Option<RoutingSpec>` reaches both
6034 /// surfaces' `routing-form-<kind>` families through the SAME
6035 /// [`RoutingSpec::has_form`] walk. Distinct from
6036 /// [`Self::has_teardown_policy`] on this same surface, which
6037 /// walks a required-scalar-child through no Option-parent hop.
6038 ///
6039 /// # Compounding
6040 ///
6041 /// The ephemeral require-tag classifier composes this primitive
6042 /// with the closed-set `FromStr` autoderived on [`RoutingForm`]
6043 /// through the `strip_and_classify_prefixed_kind` substrate to
6044 /// publish a `routing-form-<kind>` prefix family byte-for-byte
6045 /// symmetrical with the point surface's family via
6046 /// [`crate::routing::RoutingSpec::has_form`]. A future third
6047 /// [`RoutingForm`] variant added to `ALL` (a hypothetical
6048 /// `Anchored` for "hold the claim only for a specific
6049 /// generation") reaches BOTH surfaces' `routing-form-<kind>`
6050 /// prefix families through the SAME closed-set walk with no
6051 /// per-caller edit — the two-surface symmetry means adding a
6052 /// variant on the closed set publishes it in lockstep across
6053 /// every downstream consumer.
6054 ///
6055 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition
6056 /// preserves proofs — the Option-gated derived-scalar-carrier
6057 /// presence-probe body lives at ONE substrate site per surface
6058 /// so every downstream (`routing-form-<kind>` require-tag families
6059 /// on both surfaces in tatara-check, closed-set audit dispatchers,
6060 /// future variant additions on [`RoutingForm`]) binds through the
6061 /// SAME `has(kind)` shape rather than restating the
6062 /// `spec.routing.as_ref().is_some_and(|r| r.has_form(kind))`
6063 /// closure body at each call site). THEORY.md §VI.1 (generation
6064 /// over composition — a future variant lands at ONE `ALL` entry +
6065 /// one `as_str` arm on the closed set and the probe picks it up
6066 /// mechanically without further per-consumer edits).
6067 #[must_use]
6068 pub fn has_routing_form(&self, kind: RoutingForm) -> bool {
6069 self.routing.as_ref().is_some_and(|r| r.has_form(kind))
6070 }
6071
6072 /// True iff at least one declared export in `self.exports` would
6073 /// fire on the given terminal-reached [`ProcessPhase`] — the peer
6074 /// of [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6075 /// on the [`EphemeralSpec`] surface.
6076 ///
6077 /// # Semantics — byte-identical to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6078 ///
6079 /// Both surfaces walk the SAME slice-level substrate primitive
6080 /// [`ExportSpecSliceExt::has_applicable_at`] on their respective
6081 /// `Vec<ExportSpec>` slot: [`EphemeralSpec`]'s `exports` field is
6082 /// copied byte-for-byte into `EphemeralLifetime::exports` at the
6083 /// `From<EphemeralSpec>` lowering, so a `has_applicable_exports_at`
6084 /// query on the authored ephemeral spec answers identically to a
6085 /// `has_applicable_exports` query on the lowered `EphemeralLifetime`.
6086 /// A regression at the compound `(when, phase) → fires_on(phase)`
6087 /// walk fails at [`ExportSpecSliceExt::has_applicable_at`]'s tests
6088 /// rather than as silent drift at either surface's inherent method.
6089 ///
6090 /// # Sibling to [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6091 ///
6092 /// Same shape, same axis, same body — the point-domain surface
6093 /// composes through `spec.lifetime.resolved_ephemeral().is_some_and(
6094 /// |e| e.exports.has_applicable_at(phase))`; the ephemeral sugar
6095 /// surface reads `self.exports.has_applicable_at(phase)` directly
6096 /// because `EphemeralSpec` stores `exports: Vec<ExportSpec>` as a
6097 /// top-level field. Both routes bind through THIS ONE slice-level
6098 /// primitive so a future normalization (widening the trigger from
6099 /// a stored discriminator to a computed predicate, adding a phase
6100 /// that composes across multiple trigger arms, threading a
6101 /// per-export justification back for editor tooltips) lands at ONE
6102 /// site and every downstream inherits the shift by construction.
6103 ///
6104 /// # Compounding
6105 ///
6106 /// The ephemeral require-tag classifier composes this primitive
6107 /// with the closed-set [`ProcessPhase`]'s autoderived `FromStr`
6108 /// through the `strip_and_classify_prefixed_kind` substrate to
6109 /// publish an `exports-fire-on-<phase>` closed-set prefix family
6110 /// byte-for-byte symmetrical with the point surface's family via
6111 /// `spec.lifetime.resolved_ephemeral().is_some_and(|e|
6112 /// e.exports.has_applicable_at(phase))`. A future twelfth
6113 /// [`ProcessPhase`] variant reaches BOTH surfaces' prefix families
6114 /// through the ONE [`crate::export::ExportTrigger::fires_on`]
6115 /// exhaustive match — either the new phase inherits a per-trigger
6116 /// fire rule at that single substrate site or it collapses to
6117 /// `false` for every trigger (the current non-terminal tail),
6118 /// without a per-caller edit anywhere else.
6119 ///
6120 /// A future normalization at the compound `(when, phase) →
6121 /// fires_on(phase)` walk (a widening that returns the applicable
6122 /// exports themselves rather than a bool, a debug-build assertion
6123 /// on redundant `Always`-triggered exports coexisting with an
6124 /// `OnAttested` peer, a fleet-wide warn on empty-export ephemerals
6125 /// declaring `OnAttested` postconditions) lands at the ONE
6126 /// slice-level substrate primitive [`ExportSpecSliceExt::has_applicable_at`]
6127 /// both this method and [`crate::lifetime::EphemeralLifetime::has_applicable_exports`]
6128 /// compose against — so the two struct-level union methods stay
6129 /// symmetric by construction.
6130 ///
6131 /// Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves
6132 /// proofs — the walk composes the SAME slice-level substrate
6133 /// primitive on both this ephemeral surface and the
6134 /// [`crate::lifetime::EphemeralLifetime`] surface, so a regression
6135 /// at the compound `(when, phase) → fires_on(phase)` chain fails
6136 /// at ONE site rather than as silent drift between the two peers).
6137 /// THEORY.md §VI.1 (generation over composition — a future
6138 /// [`ProcessPhase`] variant or a future [`crate::export::ExportTrigger`]
6139 /// variant reaches both `exports-fire-on-<phase>` require-tag
6140 /// surfaces mechanically through the SAME closed-set walk).
6141 #[must_use]
6142 pub fn has_applicable_exports_at(&self, phase: ProcessPhase) -> bool {
6143 self.exports.has_applicable_at(phase)
6144 }
6145}
6146
6147impl From<EphemeralSpec> for ProcessSpec {
6148 fn from(e: EphemeralSpec) -> Self {
6149 let classification = e.classification.unwrap_or_else(default_ephemeral_class);
6150 let mut spec = Self {
6151 identity: crate::spec::IdentitySpec {
6152 parent: e.parent,
6153 name_override: None,
6154 },
6155 classification,
6156 intent: Intent {
6157 aplicacao: Some(e.aplicacao),
6158 ..Intent::default()
6159 },
6160 boundary: Boundary {
6161 preconditions: e.preconditions,
6162 postconditions: e.postconditions,
6163 timeout: e.verify_timeout,
6164 },
6165 compliance: Default::default(),
6166 depends_on: vec![],
6167 signals: Default::default(),
6168 // Routes through the ONE substrate composer
6169 // [`Lifetime::ephemeral`] — pre-lift this was one of
6170 // ELEVEN+ hand-authored `Lifetime { ephemeral: Some(<e>),
6171 // .. }` sites past the ★★ PRIME-DIRECTIVE ≥ 2 threshold.
6172 // See the composer's doc-comment for the full migration
6173 // rationale.
6174 lifetime: Lifetime::ephemeral(EphemeralLifetime {
6175 ttl: e.ttl,
6176 teardown_policy: e.teardown,
6177 max_concurrent: e.max_concurrent,
6178 exports: e.exports,
6179 }),
6180 // R5 — propagate routing template (None = no edges).
6181 routing: e.routing,
6182 // EncapsulatesSpec isn't exposed via EphemeralSpec sugar;
6183 // operators wanting Adopt/Observe author the full
6184 // (defpoint …) form. Sugar path stays greenfield-Manage.
6185 encapsulates: None,
6186 suspended: false,
6187 };
6188 // Belt-and-suspenders: make sure exactly-one Intent invariant holds.
6189 spec.intent.nix = None;
6190 spec.intent.flux = None;
6191 spec.intent.lisp = None;
6192 spec.intent.container = None;
6193 spec.intent.guest = None;
6194 spec
6195 }
6196}
6197
6198fn default_ephemeral_class() -> Classification {
6199 // Delegates through the substrate `(Gate, Compute)` baseline owner
6200 // so the shape lives at ONE workspace-wide site — see
6201 // [`Classification::gate_compute`] for the pre-lift ten-callsite
6202 // duplication history and the sibling-default correspondence
6203 // pinned there.
6204 Classification::gate_compute()
6205}
6206
6207/// Compile a `(defephemeral …)` Lisp source into named `EphemeralSpec` values.
6208pub fn compile_ephemeral_source(
6209 src: &str,
6210) -> tatara_lisp::Result<Vec<tatara_lisp::NamedDefinition<EphemeralSpec>>> {
6211 tatara_lisp::compile_named::<EphemeralSpec>(src)
6212}
6213
6214#[cfg(test)]
6215mod tests {
6216 use super::*;
6217 use crate::boundary::{assert_slice_refinement_composition_laws, ConditionKind};
6218 use crate::classification::{
6219 Arity, CalmClassification, ConvergencePointType, DataClassification, Horizon, HorizonKind,
6220 OptimizationDirection, SubstrateType,
6221 };
6222 use crate::intent::IntentVariant;
6223 use crate::lifetime::LifetimeVariant;
6224
6225 /// LANDMARK PIN — the (ephemeral-surface test-fixture ×
6226 /// [`Classification::gate_compute_with_axis`] on horizon-nested
6227 /// axes) sweep equivalence. Nine ephemeral-surface probe-sweep
6228 /// tests in this module (`has_horizon_kind_*`,
6229 /// `has_optimization_direction_*`, `horizon_terminates_*`,
6230 /// `horizon_requires_metric_axes_*`, `horizon_terminates_xor_*`)
6231 /// pre-sweep restated the SAME `let mut c =
6232 /// Classification::gate_compute(); c.horizon = Horizon { <slot>:
6233 /// populated, ..Horizon::default() }` five-line fixture at each
6234 /// callsite, mutating exactly ONE horizon-nested slot to
6235 /// `populated`; post-sweep each callsite reads
6236 /// [`Classification::gate_compute_with_axis(populated)`] — one
6237 /// line — and the four-baseline-slot restatement lives at ONE
6238 /// substrate primitive. This pin asserts byte-parity between the
6239 /// pre-sweep hand-authored `Horizon` struct-literal shape (both
6240 /// the [`HorizonKind::kind`] mutation shape AND the
6241 /// [`OptimizationDirection`]-into-`Some(_)` mutation shape) and
6242 /// the post-sweep composer output on every variant of each closed
6243 /// set, so a regression that either (a) changed
6244 /// [`ClassificationAxis for HorizonKind`] to stomp a non-`kind`
6245 /// sub-slot, (b) changed [`ClassificationAxis for OptimizationDirection`]
6246 /// to drop the `Some(...)` wrap, or (c) reintroduced a whole-
6247 /// `Horizon`-reset shape that dropped a sibling sub-slot would
6248 /// fail HERE at ONE landmark site before landing at the peer
6249 /// probe-sweep pins that use the composer.
6250 ///
6251 /// Byte-for-byte peer of the sibling landmark
6252 /// `with_axis_optimization_direction_overlay_wraps_variant_in_some`
6253 /// on the point-surface classification-module tests — this pin
6254 /// carries the same substrate contract through to the ephemeral-
6255 /// surface tests that consume the composer.
6256 #[test]
6257 fn gate_compute_with_axis_on_horizon_nested_axes_matches_hand_authored_shape() {
6258 for kind in HorizonKind::ALL {
6259 let via_composer = Classification::gate_compute_with_axis(kind);
6260 let mut via_hand_authored = Classification::gate_compute();
6261 via_hand_authored.horizon = Horizon {
6262 kind,
6263 ..Horizon::default()
6264 };
6265 assert_eq!(
6266 via_composer, via_hand_authored,
6267 "HorizonKind::{kind:?}: composer vs pre-sweep hand-authored struct-literal drift",
6268 );
6269 }
6270 for direction in OptimizationDirection::ALL {
6271 let via_composer = Classification::gate_compute_with_axis(direction);
6272 let mut via_hand_authored = Classification::gate_compute();
6273 via_hand_authored.horizon = Horizon {
6274 direction: Some(direction),
6275 ..Horizon::default()
6276 };
6277 assert_eq!(
6278 via_composer, via_hand_authored,
6279 "OptimizationDirection::{direction:?}: composer vs pre-sweep hand-authored struct-literal drift",
6280 );
6281 }
6282 }
6283
6284 /// Primitive-owner pin — `EphemeralSpec::with_classification_axis`
6285 /// on a `classification: None` carrier produces an ephemeral spec
6286 /// whose `classification` slot is
6287 /// `Some(Classification::gate_compute_with_axis(axis))` byte-for-
6288 /// byte on every axis-variant, and preserves every non-
6289 /// classification slot at its pre-call value. A regression that
6290 /// (a) failed to wrap the composed [`Classification`] in `Some(_)`
6291 /// on the `None`-arm, (b) mutated a sibling slot on `EphemeralSpec`
6292 /// through the axis overlay, or (c) picked a different `None`-arm
6293 /// fill-through than the sibling
6294 /// [`Self::resolved_classification`] resolver would fail HERE.
6295 #[test]
6296 fn with_classification_axis_on_none_arm_fills_through_gate_compute() {
6297 fn baseline() -> EphemeralSpec {
6298 EphemeralSpec {
6299 aplicacao: demo_overlay(),
6300 ttl: "2h".into(),
6301 teardown: TeardownPolicy::OnAttested,
6302 max_concurrent: 3,
6303 postconditions: vec![],
6304 preconditions: vec![],
6305 verify_timeout: Some("30m".into()),
6306 classification: None,
6307 parent: Some("seph.1".into()),
6308 exports: vec![],
6309 routing: None,
6310 }
6311 }
6312 // Direct-scalar axes: composer output matches
6313 // `Classification::gate_compute_with_axis(axis)` byte-for-byte,
6314 // wrapped in `Some(_)`.
6315 for kind in ConvergencePointType::ALL {
6316 let via_composer = baseline().with_classification_axis(kind);
6317 assert_eq!(
6318 via_composer.classification,
6319 Some(Classification::gate_compute_with_axis(kind)),
6320 "ConvergencePointType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6321 );
6322 }
6323 for kind in SubstrateType::ALL {
6324 let via_composer = baseline().with_classification_axis(kind);
6325 assert_eq!(
6326 via_composer.classification,
6327 Some(Classification::gate_compute_with_axis(kind)),
6328 "SubstrateType::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6329 );
6330 }
6331 for kind in CalmClassification::ALL {
6332 let via_composer = baseline().with_classification_axis(kind);
6333 assert_eq!(
6334 via_composer.classification,
6335 Some(Classification::gate_compute_with_axis(kind)),
6336 "CalmClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6337 );
6338 }
6339 for kind in DataClassification::ALL {
6340 let via_composer = baseline().with_classification_axis(kind);
6341 assert_eq!(
6342 via_composer.classification,
6343 Some(Classification::gate_compute_with_axis(kind)),
6344 "DataClassification::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6345 );
6346 }
6347 // Horizon-nested axes: same shape through the trait's
6348 // sub-slot overlay.
6349 for kind in HorizonKind::ALL {
6350 let via_composer = baseline().with_classification_axis(kind);
6351 assert_eq!(
6352 via_composer.classification,
6353 Some(Classification::gate_compute_with_axis(kind)),
6354 "HorizonKind::{kind:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6355 );
6356 }
6357 for direction in OptimizationDirection::ALL {
6358 let via_composer = baseline().with_classification_axis(direction);
6359 assert_eq!(
6360 via_composer.classification,
6361 Some(Classification::gate_compute_with_axis(direction)),
6362 "OptimizationDirection::{direction:?}: composer vs gate_compute_with_axis Some(_) drift on None-arm",
6363 );
6364 }
6365 // Non-classification slots: every one preserved byte-for-byte
6366 // across the overlay on every axis. Compare through JSON
6367 // round-trip since `AplicacaoIntent` / `ExportSpec` /
6368 // `RoutingSpec` do not carry `PartialEq`.
6369 for kind in ConvergencePointType::ALL {
6370 let via_composer = baseline().with_classification_axis(kind);
6371 let baseline_ref = baseline();
6372 assert_eq!(
6373 serde_json::to_string(&via_composer.aplicacao).unwrap(),
6374 serde_json::to_string(&baseline_ref.aplicacao).unwrap(),
6375 "aplicacao slot drifted under axis overlay for kind={kind:?}",
6376 );
6377 assert_eq!(via_composer.ttl, baseline_ref.ttl);
6378 assert_eq!(via_composer.teardown, baseline_ref.teardown);
6379 assert_eq!(via_composer.max_concurrent, baseline_ref.max_concurrent);
6380 assert_eq!(
6381 via_composer.postconditions.len(),
6382 baseline_ref.postconditions.len()
6383 );
6384 assert_eq!(
6385 via_composer.preconditions.len(),
6386 baseline_ref.preconditions.len()
6387 );
6388 assert_eq!(via_composer.verify_timeout, baseline_ref.verify_timeout);
6389 assert_eq!(via_composer.parent, baseline_ref.parent);
6390 assert_eq!(via_composer.exports.len(), baseline_ref.exports.len());
6391 assert!(via_composer.routing.is_none());
6392 }
6393 }
6394
6395 /// Primitive-owner pin —
6396 /// `EphemeralSpec::with_classification_axis` on a
6397 /// `classification: Some(prior)` carrier composes the axis
6398 /// overlay onto `prior` via [`ClassificationAxis::overlay`],
6399 /// preserving every OTHER axis slot on `prior`. Distinct from the
6400 /// `None`-arm pin above: the `Some(prior)` arm does NOT reset
6401 /// through [`Classification::gate_compute`], and consecutive
6402 /// `.with_classification_axis(...)` calls compose arbitrary
6403 /// N-axis conjunctions on the ephemeral surface with the same
6404 /// order-independence guarantee [`Classification::with_axis`]
6405 /// carries on distinct-slot axes.
6406 #[test]
6407 fn with_classification_axis_on_some_arm_chains_onto_prior() {
6408 fn baseline() -> EphemeralSpec {
6409 EphemeralSpec {
6410 aplicacao: demo_overlay(),
6411 ttl: "1h".into(),
6412 teardown: TeardownPolicy::Always,
6413 max_concurrent: 0,
6414 postconditions: vec![],
6415 preconditions: vec![],
6416 verify_timeout: None,
6417 classification: None,
6418 parent: None,
6419 exports: vec![],
6420 routing: None,
6421 }
6422 }
6423 // Prior authored point_type = Fork; overlay substrate = Storage
6424 // preserves the Fork point_type on the composed classification.
6425 let seeded = baseline().with_classification_axis(ConvergencePointType::Fork);
6426 let composed = seeded.with_classification_axis(SubstrateType::Storage);
6427 let classification = composed
6428 .classification
6429 .as_ref()
6430 .expect("with_classification_axis populates Some(_)");
6431 assert_eq!(classification.point_type, ConvergencePointType::Fork);
6432 assert_eq!(classification.substrate, SubstrateType::Storage);
6433 // Order independence on distinct-slot axes: swapping the axis
6434 // chain reads the SAME final classification.
6435 let forward = baseline()
6436 .with_classification_axis(ConvergencePointType::Fork)
6437 .with_classification_axis(SubstrateType::Storage)
6438 .with_classification_axis(CalmClassification::NonMonotone)
6439 .with_classification_axis(DataClassification::Pii)
6440 .classification
6441 .unwrap();
6442 let reverse = baseline()
6443 .with_classification_axis(DataClassification::Pii)
6444 .with_classification_axis(CalmClassification::NonMonotone)
6445 .with_classification_axis(SubstrateType::Storage)
6446 .with_classification_axis(ConvergencePointType::Fork)
6447 .classification
6448 .unwrap();
6449 assert_eq!(
6450 forward, reverse,
6451 "with_classification_axis chain must be order-independent on distinct-slot axes",
6452 );
6453 // Nested horizon-sub-slot overlays compose onto the same
6454 // carrier without stomping each other: the (kind, direction)
6455 // pair rides both chains.
6456 let paired = baseline()
6457 .with_classification_axis(HorizonKind::Asymptotic)
6458 .with_classification_axis(OptimizationDirection::Maximize)
6459 .classification
6460 .unwrap();
6461 assert_eq!(paired.horizon.kind, HorizonKind::Asymptotic);
6462 assert_eq!(
6463 paired.horizon.direction,
6464 Some(OptimizationDirection::Maximize)
6465 );
6466 }
6467
6468 /// Primitive-owner pin —
6469 /// `EphemeralSpec::with_classification_axis` composes byte-for-
6470 /// byte with the pre-sweep hand-authored two-shape callsite
6471 /// pattern that recurred at ~36 sites in
6472 /// `tatara-reconciler::bin::tatara-check`: either
6473 /// `let mut c = Classification::gate_compute(); c.<axis> =
6474 /// populated; EphemeralSpec { classification: Some(c), ..
6475 /// baseline }`, or the newer `let c =
6476 /// Classification::gate_compute_with_axis(populated); EphemeralSpec
6477 /// { classification: Some(c), ..baseline }`. Both restated
6478 /// pre-sweep shapes classify identically to
6479 /// `baseline.with_classification_axis(populated)` on every
6480 /// [`ClassificationAxis`] impl. A regression that drifted the
6481 /// composer body away from the pre-sweep shape (a stray reset of a
6482 /// non-classification slot, a stomping of a nested horizon sub-
6483 /// slot on the direct-scalar axes) fails HERE at ONE landmark site
6484 /// before drifting through the ~36 swept callsites in tatara-
6485 /// check.rs.
6486 #[test]
6487 fn with_classification_axis_matches_pre_sweep_hand_authored_shape() {
6488 fn baseline() -> EphemeralSpec {
6489 EphemeralSpec {
6490 aplicacao: demo_overlay(),
6491 ttl: "1h".into(),
6492 teardown: TeardownPolicy::Always,
6493 max_concurrent: 0,
6494 postconditions: vec![],
6495 preconditions: vec![],
6496 verify_timeout: None,
6497 classification: None,
6498 parent: None,
6499 exports: vec![],
6500 routing: None,
6501 }
6502 }
6503 // Direct-scalar axes: `<eph>.with_classification_axis(kind)`
6504 // matches the pre-sweep two-shape callsite pattern on every
6505 // ConvergencePointType variant.
6506 for kind in ConvergencePointType::ALL {
6507 let via_composer = baseline().with_classification_axis(kind);
6508 let mut hand_classification = Classification::gate_compute();
6509 hand_classification.point_type = kind;
6510 let via_hand = EphemeralSpec {
6511 classification: Some(hand_classification),
6512 ..baseline()
6513 };
6514 assert_eq!(
6515 via_composer.classification, via_hand.classification,
6516 "ConvergencePointType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6517 );
6518 }
6519 for kind in SubstrateType::ALL {
6520 let via_composer = baseline().with_classification_axis(kind);
6521 let mut hand_classification = Classification::gate_compute();
6522 hand_classification.substrate = kind;
6523 let via_hand = EphemeralSpec {
6524 classification: Some(hand_classification),
6525 ..baseline()
6526 };
6527 assert_eq!(
6528 via_composer.classification, via_hand.classification,
6529 "SubstrateType::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6530 );
6531 }
6532 for kind in CalmClassification::ALL {
6533 let via_composer = baseline().with_classification_axis(kind);
6534 let mut hand_classification = Classification::gate_compute();
6535 hand_classification.calm = kind;
6536 let via_hand = EphemeralSpec {
6537 classification: Some(hand_classification),
6538 ..baseline()
6539 };
6540 assert_eq!(
6541 via_composer.classification, via_hand.classification,
6542 "CalmClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6543 );
6544 }
6545 for kind in DataClassification::ALL {
6546 let via_composer = baseline().with_classification_axis(kind);
6547 let mut hand_classification = Classification::gate_compute();
6548 hand_classification.data_classification = kind;
6549 let via_hand = EphemeralSpec {
6550 classification: Some(hand_classification),
6551 ..baseline()
6552 };
6553 assert_eq!(
6554 via_composer.classification, via_hand.classification,
6555 "DataClassification::{kind:?}: composer vs pre-sweep hand-authored classification drift",
6556 );
6557 }
6558 // Horizon-nested axes: composer matches the newer
6559 // `gate_compute_with_axis` shape used on the horizon-nested
6560 // sweep sites in tatara-check.rs.
6561 for kind in HorizonKind::ALL {
6562 let via_composer = baseline().with_classification_axis(kind);
6563 let via_hand = EphemeralSpec {
6564 classification: Some(Classification::gate_compute_with_axis(kind)),
6565 ..baseline()
6566 };
6567 assert_eq!(
6568 via_composer.classification, via_hand.classification,
6569 "HorizonKind::{kind:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6570 );
6571 }
6572 for direction in OptimizationDirection::ALL {
6573 let via_composer = baseline().with_classification_axis(direction);
6574 let via_hand = EphemeralSpec {
6575 classification: Some(Classification::gate_compute_with_axis(direction)),
6576 ..baseline()
6577 };
6578 assert_eq!(
6579 via_composer.classification, via_hand.classification,
6580 "OptimizationDirection::{direction:?}: composer vs pre-sweep gate_compute_with_axis Some(_) drift",
6581 );
6582 }
6583 }
6584
6585 fn demo_overlay() -> AplicacaoIntent {
6586 AplicacaoIntent {
6587 chart_ref: "oci://ghcr.io/pleme-io/charts/lareira-demo-app".into(),
6588 version: "0.5.5".into(),
6589 profile: "all-in-one".into(),
6590 values_overlay: serde_json::json!({
6591 "cluster": { "name": "ephemeral-test-01", "namespace": "demo-test" },
6592 "data": { "mysql": { "persistence": { "enabled": false } } },
6593 "compliance": { "overlays": [] }
6594 }),
6595 release_name: Some("demo-app-consolidated".into()),
6596 target_namespace: Some("demo-test".into()),
6597 install_timeout: Some("25m".into()),
6598 }
6599 }
6600
6601 #[test]
6602 fn defaults_resolve_for_ephemeral_spec() {
6603 let e = EphemeralSpec {
6604 aplicacao: demo_overlay(),
6605 ttl: crate::lifetime::default_ephemeral_ttl(),
6606 teardown: TeardownPolicy::default(),
6607 max_concurrent: crate::lifetime::default_ephemeral_max_concurrent(),
6608 postconditions: vec![],
6609 preconditions: vec![],
6610 verify_timeout: None,
6611 classification: None,
6612 parent: None,
6613 exports: vec![],
6614 routing: None,
6615 };
6616 let ps: ProcessSpec = e.into();
6617 // Intent must resolve to Aplicacao.
6618 match ps.intent.variant().unwrap() {
6619 IntentVariant::Aplicacao(a) => {
6620 assert_eq!(a.profile, "all-in-one");
6621 assert_eq!(a.install_timeout.as_deref(), Some("25m"));
6622 }
6623 other => panic!("expected Aplicacao, got {other:?}"),
6624 }
6625 // Lifetime must resolve to Ephemeral with defaults.
6626 match ps.lifetime.variant().unwrap() {
6627 LifetimeVariant::Ephemeral(e) => {
6628 assert_eq!(e.ttl, "1h");
6629 assert_eq!(e.teardown_policy, TeardownPolicy::Always);
6630 }
6631 other => panic!("expected ephemeral, got {other:?}"),
6632 }
6633 // Default classification gates the Process at Compute/Internal.
6634 assert_eq!(ps.classification.point_type, ConvergencePointType::Gate);
6635 assert_eq!(ps.classification.substrate, SubstrateType::Compute);
6636 }
6637
6638 #[test]
6639 fn ephemeral_lisp_round_trip() {
6640 let src = r#"
6641 (defephemeral closed-loop-attest
6642 :aplicacao (:chart-ref "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6643 :version "0.5.5"
6644 :profile "all-in-one"
6645 :values-overlay (:cluster (:name "ephemeral-test-01")
6646 :data (:mysql (:persistence (:enabled #f)))
6647 :compliance (:overlays []))
6648 :release-name "demo-app-consolidated"
6649 :target-namespace "demo-test"
6650 :install-timeout "25m")
6651 :ttl "1h"
6652 :teardown OnAttested
6653 :max-concurrent 1
6654 :postconditions
6655 ((:kind HelmReleaseReleased
6656 :params (:name "demo-app-consolidated"
6657 :namespace "demo-test"))
6658 (:kind ClosedLoopAuth
6659 :params (:issuer (:service "demo-app-issuer" :port 8080)
6660 :consumer (:service "demo-app-gateway" :port 8000)
6661 :probeImage "ghcr.io/pleme-io/closed-loop-probe:0.1.0"))))
6662 "#;
6663 let defs = compile_ephemeral_source(src).expect("compile");
6664 assert_eq!(defs.len(), 1);
6665 let d = &defs[0];
6666 assert_eq!(d.name, "closed-loop-attest");
6667
6668 // Aplicacao body landed correctly.
6669 assert_eq!(
6670 d.spec.aplicacao.chart_ref,
6671 "oci://ghcr.io/pleme-io/charts/lareira-demo-app"
6672 );
6673 assert_eq!(d.spec.aplicacao.profile, "all-in-one");
6674 assert_eq!(
6675 d.spec.aplicacao.target_namespace.as_deref(),
6676 Some("demo-test")
6677 );
6678 // values-overlay JSON is preserved.
6679 assert_eq!(
6680 d.spec.aplicacao.values_overlay["cluster"]["name"],
6681 "ephemeral-test-01"
6682 );
6683 // Boolean #f is preserved as a typed JSON bool (not the string "false").
6684 // tatara-lisp uses Scheme syntax for bools — `#t` / `#f`.
6685 assert_eq!(
6686 d.spec.aplicacao.values_overlay["data"]["mysql"]["persistence"]["enabled"],
6687 false
6688 );
6689
6690 // Lifetime knobs.
6691 assert_eq!(d.spec.ttl, "1h");
6692 assert_eq!(d.spec.teardown, TeardownPolicy::OnAttested);
6693 assert_eq!(d.spec.max_concurrent, 1);
6694
6695 // Two postconditions, both typed.
6696 assert_eq!(d.spec.postconditions.len(), 2);
6697 assert_eq!(
6698 d.spec.postconditions[0].kind,
6699 ConditionKind::HelmReleaseReleased
6700 );
6701 assert_eq!(d.spec.postconditions[1].kind, ConditionKind::ClosedLoopAuth);
6702
6703 // Lowers to ProcessSpec with the right shape.
6704 let ps: ProcessSpec = d.spec.clone().into();
6705 assert!(matches!(
6706 ps.intent.variant().unwrap(),
6707 IntentVariant::Aplicacao(_)
6708 ));
6709 assert!(matches!(
6710 ps.lifetime.variant().unwrap(),
6711 LifetimeVariant::Ephemeral(_)
6712 ));
6713 assert_eq!(ps.boundary.postconditions.len(), 2);
6714 }
6715
6716 /// End-to-end: the `:exports` slot on `(defephemeral …)` compiles
6717 /// into typed `ExportSpec` values via the Universal-Deserialize
6718 /// fallthrough — no per-domain keyword handlers needed.
6719 ///
6720 /// Receipts (empty-body source) is exercised via the Rust serde
6721 /// path only (see `export::tests::export_spec_serde_round_trip`).
6722 /// tatara-lisp's empty-kw-form `(:)` currently parses as a single-
6723 /// element array rather than a JSON `{}`; the same limitation
6724 /// affects `(:permanent)` on Lifetime. Tracked: extend the reader
6725 /// to accept `(:foo (:))` ⇒ `{"foo": {}}` as a typed-empty form,
6726 /// then re-enable Receipts here.
6727 #[test]
6728 fn exports_lisp_round_trip() {
6729 use crate::export::{ArtifactVariant, ChannelVariant, ExportTrigger, ReportFormat};
6730 let src = r#"
6731 (defephemeral closed-loop-attest
6732 :aplicacao (:chart-ref "oci://x"
6733 :version "1.0.0"
6734 :profile "minimal"
6735 :values-overlay ())
6736 :ttl "30m"
6737 :teardown OnAttested
6738 :exports
6739 ((:source (:test-report (:configmap "junit-results"
6740 :key "junit.xml"
6741 :format Junit))
6742 :channel (:nats-subject (:subject "pleme.pleme-dev.ephemeral.r1.test-report"
6743 :stream "EPHEMERAL_TEST_REPORTS"))
6744 :when OnAttested)
6745 (:source (:test-report (:configmap "junit-results"
6746 :key "junit.xml"
6747 :format Junit))
6748 :channel (:http-event (:signal-type "test-report"))
6749 :when Always)
6750 (:source (:run-marker (:labels (:run-id "r1" :phase "end")))
6751 :channel (:http-event (:signal-type "ephemeral-marker"))
6752 :when Always)))
6753 "#;
6754 let defs = compile_ephemeral_source(src).expect("compile");
6755 assert_eq!(defs.len(), 1);
6756 let d = &defs[0];
6757 assert_eq!(d.spec.exports.len(), 3);
6758
6759 // First export — TestReport → NATS subject + OnAttested
6760 let r = &d.spec.exports[0];
6761 match r.source.variant().unwrap() {
6762 ArtifactVariant::TestReport(tr) => {
6763 assert_eq!(tr.configmap, "junit-results");
6764 assert_eq!(tr.format, ReportFormat::Junit);
6765 }
6766 other => panic!("expected TestReport, got {other:?}"),
6767 }
6768 match r.channel.variant().unwrap() {
6769 ChannelVariant::NatsSubject(n) => {
6770 assert_eq!(n.subject, "pleme.pleme-dev.ephemeral.r1.test-report");
6771 assert_eq!(n.stream, "EPHEMERAL_TEST_REPORTS");
6772 }
6773 other => panic!("expected NatsSubject, got {other:?}"),
6774 }
6775 assert_eq!(r.when, ExportTrigger::OnAttested);
6776
6777 // Second export — TestReport → HTTP + Always
6778 let t = &d.spec.exports[1];
6779 match t.channel.variant().unwrap() {
6780 ChannelVariant::HttpEvent(h) => assert_eq!(h.signal_type, "test-report"),
6781 other => panic!("expected HttpEvent, got {other:?}"),
6782 }
6783 assert_eq!(t.when, ExportTrigger::Always);
6784
6785 // Third export — RunMarker (BTreeMap<String,String> round-trip).
6786 // tatara-lisp lowercases + normalizes keyword keys before
6787 // handing off to serde_json — kebab `:run-id` may land as
6788 // either `run-id` or `runId` depending on the reader path.
6789 // Accept either; the round-trip property under test is
6790 // "label survives compile" not "exact case-form".
6791 let m = &d.spec.exports[2];
6792 match m.source.variant().unwrap() {
6793 ArtifactVariant::RunMarker(rm) => {
6794 assert_eq!(rm.labels.len(), 2);
6795 let run_id = rm
6796 .labels
6797 .get("run-id")
6798 .or_else(|| rm.labels.get("runId"))
6799 .or_else(|| rm.labels.get("run_id"))
6800 .expect("run-id label present under some normalization");
6801 assert_eq!(run_id, "r1");
6802 assert_eq!(rm.labels.get("phase").map(String::as_str), Some("end"));
6803 }
6804 other => panic!("expected RunMarker, got {other:?}"),
6805 }
6806
6807 // Lowered ProcessSpec carries the exports through unchanged.
6808 let ps: ProcessSpec = d.spec.clone().into();
6809 assert_eq!(ps.lifetime.ephemeral.as_ref().unwrap().exports.len(), 3);
6810 }
6811
6812 // ── EphemeralSpec::has_condition_kind substrate pins ─────────────
6813 //
6814 // Fail-before-pass-after granularity:
6815 // `EphemeralSpec::has_condition_kind` did not exist before this
6816 // commit — the (preconditions ∪ postconditions .iter().any(|c|
6817 // c.kind == K)) union-probe shape lived at ONE struct-level site
6818 // (`Boundary::has_condition_kind` on the point surface's nested
6819 // [`Boundary`] slot). The lift adds the peer inherent method on the
6820 // [`EphemeralSpec`] sugar-surface so both struct-level union
6821 // callers compose against the SAME slice-level substrate primitive
6822 // [`ConditionSliceExt::has_kind`] in lockstep. A regression that
6823 // (a) hard-coded the arm to a single kind, (b) dropped the pre-
6824 // condition side of the OR (a re-inheritance of the pre-lift
6825 // ephemeral `closed-loop-auth` post-only shape at the union-tag
6826 // level), or (c) probed the wrong slot fails HERE at the substrate
6827 // primitive rather than as silent operator-facing drift at the
6828 // ephemeral `condition-<kind>` require-tag surface.
6829
6830 fn empty_ephemeral() -> EphemeralSpec {
6831 EphemeralSpec {
6832 aplicacao: AplicacaoIntent::chart_only("oci://ghcr.io/x", "1"),
6833 ttl: "1h".into(),
6834 teardown: TeardownPolicy::Always,
6835 max_concurrent: 0,
6836 postconditions: vec![],
6837 preconditions: vec![],
6838 verify_timeout: None,
6839 classification: None,
6840 parent: None,
6841 exports: vec![],
6842 routing: None,
6843 }
6844 }
6845
6846 fn cond(kind: ConditionKind) -> Condition {
6847 Condition {
6848 kind,
6849 params: serde_json::json!({}),
6850 }
6851 }
6852
6853 /// EMPTY-SPEC pin — a default [`EphemeralSpec`] (empty
6854 /// preconditions, empty postconditions) returns `false` for EVERY
6855 /// [`ConditionKind`]. Sweep `ConditionKind::ALL` so a new variant
6856 /// added without a matching arm in the presence probe surfaces at
6857 /// rustc's exhaustiveness gate on the ALL literal (arity forced by
6858 /// `[Self; 8]`) rather than as a silent false-positive at every
6859 /// downstream `condition-<kind>` ephemeral require-tag callsite.
6860 /// Byte-for-byte peer of
6861 /// `has_condition_kind_returns_false_on_empty_boundary_for_every_kind`
6862 /// on the [`Boundary`] surface.
6863 #[test]
6864 fn has_condition_kind_returns_false_on_empty_ephemeral_for_every_kind() {
6865 let spec = empty_ephemeral();
6866 for kind in ConditionKind::ALL {
6867 assert!(
6868 !spec.has_condition_kind(kind),
6869 "empty ephemeral spec must return false for {kind:?}",
6870 );
6871 }
6872 }
6873
6874 /// POSTCONDITION-only pin — an ephemeral spec that carries the
6875 /// kind on ONLY postconditions returns `true` for that kind,
6876 /// `false` for every other variant. Sweep the ALL × ALL cross so
6877 /// a regression that hard-coded the arm to a single kind or
6878 /// probed the wrong slot fails HERE at the substrate primitive.
6879 #[test]
6880 fn has_condition_kind_reads_ephemeral_postconditions_per_kind() {
6881 for populated in ConditionKind::ALL {
6882 let mut spec = empty_ephemeral();
6883 spec.postconditions.push(cond(populated));
6884 for query in ConditionKind::ALL {
6885 let expected = query == populated;
6886 assert_eq!(
6887 spec.has_condition_kind(query),
6888 expected,
6889 "ephemeral postcondition populated={populated:?}: \
6890 query {query:?} drifted",
6891 );
6892 }
6893 }
6894 }
6895
6896 /// PRECONDITION-only pin — mirrors the postcondition sweep on the
6897 /// other half of the union. Locks the union semantics on both
6898 /// halves separately so a regression that dropped the pre-
6899 /// condition side of the OR fails here even though the
6900 /// postcondition-side pin above passes.
6901 #[test]
6902 fn has_condition_kind_reads_ephemeral_preconditions_per_kind() {
6903 for populated in ConditionKind::ALL {
6904 let mut spec = empty_ephemeral();
6905 spec.preconditions.push(cond(populated));
6906 for query in ConditionKind::ALL {
6907 let expected = query == populated;
6908 assert_eq!(
6909 spec.has_condition_kind(query),
6910 expected,
6911 "ephemeral precondition populated={populated:?}: \
6912 query {query:?} drifted",
6913 );
6914 }
6915 }
6916 }
6917
6918 /// UNION pin — a kind that appears on preconditions returns
6919 /// `true` even when postconditions carries a DIFFERENT kind, and
6920 /// vice versa. Pins the OR-composition of the two halves so a
6921 /// regression that collapsed the union to an intersection (AND)
6922 /// silently reclassifies pre-only or post-only kinds as absent.
6923 /// Byte-for-byte peer of
6924 /// `has_condition_kind_unions_pre_and_post_condition_arms` on the
6925 /// [`Boundary`] surface.
6926 #[test]
6927 fn has_condition_kind_unions_pre_and_post_ephemeral_condition_arms() {
6928 let mut spec = empty_ephemeral();
6929 spec.preconditions
6930 .push(cond(ConditionKind::KustomizationHealthy));
6931 spec.postconditions
6932 .push(cond(ConditionKind::ClosedLoopAuth));
6933 assert!(
6934 spec.has_condition_kind(ConditionKind::KustomizationHealthy),
6935 "pre-only kind must resolve through the union",
6936 );
6937 assert!(
6938 spec.has_condition_kind(ConditionKind::ClosedLoopAuth),
6939 "post-only kind must resolve through the union",
6940 );
6941 assert!(
6942 !spec.has_condition_kind(ConditionKind::PromQL),
6943 "an absent kind must return false even with populated halves",
6944 );
6945 }
6946
6947 /// COMPOSITION pin — [`EphemeralSpec::has_condition_kind`] equals
6948 /// the OR of the two slice-level probes on the pre/post fields.
6949 /// The struct-level union body composes ONLY [`ConditionSliceExt::has_kind`]
6950 /// on each half; a regression that inlined a wide-net predicate
6951 /// (`.iter().any(|c| c.kind != kind).not()`, an `all` instead of
6952 /// `any`) drifts from the slice-level primitive here. Byte-for-
6953 /// byte peer of the
6954 /// `boundary_has_condition_kind_equals_or_of_half_slice_probes`
6955 /// composition pin on the [`Boundary`] surface.
6956 #[test]
6957 fn ephemeral_has_condition_kind_equals_or_of_half_slice_probes() {
6958 // Sweep every ConditionKind on both halves independently so the
6959 // cross of half-slice probes reaches the OR-composition body
6960 // exhaustively.
6961 for populated in ConditionKind::ALL {
6962 let mut spec = empty_ephemeral();
6963 spec.preconditions.push(cond(populated));
6964 spec.postconditions.push(cond(ConditionKind::PromQL));
6965 for query in ConditionKind::ALL {
6966 let via_or_of_halves =
6967 spec.preconditions.has_kind(query) || spec.postconditions.has_kind(query);
6968 assert_eq!(
6969 spec.has_condition_kind(query),
6970 via_or_of_halves,
6971 "populated={populated:?} query={query:?}: struct-level \
6972 union drifted from OR of slice-level probes",
6973 );
6974 }
6975 }
6976 }
6977
6978 // ── EphemeralSpec::has_(pre|post)condition_kind substrate pins ──
6979 //
6980 // Fail-before-pass-after granularity: the two half-slice arms did
6981 // not exist on the ephemeral surface before this commit — the
6982 // ephemeral require-tag classifier in `tatara-check` and the
6983 // `closed-loop-auth` fixed-tag arm reached
6984 // `spec.postconditions.has_kind(K)` through direct field access,
6985 // asymmetric with the union-arm [`EphemeralSpec::has_condition_kind`]
6986 // that already routed through the named struct method. The lift
6987 // closes the (precondition, postcondition, union) triad on the
6988 // ephemeral sugar surface so a future normalization at the
6989 // presence-probe shape lands at ONE site per surface for all
6990 // three arms.
6991
6992 /// EMPTY-SPEC pin — an ephemeral spec with no preconditions and
6993 /// no postconditions returns `false` for EVERY [`ConditionKind`]
6994 /// on both half-slice arms. Sweep `ConditionKind::ALL` so a new
6995 /// variant added without a matching arm surfaces at rustc's
6996 /// exhaustiveness gate on the ALL literal (arity forced by the
6997 /// closed-set array) rather than as a silent false-positive at
6998 /// every downstream require-tag callsite on the ephemeral
6999 /// surface.
7000 #[test]
7001 fn ephemeral_has_precondition_and_postcondition_kind_return_false_on_empty_spec() {
7002 let spec = empty_ephemeral();
7003 for kind in ConditionKind::ALL {
7004 assert!(
7005 !spec.has_precondition_kind(kind),
7006 "empty ephemeral must return false on precondition arm for {kind:?}",
7007 );
7008 assert!(
7009 !spec.has_postcondition_kind(kind),
7010 "empty ephemeral must return false on postcondition arm for {kind:?}",
7011 );
7012 }
7013 }
7014
7015 /// SLICE-SELECTIVITY pin (precondition arm) — an ephemeral spec
7016 /// with a kind on the precondition side ONLY resolves `true` at
7017 /// [`EphemeralSpec::has_precondition_kind`] and `false` at
7018 /// [`EphemeralSpec::has_postcondition_kind`]. Locks the (side-
7019 /// select, kind-select) partition so a regression that pointed
7020 /// the precondition arm at `self.postconditions` (a copy-paste
7021 /// from the sibling arm during the lift) surfaces HERE.
7022 #[test]
7023 fn ephemeral_has_precondition_kind_reads_preconditions_slice_only() {
7024 for populated in ConditionKind::ALL {
7025 let mut spec = empty_ephemeral();
7026 spec.preconditions.push(cond(populated));
7027 for query in ConditionKind::ALL {
7028 let expected_pre = query == populated;
7029 assert_eq!(
7030 spec.has_precondition_kind(query),
7031 expected_pre,
7032 "precondition-only populated={populated:?}: query {query:?} \
7033 drifted on ephemeral precondition arm",
7034 );
7035 assert!(
7036 !spec.has_postcondition_kind(query),
7037 "precondition-only populated={populated:?}: query {query:?} must \
7038 return false on ephemeral postcondition arm (postconditions is empty)",
7039 );
7040 }
7041 }
7042 }
7043
7044 /// SLICE-SELECTIVITY pin (postcondition arm) — mirror of the
7045 /// precondition-only sweep on the other half. Locks the
7046 /// postcondition arm's binding to `self.postconditions` so a
7047 /// regression that pointed it at `self.preconditions` fails HERE
7048 /// even though the precondition-arm pin above passes.
7049 #[test]
7050 fn ephemeral_has_postcondition_kind_reads_postconditions_slice_only() {
7051 for populated in ConditionKind::ALL {
7052 let mut spec = empty_ephemeral();
7053 spec.postconditions.push(cond(populated));
7054 for query in ConditionKind::ALL {
7055 let expected_post = query == populated;
7056 assert_eq!(
7057 spec.has_postcondition_kind(query),
7058 expected_post,
7059 "postcondition-only populated={populated:?}: query {query:?} \
7060 drifted on ephemeral postcondition arm",
7061 );
7062 assert!(
7063 !spec.has_precondition_kind(query),
7064 "postcondition-only populated={populated:?}: query {query:?} must \
7065 return false on ephemeral precondition arm (preconditions is empty)",
7066 );
7067 }
7068 }
7069 }
7070
7071 /// COMPOSITION-LAW pin — [`EphemeralSpec::has_condition_kind`]
7072 /// equals `has_precondition_kind(k) || has_postcondition_kind(k)`
7073 /// at EVERY (pre-populated, post-populated, query) triple on
7074 /// `ConditionKind::ALL`. Byte-for-byte peer of the
7075 /// `boundary_has_condition_kind_composes_precondition_and_postcondition_arms`
7076 /// composition-law pin on the [`Boundary`] surface — the
7077 /// two-surface parity contract binds the ephemeral sugar type
7078 /// and the point-domain boundary type through the SAME
7079 /// (`condition_kind = precondition_kind ∨ postcondition_kind`)
7080 /// composition, so every downstream `condition-<K>` require-tag
7081 /// classifier on either surface inherits the composition
7082 /// mechanically.
7083 #[test]
7084 fn ephemeral_has_condition_kind_composes_precondition_and_postcondition_arms() {
7085 for pre_kind in ConditionKind::ALL {
7086 for post_kind in ConditionKind::ALL {
7087 let mut spec = empty_ephemeral();
7088 spec.preconditions.push(cond(pre_kind));
7089 spec.postconditions.push(cond(post_kind));
7090 for query in ConditionKind::ALL {
7091 let via_arms =
7092 spec.has_precondition_kind(query) || spec.has_postcondition_kind(query);
7093 assert_eq!(
7094 spec.has_condition_kind(query),
7095 via_arms,
7096 "ephemeral union arm drifted from OR of half-slice arms: \
7097 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7098 );
7099 }
7100 }
7101 }
7102 }
7103
7104 /// SUBSTRATE-DELEGATION pin — the two half-slice arms on the
7105 /// ephemeral surface delegate verbatim to
7106 /// [`crate::boundary::ConditionSliceExt::has_kind`] on the
7107 /// underlying [`Vec<Condition>`] slice, no inline reimplementation.
7108 /// Sweep the full `ConditionKind::ALL` × `ConditionKind::ALL`
7109 /// cross so a regression that inlined a divergent walk at either
7110 /// arm surfaces HERE at the substrate boundary rather than as
7111 /// silent skew between the struct-level arm and the slice-level
7112 /// primitive.
7113 #[test]
7114 fn ephemeral_has_precondition_and_postcondition_kind_delegate_to_slice_has_kind() {
7115 for populated in ConditionKind::ALL {
7116 let mut spec = empty_ephemeral();
7117 spec.preconditions.push(cond(populated));
7118 spec.postconditions.push(cond(populated));
7119 for query in ConditionKind::ALL {
7120 assert_eq!(
7121 spec.has_precondition_kind(query),
7122 spec.preconditions.has_kind(query),
7123 "ephemeral precondition arm must delegate to preconditions.has_kind: \
7124 populated={populated:?} query={query:?}",
7125 );
7126 assert_eq!(
7127 spec.has_postcondition_kind(query),
7128 spec.postconditions.has_kind(query),
7129 "ephemeral postcondition arm must delegate to postconditions.has_kind: \
7130 populated={populated:?} query={query:?}",
7131 );
7132 }
7133 }
7134 }
7135
7136 // ── EphemeralSpec::find_(pre|post|)condition_kind widened triad ──
7137 //
7138 // Fail-before-pass-after granularity: the three widened
7139 // `find_*_kind` arms did not exist on the ephemeral surface before
7140 // this commit — the (widened `Option<&Condition>` return) axis
7141 // lived at ONE struct-level site (`Boundary::find_condition_kind`
7142 // on the point surface's nested [`Boundary`] slot). The lift adds
7143 // the peer inherent methods on the [`EphemeralSpec`] sugar-surface
7144 // so both struct-level widened callers compose against the SAME
7145 // slice-level substrate primitive
7146 // [`crate::boundary::ConditionSliceExt::find_kind`] in lockstep.
7147 // A regression that (a) hard-coded the arm to a single kind, (b)
7148 // reversed the walk order on the union (postcondition first), or
7149 // (c) collapsed `or_else` to `and_then` (silently narrowing the
7150 // union to an intersection) fails HERE at the substrate primitive
7151 // rather than as silent operator-facing drift at the ephemeral
7152 // require-tag surface.
7153
7154 /// EMPTY-SPEC pin (find-triad) — a default [`EphemeralSpec`]
7155 /// (empty preconditions, empty postconditions) returns `None`
7156 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
7157 /// `ConditionKind::ALL` × three-arm cross so a new variant added
7158 /// without a matching arm surfaces at rustc's exhaustiveness gate
7159 /// on the ALL literal (arity forced by the closed-set array)
7160 /// rather than as a silent false-`Some` at every downstream
7161 /// widened callsite on the ephemeral surface.
7162 #[test]
7163 fn ephemeral_find_condition_kind_triad_returns_none_on_empty_spec() {
7164 let spec = empty_ephemeral();
7165 for kind in ConditionKind::ALL {
7166 assert!(
7167 spec.find_precondition_kind(kind).is_none(),
7168 "empty ephemeral must return None on precondition find arm for {kind:?}",
7169 );
7170 assert!(
7171 spec.find_postcondition_kind(kind).is_none(),
7172 "empty ephemeral must return None on postcondition find arm for {kind:?}",
7173 );
7174 assert!(
7175 spec.find_condition_kind(kind).is_none(),
7176 "empty ephemeral must return None on union find arm for {kind:?}",
7177 );
7178 }
7179 }
7180
7181 /// SUBSTRATE-DELEGATION pin (ephemeral find-triad) — the three
7182 /// widened `find_*_kind` methods on [`EphemeralSpec`] delegate
7183 /// verbatim to [`crate::boundary::ConditionSliceExt::find_kind`]
7184 /// on the underlying [`Vec<Condition>`] slices, no inline
7185 /// reimplementation. The `find_condition_kind` union walks
7186 /// preconditions first then postconditions via `Option::or_else`.
7187 /// Sweep `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
7188 /// so a regression that (a) inlined a divergent walk at either
7189 /// half-slice arm, (b) reversed the union walk order on the
7190 /// ephemeral surface only (breaking two-surface parity with
7191 /// [`crate::boundary::Boundary::find_condition_kind`]), or (c)
7192 /// collapsed `or_else` to `and_then` surfaces HERE at the substrate
7193 /// boundary. Byte-for-byte peer of the point-domain
7194 /// `find_condition_kind_triad_delegates_to_slice_find_kind` pin.
7195 #[test]
7196 fn ephemeral_find_condition_kind_triad_delegates_to_slice_find_kind() {
7197 for pre_kind in ConditionKind::ALL {
7198 for post_kind in ConditionKind::ALL {
7199 let mut spec = empty_ephemeral();
7200 spec.preconditions.push(cond(pre_kind));
7201 spec.postconditions.push(cond(post_kind));
7202 for query in ConditionKind::ALL {
7203 let via_pre = spec.preconditions.find_kind(query);
7204 let via_post = spec.postconditions.find_kind(query);
7205 assert_eq!(
7206 spec.find_precondition_kind(query).map(|c| c.kind),
7207 via_pre.map(|c| c.kind),
7208 "ephemeral precondition find arm must delegate: \
7209 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7210 );
7211 assert_eq!(
7212 spec.find_postcondition_kind(query).map(|c| c.kind),
7213 via_post.map(|c| c.kind),
7214 "ephemeral postcondition find arm must delegate: \
7215 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7216 );
7217 let expected_union = via_pre.or(via_post).map(|c| c.kind);
7218 assert_eq!(
7219 spec.find_condition_kind(query).map(|c| c.kind),
7220 expected_union,
7221 "ephemeral union find arm must equal precondition.or_else(postcondition): \
7222 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7223 );
7224 }
7225 }
7226 }
7227 }
7228
7229 /// PRECONDITION-PRECEDENCE pin (ephemeral) — a kind authored on
7230 /// BOTH sides returns the precondition-side [`Condition`] from
7231 /// `find_condition_kind`. Byte-for-byte peer of the point-domain
7232 /// `find_condition_kind_returns_precondition_side_on_dual_populated`
7233 /// pin, so the two-surface parity contract binds the walk order
7234 /// on both surfaces through ONE composition law. Uses two params-
7235 /// distinguishable [`Condition`]s so a regression on the ephemeral
7236 /// surface only that reversed the walk order surfaces at the
7237 /// returned params payload rather than silently at the presence
7238 /// bit.
7239 #[test]
7240 fn ephemeral_find_condition_kind_returns_precondition_side_on_dual_populated() {
7241 let mut spec = empty_ephemeral();
7242 spec.preconditions.push(Condition {
7243 kind: ConditionKind::ClosedLoopAuth,
7244 params: serde_json::json!({ "side": "pre" }),
7245 });
7246 spec.postconditions.push(Condition {
7247 kind: ConditionKind::ClosedLoopAuth,
7248 params: serde_json::json!({ "side": "post" }),
7249 });
7250 let hit = spec
7251 .find_condition_kind(ConditionKind::ClosedLoopAuth)
7252 .expect("dual-populated ephemeral spec must resolve Some");
7253 assert_eq!(
7254 hit.params.get("side").and_then(serde_json::Value::as_str),
7255 Some("pre"),
7256 "ephemeral find_condition_kind must walk preconditions first",
7257 );
7258 }
7259
7260 /// STRUCT-LEVEL DELEGATION pin (ephemeral has ↔ find) — the three
7261 /// [`EphemeralSpec`] `has_*_kind` arms equal their widened peers'
7262 /// `.is_some()` projection at EVERY (pre-populated, post-populated,
7263 /// query) triple on `ConditionKind::ALL`. Byte-for-byte peer of
7264 /// the point-domain
7265 /// `boundary_has_triad_equals_find_triad_is_some_projection` pin,
7266 /// so both surfaces' has/find refinement bridge stays symmetric by
7267 /// construction — a future consumer that reads
7268 /// `spec.has_condition_kind(k)` as sugar for
7269 /// `spec.find_condition_kind(k).is_some()` on either surface stays
7270 /// typed against the SAME truth table across the two-surface
7271 /// parity contract.
7272 #[test]
7273 fn ephemeral_has_triad_equals_find_triad_is_some_projection() {
7274 for pre_kind in ConditionKind::ALL {
7275 for post_kind in ConditionKind::ALL {
7276 let mut spec = empty_ephemeral();
7277 spec.preconditions.push(cond(pre_kind));
7278 spec.postconditions.push(cond(post_kind));
7279 for query in ConditionKind::ALL {
7280 assert_eq!(
7281 spec.has_precondition_kind(query),
7282 spec.find_precondition_kind(query).is_some(),
7283 "ephemeral precondition has/find bridge drifted: \
7284 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7285 );
7286 assert_eq!(
7287 spec.has_postcondition_kind(query),
7288 spec.find_postcondition_kind(query).is_some(),
7289 "ephemeral postcondition has/find bridge drifted: \
7290 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7291 );
7292 assert_eq!(
7293 spec.has_condition_kind(query),
7294 spec.find_condition_kind(query).is_some(),
7295 "ephemeral union has/find bridge drifted: \
7296 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7297 );
7298 }
7299 }
7300 }
7301 }
7302
7303 // ── EphemeralSpec::iter_(pre|post|)condition_kind widened triad ──
7304 //
7305 // Fail-before-pass-after granularity: the three widened
7306 // `iter_*_kind` arms did not exist on the ephemeral surface before
7307 // this commit — the (widened `impl Iterator<Item = &Condition>`
7308 // stream) axis lived at ONE struct-level site
7309 // (`Boundary::iter_condition_kind` on the point surface's nested
7310 // [`Boundary`] slot). The lift adds the peer inherent methods on
7311 // the [`EphemeralSpec`] sugar-surface so both struct-level widened
7312 // callers compose against the SAME slice-level substrate primitive
7313 // [`crate::boundary::ConditionSliceExt::iter_kind`] in lockstep.
7314 // A regression that (a) hard-coded the arm to a single kind, (b)
7315 // reversed the chain order on the union (postcondition first), or
7316 // (c) collapsed the chain to a `.zip(...)` (silently narrowing the
7317 // union to an intersection-by-position) fails HERE at the
7318 // substrate primitive rather than as silent operator-facing drift
7319 // at the ephemeral require-tag surface.
7320
7321 /// EMPTY-SPEC pin (iter-triad) — a default [`EphemeralSpec`]
7322 /// (empty preconditions, empty postconditions) yields nothing
7323 /// from every widened arm for EVERY [`ConditionKind`]. Sweep
7324 /// `ConditionKind::ALL` × three-arm cross so a new variant added
7325 /// without a matching arm surfaces at rustc's exhaustiveness gate
7326 /// on the ALL literal rather than as a silent phantom-yield at
7327 /// every downstream widened callsite on the ephemeral surface.
7328 #[test]
7329 fn ephemeral_iter_condition_kind_triad_yields_nothing_on_empty_spec() {
7330 let spec = empty_ephemeral();
7331 for kind in ConditionKind::ALL {
7332 assert_eq!(
7333 spec.iter_precondition_kind(kind).count(),
7334 0,
7335 "empty ephemeral must yield nothing on precondition iter arm for {kind:?}",
7336 );
7337 assert_eq!(
7338 spec.iter_postcondition_kind(kind).count(),
7339 0,
7340 "empty ephemeral must yield nothing on postcondition iter arm for {kind:?}",
7341 );
7342 assert_eq!(
7343 spec.iter_condition_kind(kind).count(),
7344 0,
7345 "empty ephemeral must yield nothing on union iter arm for {kind:?}",
7346 );
7347 }
7348 }
7349
7350 /// SUBSTRATE-DELEGATION pin (ephemeral iter-triad) — the three
7351 /// widened `iter_*_kind` methods on [`EphemeralSpec`] delegate
7352 /// verbatim to [`crate::boundary::ConditionSliceExt::iter_kind`]
7353 /// on the underlying [`Vec<Condition>`] slices, no inline
7354 /// reimplementation. The `iter_condition_kind` union chains
7355 /// preconditions first then postconditions via
7356 /// [`Iterator::chain`]. Sweep
7357 /// `ConditionKind::ALL × ConditionKind::ALL × ConditionKind::ALL`
7358 /// so a regression that (a) inlined a divergent walk at either
7359 /// half-slice arm, (b) reversed the chain order on the ephemeral
7360 /// surface only (breaking two-surface parity with
7361 /// [`crate::boundary::Boundary::iter_condition_kind`]), or (c)
7362 /// collapsed the chain to a `.zip(...)` surfaces HERE at the
7363 /// substrate boundary. Byte-for-byte peer of the point-domain
7364 /// `iter_condition_kind_triad_delegates_to_slice_iter_kind` pin.
7365 #[test]
7366 fn ephemeral_iter_condition_kind_triad_delegates_to_slice_iter_kind() {
7367 for pre_kind in ConditionKind::ALL {
7368 for post_kind in ConditionKind::ALL {
7369 let mut spec = empty_ephemeral();
7370 spec.preconditions.push(cond(pre_kind));
7371 spec.postconditions.push(cond(post_kind));
7372 for query in ConditionKind::ALL {
7373 let via_pre: Vec<_> = spec
7374 .preconditions
7375 .iter_kind(query)
7376 .map(|c| c.kind)
7377 .collect();
7378 let via_post: Vec<_> = spec
7379 .postconditions
7380 .iter_kind(query)
7381 .map(|c| c.kind)
7382 .collect();
7383 assert_eq!(
7384 spec.iter_precondition_kind(query)
7385 .map(|c| c.kind)
7386 .collect::<Vec<_>>(),
7387 via_pre,
7388 "ephemeral precondition iter arm must delegate: \
7389 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7390 );
7391 assert_eq!(
7392 spec.iter_postcondition_kind(query)
7393 .map(|c| c.kind)
7394 .collect::<Vec<_>>(),
7395 via_post,
7396 "ephemeral postcondition iter arm must delegate: \
7397 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7398 );
7399 let mut expected_union = via_pre.clone();
7400 expected_union.extend(via_post.iter().copied());
7401 assert_eq!(
7402 spec.iter_condition_kind(query)
7403 .map(|c| c.kind)
7404 .collect::<Vec<_>>(),
7405 expected_union,
7406 "ephemeral union iter arm must chain precondition ⨟ postcondition: \
7407 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7408 );
7409 }
7410 }
7411 }
7412 }
7413
7414 /// PRECONDITION-PRECEDENCE pin (ephemeral iter) — a kind
7415 /// authored on BOTH sides yields precondition-side matches
7416 /// FIRST in the union chain. Byte-for-byte peer of the
7417 /// point-domain
7418 /// `iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated`
7419 /// pin — the two-surface parity contract binds the chain order
7420 /// on both surfaces through ONE composition law. Uses two
7421 /// params-distinguishable [`Condition`]s so a regression on the
7422 /// ephemeral surface only that reversed the chain order surfaces
7423 /// at the returned params payload rather than silently at the
7424 /// count.
7425 #[test]
7426 fn ephemeral_iter_condition_kind_yields_preconditions_before_postconditions_on_dual_populated()
7427 {
7428 let mut spec = empty_ephemeral();
7429 spec.preconditions.push(Condition {
7430 kind: ConditionKind::ClosedLoopAuth,
7431 params: serde_json::json!({ "side": "pre-1" }),
7432 });
7433 spec.postconditions.push(Condition {
7434 kind: ConditionKind::ClosedLoopAuth,
7435 params: serde_json::json!({ "side": "post-1" }),
7436 });
7437 spec.postconditions.push(Condition {
7438 kind: ConditionKind::ClosedLoopAuth,
7439 params: serde_json::json!({ "side": "post-2" }),
7440 });
7441 let sides: Vec<_> = spec
7442 .iter_condition_kind(ConditionKind::ClosedLoopAuth)
7443 .map(|c| {
7444 c.params
7445 .get("side")
7446 .and_then(serde_json::Value::as_str)
7447 .unwrap_or_default()
7448 .to_owned()
7449 })
7450 .collect();
7451 assert_eq!(
7452 sides,
7453 vec!["pre-1".to_owned(), "post-1".to_owned(), "post-2".to_owned(),],
7454 "ephemeral iter_condition_kind must yield every precondition-side match before \
7455 any postcondition-side match (chain order pinned by two-surface parity)",
7456 );
7457 }
7458
7459 /// STRUCT-LEVEL DELEGATION pin (find ↔ iter on EphemeralSpec) —
7460 /// the three [`EphemeralSpec`] `find_*_kind` arms equal their
7461 /// widened peers' `.next()` projection at EVERY (pre-populated,
7462 /// post-populated, query) triple on `ConditionKind::ALL`.
7463 /// Byte-for-byte peer of the point-domain
7464 /// `boundary_find_triad_equals_iter_triad_next_projection` pin,
7465 /// so both surfaces' find/iter refinement bridge stays symmetric
7466 /// by construction across the two-surface parity contract.
7467 #[test]
7468 fn ephemeral_find_triad_equals_iter_triad_next_projection() {
7469 for pre_kind in ConditionKind::ALL {
7470 for post_kind in ConditionKind::ALL {
7471 let mut spec = empty_ephemeral();
7472 spec.preconditions.push(cond(pre_kind));
7473 spec.postconditions.push(cond(post_kind));
7474 for query in ConditionKind::ALL {
7475 assert_eq!(
7476 spec.find_precondition_kind(query).map(|c| c.kind),
7477 spec.iter_precondition_kind(query).next().map(|c| c.kind),
7478 "ephemeral precondition find/iter bridge drifted: \
7479 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7480 );
7481 assert_eq!(
7482 spec.find_postcondition_kind(query).map(|c| c.kind),
7483 spec.iter_postcondition_kind(query).next().map(|c| c.kind),
7484 "ephemeral postcondition find/iter bridge drifted: \
7485 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7486 );
7487 assert_eq!(
7488 spec.find_condition_kind(query).map(|c| c.kind),
7489 spec.iter_condition_kind(query).next().map(|c| c.kind),
7490 "ephemeral union find/iter bridge drifted: \
7491 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7492 );
7493 }
7494 }
7495 }
7496 }
7497
7498 // ── EphemeralSpec count triad — scalar cardinality peers ─────────
7499 //
7500 // Byte-for-byte peers of the point-domain `Boundary`
7501 // `count_(pre|post|)condition_kind` triad, tested at the ephemeral
7502 // sugar surface. Same SUM composition on the union arm, same
7503 // slice-level substrate delegation, same composition-law bridge
7504 // against the widened iter refinement.
7505
7506 /// EMPTY-SPEC pin (count-triad) — a default [`EphemeralSpec`]
7507 /// counts `0` from every arm of the count triad for EVERY
7508 /// [`ConditionKind`].
7509 #[test]
7510 fn ephemeral_count_condition_kind_triad_returns_zero_on_empty_spec() {
7511 let spec = empty_ephemeral();
7512 for kind in ConditionKind::ALL {
7513 assert_eq!(
7514 spec.count_precondition_kind(kind),
7515 0,
7516 "empty ephemeral must count 0 on precondition arm for {kind:?}",
7517 );
7518 assert_eq!(
7519 spec.count_postcondition_kind(kind),
7520 0,
7521 "empty ephemeral must count 0 on postcondition arm for {kind:?}",
7522 );
7523 assert_eq!(
7524 spec.count_condition_kind(kind),
7525 0,
7526 "empty ephemeral must count 0 on union arm for {kind:?}",
7527 );
7528 }
7529 }
7530
7531 /// SUBSTRATE-DELEGATION pin (ephemeral count-triad) — the three
7532 /// widened `count_*_kind` methods on [`EphemeralSpec`] delegate
7533 /// verbatim to [`crate::boundary::ConditionSliceExt::count_kind`]
7534 /// on the underlying [`Vec<Condition>`] slices. The
7535 /// `count_condition_kind` union SUMS preconditions and
7536 /// postconditions. Byte-for-byte peer of the point-domain
7537 /// `boundary_count_condition_kind_triad_delegates_and_sums_slice_count_kind`
7538 /// pin; a regression that (a) subtracted rather than summed, (b)
7539 /// collapsed the sum to [`std::cmp::max`], or (c) inlined a
7540 /// divergent count at either half-slice arm on the ephemeral
7541 /// surface only (breaking two-surface parity with [`Boundary`])
7542 /// surfaces HERE.
7543 #[test]
7544 fn ephemeral_count_condition_kind_triad_delegates_and_sums_slice_count_kind() {
7545 for pre_kind in ConditionKind::ALL {
7546 for post_kind in ConditionKind::ALL {
7547 let mut spec = empty_ephemeral();
7548 spec.preconditions.push(cond(pre_kind));
7549 spec.postconditions.push(cond(post_kind));
7550 for query in ConditionKind::ALL {
7551 let via_pre = spec.preconditions.count_kind(query);
7552 let via_post = spec.postconditions.count_kind(query);
7553 assert_eq!(
7554 spec.count_precondition_kind(query),
7555 via_pre,
7556 "ephemeral precondition count arm must delegate: \
7557 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7558 );
7559 assert_eq!(
7560 spec.count_postcondition_kind(query),
7561 via_post,
7562 "ephemeral postcondition count arm must delegate: \
7563 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7564 );
7565 assert_eq!(
7566 spec.count_condition_kind(query),
7567 via_pre + via_post,
7568 "ephemeral union count arm must SUM pre + post: \
7569 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7570 );
7571 }
7572 }
7573 }
7574 }
7575
7576 /// STRUCT-LEVEL DELEGATION pin (count ↔ iter on EphemeralSpec) —
7577 /// the three [`EphemeralSpec`] `count_*_kind` arms equal their
7578 /// widened peers' `.count()` projection at EVERY (pre-populated
7579 /// twice, post-populated, query) triple. Byte-for-byte peer of
7580 /// the point-domain
7581 /// `boundary_count_triad_equals_iter_triad_count_projection`
7582 /// pin. Uses two-preconditions authoring so the union arm's SUM
7583 /// composition witnesses a nontrivial cardinality (rather than
7584 /// coinciding with the presence bit).
7585 #[test]
7586 fn ephemeral_count_triad_equals_iter_triad_count_projection() {
7587 for pre_kind in ConditionKind::ALL {
7588 for post_kind in ConditionKind::ALL {
7589 let mut spec = empty_ephemeral();
7590 spec.preconditions.push(cond(pre_kind));
7591 spec.preconditions.push(cond(pre_kind));
7592 spec.postconditions.push(cond(post_kind));
7593 for query in ConditionKind::ALL {
7594 assert_eq!(
7595 spec.count_precondition_kind(query),
7596 spec.iter_precondition_kind(query).count(),
7597 "ephemeral precondition count/iter bridge drifted: \
7598 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7599 );
7600 assert_eq!(
7601 spec.count_postcondition_kind(query),
7602 spec.iter_postcondition_kind(query).count(),
7603 "ephemeral postcondition count/iter bridge drifted: \
7604 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7605 );
7606 assert_eq!(
7607 spec.count_condition_kind(query),
7608 spec.iter_condition_kind(query).count(),
7609 "ephemeral union count/iter bridge drifted: \
7610 pre={pre_kind:?} post={post_kind:?} query={query:?}",
7611 );
7612 }
7613 }
7614 }
7615 }
7616
7617 // ── EphemeralSpec distinct-set triad — substrate-delegation pin ──
7618 //
7619 // The (precondition, postcondition, condition-union) distinct-set
7620 // triad on [`EphemeralSpec`] delegates to the slice-level substrate
7621 // primitive [`crate::boundary::ConditionSliceExt::distinct_kinds`]
7622 // on each half-slice and composes the union via
7623 // [`Self::has_condition_kind`] over [`ConditionKind::ALL`] — byte-
7624 // for-byte peer of the point-surface distinct-set triad on
7625 // [`crate::boundary::Boundary`]. The two-surface parity contract
7626 // now covers FIVE refinements on the condition axis: the four
7627 // point-probe refinements (has / find / iter / count) AND the ONE
7628 // closed-set-inversion refinement (distinct-set) on both surfaces.
7629
7630 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-kind-count
7631 /// triad) — the three `distinct_*_kind_count` methods on
7632 /// [`EphemeralSpec`] delegate to the slice-level substrate
7633 /// primitive [`crate::boundary::ConditionSliceExt::distinct_kind_count`]
7634 /// over the two `Vec<Condition>` slots and compose the union
7635 /// scalar via `ConditionKind::ALL.filter(|k|
7636 /// has_condition_kind(*k)).count()`. Byte-for-byte peer of the
7637 /// point-surface pin
7638 /// `distinct_condition_kind_count_triad_delegates_to_slice_distinct_kind_count`
7639 /// on [`crate::boundary::Boundary`] — the two-surface parity
7640 /// contract now binds every downstream scalar-cardinality consumer
7641 /// on either surface to the SAME closed-set walk through ONE
7642 /// substrate rather than through per-surface `.distinct_*_kinds().len()`
7643 /// re-materializations that pay for a heap allocation.
7644 #[test]
7645 fn ephemeral_distinct_condition_kind_count_triad_delegates_and_matches_distinct_kinds_len() {
7646 // Empty spec — every arm returns 0.
7647 let spec = empty_ephemeral();
7648 for kind in ConditionKind::ALL {
7649 assert_eq!(
7650 spec.distinct_precondition_kind_count(),
7651 0,
7652 "empty ephemeral spec must return 0 on distinct_precondition_kind_count, kind={kind:?}",
7653 );
7654 assert_eq!(
7655 spec.distinct_postcondition_kind_count(),
7656 0,
7657 "empty ephemeral spec must return 0 on distinct_postcondition_kind_count, kind={kind:?}",
7658 );
7659 assert_eq!(
7660 spec.distinct_condition_kind_count(),
7661 0,
7662 "empty ephemeral spec must return 0 on distinct_condition_kind_count, kind={kind:?}",
7663 );
7664 }
7665
7666 for pre_kind in ConditionKind::ALL {
7667 for post_kind in ConditionKind::ALL {
7668 let mut spec = empty_ephemeral();
7669 spec.preconditions.push(cond(pre_kind));
7670 spec.postconditions.push(cond(post_kind));
7671
7672 assert_eq!(
7673 spec.distinct_precondition_kind_count(),
7674 spec.preconditions.distinct_kind_count(),
7675 "EphemeralSpec::distinct_precondition_kind_count must delegate verbatim to \
7676 preconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7677 );
7678 assert_eq!(
7679 spec.distinct_precondition_kind_count(),
7680 spec.distinct_precondition_kinds().len(),
7681 "EphemeralSpec::distinct_precondition_kind_count must equal \
7682 distinct_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7683 );
7684 assert_eq!(
7685 spec.distinct_postcondition_kind_count(),
7686 spec.postconditions.distinct_kind_count(),
7687 "EphemeralSpec::distinct_postcondition_kind_count must delegate verbatim to \
7688 postconditions.distinct_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7689 );
7690 assert_eq!(
7691 spec.distinct_postcondition_kind_count(),
7692 spec.distinct_postcondition_kinds().len(),
7693 "EphemeralSpec::distinct_postcondition_kind_count must equal \
7694 distinct_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7695 );
7696 let expected_union_count = if pre_kind == post_kind { 1 } else { 2 };
7697 assert_eq!(
7698 spec.distinct_condition_kind_count(),
7699 expected_union_count,
7700 "EphemeralSpec::distinct_condition_kind_count must count distinct union kinds \
7701 for pre={pre_kind:?} post={post_kind:?}",
7702 );
7703 assert_eq!(
7704 spec.distinct_condition_kind_count(),
7705 spec.distinct_condition_kinds().len(),
7706 "EphemeralSpec::distinct_condition_kind_count must equal \
7707 distinct_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7708 );
7709 }
7710 }
7711 }
7712
7713 /// SUBSTRATE-DELEGATION pin (ephemeral surface, distinct-set triad)
7714 /// — the three `distinct_*_kinds` methods on [`EphemeralSpec`]
7715 /// delegate to the slice-level substrate primitive over the two
7716 /// `Vec<Condition>` slots and compose the union via
7717 /// `ConditionKind::ALL.filter(|k| has_condition_kind(*k))`. Byte-
7718 /// for-byte peer of the point-surface pin
7719 /// `distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds`
7720 /// on [`crate::boundary::Boundary`] — the two-surface parity
7721 /// contract binds every downstream distinct-set consumer on either
7722 /// surface to the SAME closed-set-inversion primitive through ONE
7723 /// substrate rather than through per-surface re-authored sweeps.
7724 #[test]
7725 fn ephemeral_distinct_condition_kinds_triad_delegates_to_slice_distinct_kinds() {
7726 for pre_kind in ConditionKind::ALL {
7727 for post_kind in ConditionKind::ALL {
7728 let mut spec = empty_ephemeral();
7729 spec.preconditions.push(cond(pre_kind));
7730 spec.postconditions.push(cond(post_kind));
7731
7732 assert_eq!(
7733 spec.distinct_precondition_kinds(),
7734 spec.preconditions.distinct_kinds(),
7735 "EphemeralSpec::distinct_precondition_kinds must delegate verbatim to \
7736 preconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7737 );
7738 assert_eq!(
7739 spec.distinct_postcondition_kinds(),
7740 spec.postconditions.distinct_kinds(),
7741 "EphemeralSpec::distinct_postcondition_kinds must delegate verbatim to \
7742 postconditions.distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
7743 );
7744 let expected_union: Vec<_> = ConditionKind::ALL
7745 .into_iter()
7746 .filter(|k| pre_kind == *k || post_kind == *k)
7747 .collect();
7748 assert_eq!(
7749 spec.distinct_condition_kinds(),
7750 expected_union,
7751 "EphemeralSpec::distinct_condition_kinds must equal ConditionKind::ALL-ordered \
7752 set-union of the two half-slice distinct-sets for pre={pre_kind:?} post={post_kind:?}",
7753 );
7754 }
7755 }
7756 }
7757
7758 /// SUBSTRATE-DELEGATION pin (EphemeralSpec distinct-set ITERATOR
7759 /// triad) — the three `iter_distinct_*_condition_kinds` methods on
7760 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7761 /// [`crate::boundary::ConditionSliceExt::iter_distinct_kinds`] over
7762 /// the two `Vec<Condition>` slots and compose the union via
7763 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7764 /// has_condition_kind(k))`. Byte-for-byte peer of
7765 /// `iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7766 /// on the point-domain [`crate::boundary::Boundary`] surface — both
7767 /// peers compose against the SAME slice-level iterator substrate.
7768 #[test]
7769 fn ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds() {
7770 for pre_kind in ConditionKind::ALL {
7771 for post_kind in ConditionKind::ALL {
7772 let mut spec = empty_ephemeral();
7773 spec.preconditions.push(cond(pre_kind));
7774 spec.postconditions.push(cond(post_kind));
7775
7776 let pre_via_iter: Vec<_> = spec.iter_distinct_precondition_kinds().collect();
7777 assert_eq!(
7778 pre_via_iter,
7779 spec.distinct_precondition_kinds(),
7780 "EphemeralSpec::iter_distinct_precondition_kinds().collect() drifted from \
7781 distinct_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7782 );
7783 let post_via_iter: Vec<_> = spec.iter_distinct_postcondition_kinds().collect();
7784 assert_eq!(
7785 post_via_iter,
7786 spec.distinct_postcondition_kinds(),
7787 "EphemeralSpec::iter_distinct_postcondition_kinds().collect() drifted from \
7788 distinct_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7789 );
7790 let union_via_iter: Vec<_> = spec.iter_distinct_condition_kinds().collect();
7791 assert_eq!(
7792 union_via_iter,
7793 spec.distinct_condition_kinds(),
7794 "EphemeralSpec::iter_distinct_condition_kinds().collect() drifted from \
7795 distinct_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7796 );
7797 }
7798 }
7799 }
7800
7801 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set ITERATOR
7802 /// triad) — the three `iter_missing_*_condition_kinds` methods on
7803 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
7804 /// [`crate::boundary::ConditionSliceExt::iter_missing_kinds`] over
7805 /// the two `Vec<Condition>` slots and compose the union via
7806 /// `ConditionKind::ALL.iter().copied().filter(|&k|
7807 /// !has_condition_kind(k))`. Peer of
7808 /// `ephemeral_iter_distinct_condition_kinds_triad_delegates_to_slice_iter_distinct_kinds`
7809 /// on the missing side under a NEGATED point-probe.
7810 #[test]
7811 fn ephemeral_iter_missing_condition_kinds_triad_delegates_to_slice_iter_missing_kinds() {
7812 let empty = empty_ephemeral();
7813 let all: Vec<_> = ConditionKind::ALL.to_vec();
7814 assert_eq!(
7815 empty.iter_missing_precondition_kinds().collect::<Vec<_>>(),
7816 all,
7817 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_precondition_kinds",
7818 );
7819 assert_eq!(
7820 empty.iter_missing_postcondition_kinds().collect::<Vec<_>>(),
7821 all,
7822 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_postcondition_kinds",
7823 );
7824 assert_eq!(
7825 empty.iter_missing_condition_kinds().collect::<Vec<_>>(),
7826 all,
7827 "empty ephemeral spec must yield ConditionKind::ALL on iter_missing_condition_kinds",
7828 );
7829
7830 for pre_kind in ConditionKind::ALL {
7831 for post_kind in ConditionKind::ALL {
7832 let mut spec = empty_ephemeral();
7833 spec.preconditions.push(cond(pre_kind));
7834 spec.postconditions.push(cond(post_kind));
7835
7836 let pre_via_iter: Vec<_> = spec.iter_missing_precondition_kinds().collect();
7837 assert_eq!(
7838 pre_via_iter,
7839 spec.missing_precondition_kinds(),
7840 "EphemeralSpec::iter_missing_precondition_kinds().collect() drifted from \
7841 missing_precondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7842 );
7843 let post_via_iter: Vec<_> = spec.iter_missing_postcondition_kinds().collect();
7844 assert_eq!(
7845 post_via_iter,
7846 spec.missing_postcondition_kinds(),
7847 "EphemeralSpec::iter_missing_postcondition_kinds().collect() drifted from \
7848 missing_postcondition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7849 );
7850 let union_via_iter: Vec<_> = spec.iter_missing_condition_kinds().collect();
7851 assert_eq!(
7852 union_via_iter,
7853 spec.missing_condition_kinds(),
7854 "EphemeralSpec::iter_missing_condition_kinds().collect() drifted from \
7855 missing_condition_kinds() for pre={pre_kind:?} post={post_kind:?}",
7856 );
7857 }
7858 }
7859 }
7860
7861 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-set triad) —
7862 /// the three `missing_*_kinds` methods on [`EphemeralSpec`]
7863 /// delegate to the slice-level substrate primitive
7864 /// [`crate::boundary::ConditionSliceExt::missing_kinds`] over the
7865 /// two `Vec<Condition>` slots and compose the union via
7866 /// `ConditionKind::ALL.filter(|k| !has_condition_kind(*k))`. Sweep
7867 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7868 /// `missing_condition_kinds_triad_delegates_to_slice_missing_kinds`
7869 /// on the point-domain [`crate::boundary::Boundary`] surface —
7870 /// both peers compose against the SAME slice-level substrate
7871 /// primitive so a regression at the per-slice complement walk
7872 /// fails at that primitive's tests rather than as silent drift at
7873 /// either struct-level arm.
7874 #[test]
7875 fn ephemeral_missing_condition_kinds_triad_delegates_to_slice_missing_kinds() {
7876 // Empty ephemeral spec — every arm returns ConditionKind::ALL.
7877 let empty = empty_ephemeral();
7878 let all_kinds = ConditionKind::ALL.to_vec();
7879 assert_eq!(
7880 empty.missing_precondition_kinds(),
7881 all_kinds,
7882 "empty ephemeral spec must return ConditionKind::ALL on missing_precondition_kinds",
7883 );
7884 assert_eq!(
7885 empty.missing_postcondition_kinds(),
7886 all_kinds,
7887 "empty ephemeral spec must return ConditionKind::ALL on missing_postcondition_kinds",
7888 );
7889 assert_eq!(
7890 empty.missing_condition_kinds(),
7891 all_kinds,
7892 "empty ephemeral spec must return ConditionKind::ALL on missing_condition_kinds",
7893 );
7894
7895 for pre_kind in ConditionKind::ALL {
7896 for post_kind in ConditionKind::ALL {
7897 let mut spec = empty_ephemeral();
7898 spec.preconditions.push(cond(pre_kind));
7899 spec.postconditions.push(cond(post_kind));
7900
7901 assert_eq!(
7902 spec.missing_precondition_kinds(),
7903 spec.preconditions.missing_kinds(),
7904 "EphemeralSpec::missing_precondition_kinds must delegate verbatim to \
7905 preconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7906 );
7907 assert_eq!(
7908 spec.missing_postcondition_kinds(),
7909 spec.postconditions.missing_kinds(),
7910 "EphemeralSpec::missing_postcondition_kinds must delegate verbatim to \
7911 postconditions.missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
7912 );
7913 // Union: a kind is missing from the union iff it is
7914 // missing from BOTH half-slices (SET-INTERSECTION).
7915 let expected_union: Vec<_> = ConditionKind::ALL
7916 .into_iter()
7917 .filter(|k| pre_kind != *k && post_kind != *k)
7918 .collect();
7919 assert_eq!(
7920 spec.missing_condition_kinds(),
7921 expected_union,
7922 "EphemeralSpec::missing_condition_kinds must equal ConditionKind::ALL-ordered \
7923 set-INTERSECTION of the two half-slice missing-sets for pre={pre_kind:?} post={post_kind:?}",
7924 );
7925 // Partition invariant (distinct ∪ missing == ALL, disjoint).
7926 let distinct = spec.distinct_condition_kinds();
7927 let missing = spec.missing_condition_kinds();
7928 for kind in ConditionKind::ALL {
7929 assert!(
7930 distinct.contains(&kind) ^ missing.contains(&kind),
7931 "EphemeralSpec (distinct, missing) partition violated on {kind:?} for pre={pre_kind:?} post={post_kind:?}",
7932 );
7933 }
7934 assert_eq!(
7935 distinct.len() + missing.len(),
7936 ConditionKind::ALL.len(),
7937 "EphemeralSpec (distinct, missing) cardinality partition drift for pre={pre_kind:?} post={post_kind:?}",
7938 );
7939 }
7940 }
7941 }
7942
7943 /// SUBSTRATE-DELEGATION pin (EphemeralSpec missing-kind-count triad)
7944 /// — the three `missing_*_kind_count` methods on [`EphemeralSpec`]
7945 /// delegate to the slice-level substrate primitive
7946 /// [`crate::boundary::ConditionSliceExt::missing_kind_count`] over
7947 /// the two `Vec<Condition>` slots and compose the union scalar via
7948 /// `ConditionKind::ALL.iter().filter(|k|
7949 /// !has_condition_kind(**k)).count()`. Sweep
7950 /// `ConditionKind::ALL × ConditionKind::ALL`. Byte-for-byte peer of
7951 /// `missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count`
7952 /// on the point-domain [`crate::boundary::Boundary`] surface —
7953 /// both peers compose against the SAME slice-level substrate
7954 /// primitive so a regression at the per-slice negated closed-set
7955 /// walk fails at that primitive's tests rather than as silent drift
7956 /// at either struct-level scalar-cardinality arm. Also pins the
7957 /// scalar-partition invariant `distinct_kind_count +
7958 /// missing_kind_count == ConditionKind::ALL.len()` per arrangement.
7959 #[test]
7960 fn ephemeral_missing_condition_kind_count_triad_delegates_to_slice_missing_kind_count() {
7961 // Empty ephemeral spec — every arm returns ConditionKind::ALL.len().
7962 let empty = empty_ephemeral();
7963 let total = ConditionKind::ALL.len();
7964 assert_eq!(
7965 empty.missing_precondition_kind_count(),
7966 total,
7967 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_precondition_kind_count",
7968 );
7969 assert_eq!(
7970 empty.missing_postcondition_kind_count(),
7971 total,
7972 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_postcondition_kind_count",
7973 );
7974 assert_eq!(
7975 empty.missing_condition_kind_count(),
7976 total,
7977 "empty ephemeral spec must return ConditionKind::ALL.len() on missing_condition_kind_count",
7978 );
7979
7980 for pre_kind in ConditionKind::ALL {
7981 for post_kind in ConditionKind::ALL {
7982 let mut spec = empty_ephemeral();
7983 spec.preconditions.push(cond(pre_kind));
7984 spec.postconditions.push(cond(post_kind));
7985
7986 // Half-slice arms delegate byte-for-byte to the slice
7987 // substrate primitive.
7988 assert_eq!(
7989 spec.missing_precondition_kind_count(),
7990 spec.preconditions.missing_kind_count(),
7991 "EphemeralSpec::missing_precondition_kind_count must delegate verbatim to \
7992 preconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
7993 );
7994 assert_eq!(
7995 spec.missing_precondition_kind_count(),
7996 spec.missing_precondition_kinds().len(),
7997 "EphemeralSpec::missing_precondition_kind_count must equal \
7998 missing_precondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
7999 );
8000 assert_eq!(
8001 spec.missing_postcondition_kind_count(),
8002 spec.postconditions.missing_kind_count(),
8003 "EphemeralSpec::missing_postcondition_kind_count must delegate verbatim to \
8004 postconditions.missing_kind_count() for pre={pre_kind:?} post={post_kind:?}",
8005 );
8006 assert_eq!(
8007 spec.missing_postcondition_kind_count(),
8008 spec.missing_postcondition_kinds().len(),
8009 "EphemeralSpec::missing_postcondition_kind_count must equal \
8010 missing_postcondition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
8011 );
8012 // Union arm equals missing_condition_kinds().len().
8013 assert_eq!(
8014 spec.missing_condition_kind_count(),
8015 spec.missing_condition_kinds().len(),
8016 "EphemeralSpec::missing_condition_kind_count must equal \
8017 missing_condition_kinds().len() for pre={pre_kind:?} post={post_kind:?}",
8018 );
8019 // Scalar-partition invariant: distinct + missing == ALL.
8020 assert_eq!(
8021 spec.distinct_condition_kind_count() + spec.missing_condition_kind_count(),
8022 ConditionKind::ALL.len(),
8023 "EphemeralSpec (distinct, missing) scalar partition drift for pre={pre_kind:?} post={post_kind:?}",
8024 );
8025 }
8026 }
8027 }
8028
8029 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-distinct-kind
8030 /// triad) — the three `first_distinct_*_kind` methods on
8031 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
8032 /// [`crate::boundary::ConditionSliceExt::first_distinct_kind`] over
8033 /// the two `Vec<Condition>` slots and compose the union via
8034 /// `ConditionKind::ALL.iter().copied().find(|k|
8035 /// has_condition_kind(*k))`. Byte-for-byte peer of
8036 /// `first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind`
8037 /// on the point-domain [`crate::boundary::Boundary`] surface — both
8038 /// peers compose against the SAME slice-level substrate primitive
8039 /// so a regression at the per-slice short-circuit walk fails at
8040 /// that primitive's tests rather than as silent drift at either
8041 /// struct-level earliest-element arm.
8042 #[test]
8043 fn ephemeral_first_distinct_condition_kind_triad_delegates_to_slice_first_distinct_kind() {
8044 // Empty ephemeral spec — every arm returns None.
8045 let empty = empty_ephemeral();
8046 assert_eq!(
8047 empty.first_distinct_precondition_kind(),
8048 None,
8049 "empty ephemeral spec must return None on first_distinct_precondition_kind",
8050 );
8051 assert_eq!(
8052 empty.first_distinct_postcondition_kind(),
8053 None,
8054 "empty ephemeral spec must return None on first_distinct_postcondition_kind",
8055 );
8056 assert_eq!(
8057 empty.first_distinct_condition_kind(),
8058 None,
8059 "empty ephemeral spec must return None on first_distinct_condition_kind",
8060 );
8061
8062 for pre_kind in ConditionKind::ALL {
8063 for post_kind in ConditionKind::ALL {
8064 let mut spec = empty_ephemeral();
8065 spec.preconditions.push(cond(pre_kind));
8066 spec.postconditions.push(cond(post_kind));
8067
8068 assert_eq!(
8069 spec.first_distinct_precondition_kind(),
8070 spec.preconditions.first_distinct_kind(),
8071 "EphemeralSpec::first_distinct_precondition_kind must delegate verbatim to \
8072 preconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8073 );
8074 assert_eq!(
8075 spec.first_distinct_precondition_kind(),
8076 spec.distinct_precondition_kinds().first().copied(),
8077 "EphemeralSpec::first_distinct_precondition_kind must equal \
8078 distinct_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8079 );
8080 assert_eq!(
8081 spec.first_distinct_postcondition_kind(),
8082 spec.postconditions.first_distinct_kind(),
8083 "EphemeralSpec::first_distinct_postcondition_kind must delegate verbatim to \
8084 postconditions.first_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8085 );
8086 assert_eq!(
8087 spec.first_distinct_postcondition_kind(),
8088 spec.distinct_postcondition_kinds().first().copied(),
8089 "EphemeralSpec::first_distinct_postcondition_kind must equal \
8090 distinct_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8091 );
8092 let expected_union = ConditionKind::ALL
8093 .into_iter()
8094 .find(|k| pre_kind == *k || post_kind == *k);
8095 assert_eq!(
8096 spec.first_distinct_condition_kind(),
8097 expected_union,
8098 "EphemeralSpec::first_distinct_condition_kind must equal earliest ALL entry \
8099 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8100 );
8101 assert_eq!(
8102 spec.first_distinct_condition_kind(),
8103 spec.distinct_condition_kinds().first().copied(),
8104 "EphemeralSpec::first_distinct_condition_kind must equal \
8105 distinct_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8106 );
8107 }
8108 }
8109 }
8110
8111 /// SUBSTRATE-DELEGATION pin (EphemeralSpec first-missing-kind triad)
8112 /// — the three `first_missing_*_kind` methods on [`EphemeralSpec`]
8113 /// delegate to the slice-level substrate primitive
8114 /// [`crate::boundary::ConditionSliceExt::first_missing_kind`] over
8115 /// the two `Vec<Condition>` slots and compose the union via
8116 /// `ConditionKind::ALL.iter().copied().find(|k|
8117 /// !has_condition_kind(*k))`. Byte-for-byte peer of
8118 /// `first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind`
8119 /// on the point-domain [`crate::boundary::Boundary`] surface.
8120 #[test]
8121 fn ephemeral_first_missing_condition_kind_triad_delegates_to_slice_first_missing_kind() {
8122 // Empty ephemeral spec — every arm returns Some(ConditionKind::ALL[0]).
8123 let empty = empty_ephemeral();
8124 let first = Some(ConditionKind::ALL[0]);
8125 assert_eq!(
8126 empty.first_missing_precondition_kind(),
8127 first,
8128 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_precondition_kind",
8129 );
8130 assert_eq!(
8131 empty.first_missing_postcondition_kind(),
8132 first,
8133 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_postcondition_kind",
8134 );
8135 assert_eq!(
8136 empty.first_missing_condition_kind(),
8137 first,
8138 "empty ephemeral spec must return Some(ConditionKind::ALL[0]) on first_missing_condition_kind",
8139 );
8140
8141 for pre_kind in ConditionKind::ALL {
8142 for post_kind in ConditionKind::ALL {
8143 let mut spec = empty_ephemeral();
8144 spec.preconditions.push(cond(pre_kind));
8145 spec.postconditions.push(cond(post_kind));
8146
8147 assert_eq!(
8148 spec.first_missing_precondition_kind(),
8149 spec.preconditions.first_missing_kind(),
8150 "EphemeralSpec::first_missing_precondition_kind must delegate verbatim to \
8151 preconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8152 );
8153 assert_eq!(
8154 spec.first_missing_precondition_kind(),
8155 spec.missing_precondition_kinds().first().copied(),
8156 "EphemeralSpec::first_missing_precondition_kind must equal \
8157 missing_precondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8158 );
8159 assert_eq!(
8160 spec.first_missing_postcondition_kind(),
8161 spec.postconditions.first_missing_kind(),
8162 "EphemeralSpec::first_missing_postcondition_kind must delegate verbatim to \
8163 postconditions.first_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8164 );
8165 assert_eq!(
8166 spec.first_missing_postcondition_kind(),
8167 spec.missing_postcondition_kinds().first().copied(),
8168 "EphemeralSpec::first_missing_postcondition_kind must equal \
8169 missing_postcondition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8170 );
8171 let expected_union = ConditionKind::ALL
8172 .into_iter()
8173 .find(|k| pre_kind != *k && post_kind != *k);
8174 assert_eq!(
8175 spec.first_missing_condition_kind(),
8176 expected_union,
8177 "EphemeralSpec::first_missing_condition_kind must equal earliest ALL entry \
8178 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8179 );
8180 assert_eq!(
8181 spec.first_missing_condition_kind(),
8182 spec.missing_condition_kinds().first().copied(),
8183 "EphemeralSpec::first_missing_condition_kind must equal \
8184 missing_condition_kinds().first().copied() for pre={pre_kind:?} post={post_kind:?}",
8185 );
8186 }
8187 }
8188 }
8189
8190 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-distinct-kind
8191 /// triad) — the three `last_distinct_*_kind` methods on
8192 /// [`EphemeralSpec`] delegate to the slice-level substrate
8193 /// primitive [`crate::boundary::ConditionSliceExt::last_distinct_kind`]
8194 /// over the two `Vec<Condition>` slots and compose the union via
8195 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
8196 /// has_condition_kind(*k))`. Byte-for-byte peer of
8197 /// `last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind`
8198 /// on the point-domain [`crate::boundary::Boundary`] surface —
8199 /// both peers compose against the SAME slice-level substrate
8200 /// primitive so a regression at the per-slice REVERSED short-
8201 /// circuit walk fails at that primitive's tests rather than as
8202 /// silent drift at either struct-level latest-element arm.
8203 #[test]
8204 fn ephemeral_last_distinct_condition_kind_triad_delegates_to_slice_last_distinct_kind() {
8205 // Empty ephemeral spec — every arm returns None.
8206 let empty = empty_ephemeral();
8207 assert_eq!(
8208 empty.last_distinct_precondition_kind(),
8209 None,
8210 "empty ephemeral spec must return None on last_distinct_precondition_kind",
8211 );
8212 assert_eq!(
8213 empty.last_distinct_postcondition_kind(),
8214 None,
8215 "empty ephemeral spec must return None on last_distinct_postcondition_kind",
8216 );
8217 assert_eq!(
8218 empty.last_distinct_condition_kind(),
8219 None,
8220 "empty ephemeral spec must return None on last_distinct_condition_kind",
8221 );
8222
8223 for pre_kind in ConditionKind::ALL {
8224 for post_kind in ConditionKind::ALL {
8225 let mut spec = empty_ephemeral();
8226 spec.preconditions.push(cond(pre_kind));
8227 spec.postconditions.push(cond(post_kind));
8228
8229 assert_eq!(
8230 spec.last_distinct_precondition_kind(),
8231 spec.preconditions.last_distinct_kind(),
8232 "EphemeralSpec::last_distinct_precondition_kind must delegate verbatim to \
8233 preconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8234 );
8235 assert_eq!(
8236 spec.last_distinct_precondition_kind(),
8237 spec.distinct_precondition_kinds().last().copied(),
8238 "EphemeralSpec::last_distinct_precondition_kind must equal \
8239 distinct_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8240 );
8241 assert_eq!(
8242 spec.last_distinct_postcondition_kind(),
8243 spec.postconditions.last_distinct_kind(),
8244 "EphemeralSpec::last_distinct_postcondition_kind must delegate verbatim to \
8245 postconditions.last_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
8246 );
8247 assert_eq!(
8248 spec.last_distinct_postcondition_kind(),
8249 spec.distinct_postcondition_kinds().last().copied(),
8250 "EphemeralSpec::last_distinct_postcondition_kind must equal \
8251 distinct_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8252 );
8253 let expected_union = ConditionKind::ALL
8254 .into_iter()
8255 .rev()
8256 .find(|k| pre_kind == *k || post_kind == *k);
8257 assert_eq!(
8258 spec.last_distinct_condition_kind(),
8259 expected_union,
8260 "EphemeralSpec::last_distinct_condition_kind must equal latest ALL entry \
8261 populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8262 );
8263 assert_eq!(
8264 spec.last_distinct_condition_kind(),
8265 spec.distinct_condition_kinds().last().copied(),
8266 "EphemeralSpec::last_distinct_condition_kind must equal \
8267 distinct_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8268 );
8269 }
8270 }
8271 }
8272
8273 /// SUBSTRATE-DELEGATION pin (EphemeralSpec last-missing-kind triad)
8274 /// — the three `last_missing_*_kind` methods on [`EphemeralSpec`]
8275 /// delegate to the slice-level substrate primitive
8276 /// [`crate::boundary::ConditionSliceExt::last_missing_kind`] over
8277 /// the two `Vec<Condition>` slots and compose the union via
8278 /// `ConditionKind::ALL.iter().rev().copied().find(|k|
8279 /// !has_condition_kind(*k))`. Byte-for-byte peer of
8280 /// `last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind`
8281 /// on the point-domain [`crate::boundary::Boundary`] surface.
8282 #[test]
8283 fn ephemeral_last_missing_condition_kind_triad_delegates_to_slice_last_missing_kind() {
8284 // Empty ephemeral spec — every arm returns Some(*ConditionKind::ALL.last().unwrap()).
8285 let empty = empty_ephemeral();
8286 let last = ConditionKind::ALL.last().copied();
8287 assert_eq!(
8288 empty.last_missing_precondition_kind(),
8289 last,
8290 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_precondition_kind",
8291 );
8292 assert_eq!(
8293 empty.last_missing_postcondition_kind(),
8294 last,
8295 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_postcondition_kind",
8296 );
8297 assert_eq!(
8298 empty.last_missing_condition_kind(),
8299 last,
8300 "empty ephemeral spec must return Some(*ConditionKind::ALL.last().unwrap()) on last_missing_condition_kind",
8301 );
8302
8303 for pre_kind in ConditionKind::ALL {
8304 for post_kind in ConditionKind::ALL {
8305 let mut spec = empty_ephemeral();
8306 spec.preconditions.push(cond(pre_kind));
8307 spec.postconditions.push(cond(post_kind));
8308
8309 assert_eq!(
8310 spec.last_missing_precondition_kind(),
8311 spec.preconditions.last_missing_kind(),
8312 "EphemeralSpec::last_missing_precondition_kind must delegate verbatim to \
8313 preconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8314 );
8315 assert_eq!(
8316 spec.last_missing_precondition_kind(),
8317 spec.missing_precondition_kinds().last().copied(),
8318 "EphemeralSpec::last_missing_precondition_kind must equal \
8319 missing_precondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8320 );
8321 assert_eq!(
8322 spec.last_missing_postcondition_kind(),
8323 spec.postconditions.last_missing_kind(),
8324 "EphemeralSpec::last_missing_postcondition_kind must delegate verbatim to \
8325 postconditions.last_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
8326 );
8327 assert_eq!(
8328 spec.last_missing_postcondition_kind(),
8329 spec.missing_postcondition_kinds().last().copied(),
8330 "EphemeralSpec::last_missing_postcondition_kind must equal \
8331 missing_postcondition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8332 );
8333 let expected_union = ConditionKind::ALL
8334 .into_iter()
8335 .rev()
8336 .find(|k| pre_kind != *k && post_kind != *k);
8337 assert_eq!(
8338 spec.last_missing_condition_kind(),
8339 expected_union,
8340 "EphemeralSpec::last_missing_condition_kind must equal latest ALL entry \
8341 NOT populated by either half-slice for pre={pre_kind:?} post={post_kind:?}",
8342 );
8343 assert_eq!(
8344 spec.last_missing_condition_kind(),
8345 spec.missing_condition_kinds().last().copied(),
8346 "EphemeralSpec::last_missing_condition_kind must equal \
8347 missing_condition_kinds().last().copied() for pre={pre_kind:?} post={post_kind:?}",
8348 );
8349 }
8350 }
8351 }
8352
8353 // ── assert_slice_refinement_composition_laws — mirror invocations ──
8354 //
8355 // The substrate testkit primitive
8356 // [`crate::boundary::assert_slice_refinement_composition_laws`]
8357 // pins the FOUR composition laws that bind the
8358 // [`crate::boundary::ConditionSliceExt`] refinement algebra
8359 // (find ↔ iter, count ↔ iter, has ↔ find, has ↔ count) at ONE
8360 // call site per authored arrangement, sweeping
8361 // [`ConditionKind::ALL`]. The two ephemeral-surface tests below
8362 // dispatch the primitive against the two `Vec<Condition>` slots
8363 // ([`EphemeralSpec::preconditions`] +
8364 // [`EphemeralSpec::postconditions`]) authored through the
8365 // ephemeral-surface test-fixture — byte-for-byte peer of the
8366 // point-surface `slice_refinement_composition_laws_hold_across_authored_arrangements`
8367 // + `slice_refinement_composition_laws_hold_on_interleaved_duplicates`
8368 // pins on the [`crate::boundary::Boundary`] surface. Two-surface
8369 // parity contract: the substrate primitive holds on every slice
8370 // reachable through either the point-surface `.preconditions` /
8371 // `.postconditions` fields OR the ephemeral-surface's
8372 // eponymous field pair.
8373
8374 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate
8375 /// primitive [`assert_slice_refinement_composition_laws`] holds
8376 /// on both [`EphemeralSpec::preconditions`] and
8377 /// [`EphemeralSpec::postconditions`] slices for every populated-
8378 /// pair authored through the ephemeral-surface test-fixture.
8379 /// Byte-for-byte peer of
8380 /// `slice_refinement_composition_laws_hold_across_authored_arrangements`
8381 /// on the point surface.
8382 #[test]
8383 fn ephemeral_slice_refinement_composition_laws_hold_across_authored_arrangements() {
8384 let empty = empty_ephemeral();
8385 assert_slice_refinement_composition_laws(empty.preconditions.as_slice());
8386 assert_slice_refinement_composition_laws(empty.postconditions.as_slice());
8387
8388 for pre_kind in ConditionKind::ALL {
8389 for post_kind in ConditionKind::ALL {
8390 let mut spec = empty_ephemeral();
8391 spec.preconditions.push(cond(pre_kind));
8392 spec.postconditions.push(cond(post_kind));
8393 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
8394 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
8395 }
8396 }
8397
8398 for populated in ConditionKind::ALL {
8399 let mut spec = empty_ephemeral();
8400 spec.preconditions.push(cond(populated));
8401 spec.preconditions.push(cond(populated));
8402 spec.preconditions.push(cond(populated));
8403 spec.postconditions.push(cond(populated));
8404 spec.postconditions.push(cond(populated));
8405 assert_slice_refinement_composition_laws(spec.preconditions.as_slice());
8406 assert_slice_refinement_composition_laws(spec.postconditions.as_slice());
8407 }
8408 }
8409
8410 // ── assert_surface_union_composition_laws — ephemeral surface ────
8411 //
8412 // The substrate testkit macro
8413 // [`crate::assert_surface_union_composition_laws`] pins the FOUR
8414 // union composition laws (has: OR, find: or_else, iter: chain,
8415 // count: SUM) that bind the (pre, post, union) refinement triads
8416 // on the [`EphemeralSpec`] sugar-surface at ONE call site per
8417 // authored arrangement, sweeping [`ConditionKind::ALL`]. Byte-for-
8418 // byte peer of the point-surface
8419 // `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
8420 // / `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
8421 // pins on the [`crate::boundary::Boundary`] surface — the two-
8422 // surface parity contract binds every downstream `condition-<K>`
8423 // / `precondition-<K>` / `postcondition-<K>` require-tag classifier
8424 // on either surface to the SAME four union-composition operators
8425 // through ONE substrate primitive rather than through per-surface
8426 // author-time re-authored sweeps.
8427
8428 /// SUBSTRATE PANEL pin (ephemeral surface) — the substrate macro
8429 /// [`crate::assert_surface_union_composition_laws`] passes on
8430 /// [`EphemeralSpec`] for the four canonical authored arrangements
8431 /// (empty spec, precondition-only populated, postcondition-only
8432 /// populated, dual-populated sweep over `ALL × ALL`). Byte-for-byte
8433 /// peer of the point-surface
8434 /// `boundary_surface_union_composition_laws_hold_across_authored_arrangements`
8435 /// pin — the two-surface parity contract binds every union
8436 /// composition law on both surfaces to the SAME substrate
8437 /// primitive.
8438 #[test]
8439 fn ephemeral_surface_union_composition_laws_hold_across_authored_arrangements() {
8440 let empty = empty_ephemeral();
8441 crate::assert_surface_union_composition_laws!(empty);
8442
8443 for populated in ConditionKind::ALL {
8444 let mut pre_only = empty_ephemeral();
8445 pre_only.preconditions.push(cond(populated));
8446 crate::assert_surface_union_composition_laws!(pre_only);
8447
8448 let mut post_only = empty_ephemeral();
8449 post_only.postconditions.push(cond(populated));
8450 crate::assert_surface_union_composition_laws!(post_only);
8451 }
8452
8453 for pre_kind in ConditionKind::ALL {
8454 for post_kind in ConditionKind::ALL {
8455 let mut dual = empty_ephemeral();
8456 dual.preconditions.push(cond(pre_kind));
8457 dual.postconditions.push(cond(post_kind));
8458 crate::assert_surface_union_composition_laws!(dual);
8459 }
8460 }
8461 }
8462
8463 /// SUBSTRATE PANEL pin (ephemeral surface, params-distinguishable
8464 /// duplicates) — the substrate macro holds on an [`EphemeralSpec`]
8465 /// whose two half-slices each carry duplicates of the same kind at
8466 /// multiple positions interleaved with a distinct kind. Byte-for-
8467 /// byte peer of the point-surface
8468 /// `boundary_surface_union_composition_laws_hold_on_interleaved_duplicates`
8469 /// pin — the non-degenerate composition of every union arm on the
8470 /// sugar-surface binds against the SAME four monoid operators as
8471 /// the point-surface peer. A regression on the ephemeral surface
8472 /// only that (a) collapsed `find`'s `or_else` to `and_then`, (b)
8473 /// collapsed `iter`'s `chain` to `zip`, or (c) collapsed `count`'s
8474 /// SUM to `max` surfaces HERE, breaking two-surface parity.
8475 #[test]
8476 fn ephemeral_surface_union_composition_laws_hold_on_interleaved_duplicates() {
8477 let mut spec = empty_ephemeral();
8478 spec.preconditions.push(Condition {
8479 kind: ConditionKind::ClosedLoopAuth,
8480 params: serde_json::json!({ "side": "pre-1" }),
8481 });
8482 spec.preconditions.push(Condition {
8483 kind: ConditionKind::PromQL,
8484 params: serde_json::json!({ "query": "up" }),
8485 });
8486 spec.preconditions.push(Condition {
8487 kind: ConditionKind::ClosedLoopAuth,
8488 params: serde_json::json!({ "side": "pre-2" }),
8489 });
8490 spec.postconditions.push(Condition {
8491 kind: ConditionKind::PromQL,
8492 params: serde_json::json!({ "query": "healthy" }),
8493 });
8494 spec.postconditions.push(Condition {
8495 kind: ConditionKind::ClosedLoopAuth,
8496 params: serde_json::json!({ "side": "post-1" }),
8497 });
8498 crate::assert_surface_union_composition_laws!(spec);
8499 }
8500
8501 #[test]
8502 fn from_impl_clears_other_intent_variants() {
8503 // Even if someone constructs an EphemeralSpec by hand and the
8504 // resulting ProcessSpec is later mutated, the From bridge sets
8505 // every non-Aplicacao slot to None explicitly.
8506 let e = EphemeralSpec {
8507 aplicacao: demo_overlay(),
8508 ttl: "10m".into(),
8509 teardown: TeardownPolicy::Never,
8510 max_concurrent: 0,
8511 postconditions: vec![],
8512 preconditions: vec![],
8513 verify_timeout: None,
8514 classification: None,
8515 parent: Some("seph.1".into()),
8516 exports: vec![],
8517 routing: None,
8518 };
8519 let ps: ProcessSpec = e.into();
8520 assert!(ps.intent.nix.is_none());
8521 assert!(ps.intent.flux.is_none());
8522 assert!(ps.intent.lisp.is_none());
8523 assert!(ps.intent.container.is_none());
8524 assert!(ps.intent.guest.is_none());
8525 assert!(ps.intent.aplicacao.is_some());
8526 assert_eq!(ps.identity.parent.as_deref(), Some("seph.1"));
8527 }
8528
8529 // ── EphemeralSpec::has_teardown_policy substrate pins ────────────
8530 //
8531 // Fail-before-pass-after granularity:
8532 // `EphemeralSpec::has_teardown_policy` did not exist before this
8533 // commit — the (`self.teardown == kind`) scalar-carrier probe on
8534 // the sugar-surface [`EphemeralSpec`] lived only implicitly via
8535 // hand-authored comparisons at potential future call sites, with
8536 // no analogue to the peer
8537 // [`crate::lifetime::EphemeralLifetime::has_teardown_policy`] on
8538 // the point-surface carrier. The lift adds the peer inherent
8539 // method on the [`EphemeralSpec`] sugar-surface so both surfaces'
8540 // `teardown-policy-<kind>` require-tag families in
8541 // `tatara-reconciler::bin::tatara-check` compose against the SAME
8542 // scalar `==` shape in lockstep. A regression that (a) hard-coded
8543 // the arm to a single kind, (b) inverted the closed-set match
8544 // (silently returning `true` on non-matching variants), or (c)
8545 // probed the wrong slot (a stray comparison against `ttl` /
8546 // `max_concurrent`) fails HERE at the substrate primitive rather
8547 // than as silent operator-facing drift at the ephemeral
8548 // `teardown-policy-<kind>` require-tag surface.
8549
8550 /// STORED-slot pin — an ephemeral spec that carries a given
8551 /// [`TeardownPolicy`] returns `true` for that kind, `false` for
8552 /// every other variant. Sweep the [`TeardownPolicy::ALL`] × ALL
8553 /// cross so a regression that hard-coded the arm to a single kind
8554 /// or wired the closure to a fixed unrelated field fails HERE at
8555 /// the substrate primitive. Byte-for-byte peer of
8556 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_returns_true_iff_variant_matches`]
8557 /// on the point-surface [`crate::lifetime::EphemeralLifetime`]
8558 /// carrier — the two surfaces publish identical `==` scalar
8559 /// semantics on their respective `teardown` / `teardown_policy`
8560 /// slots.
8561 #[test]
8562 fn has_teardown_policy_returns_true_iff_ephemeral_teardown_matches_per_kind() {
8563 for populated in TeardownPolicy::ALL {
8564 let mut spec = empty_ephemeral();
8565 spec.teardown = populated;
8566 for query in TeardownPolicy::ALL {
8567 let expected = query == populated;
8568 assert_eq!(
8569 spec.has_teardown_policy(query),
8570 expected,
8571 "ephemeral teardown={populated:?}: query {query:?} drifted",
8572 );
8573 }
8574 }
8575 }
8576
8577 /// DEFAULT-SLOT pin — an [`EphemeralSpec`] whose `teardown` slot
8578 /// is [`TeardownPolicy::default`] (`Always`) returns `true` for
8579 /// `Always` and `false` for every other variant. The
8580 /// (required-scalar-child) corner has no absent state — a
8581 /// hand-authored spec that omits `:teardown` from the
8582 /// `(defephemeral …)` form IS configured for `Always`, and this
8583 /// pin locks the corner's default-arm short-circuit as identical
8584 /// to the (Option-parent × defaulted-scalar-child) corner's
8585 /// reachable arm on the point surface (both return `true` on
8586 /// `Always` only). Byte-for-byte peer of
8587 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_policy_default_probes_always_only`]
8588 /// on the point-surface carrier.
8589 #[test]
8590 fn has_teardown_policy_default_probes_always_only_on_ephemeral() {
8591 let spec = EphemeralSpec {
8592 teardown: TeardownPolicy::default(),
8593 ..empty_ephemeral()
8594 };
8595 for kind in TeardownPolicy::ALL {
8596 let expected = kind == TeardownPolicy::Always;
8597 assert_eq!(
8598 spec.has_teardown_policy(kind),
8599 expected,
8600 "default ephemeral (teardown=Always) baseline: query {kind:?} must be {expected}",
8601 );
8602 }
8603 }
8604
8605 // ── derived-bool-predicate presence probe on EphemeralSpec ×
8606 // TeardownPolicy × ProcessPhase ──
8607 //
8608 // Fail-before-pass-after granularity:
8609 // [`EphemeralSpec::has_teardown_firing_on`] did not exist before
8610 // this commit — the ephemeral sugar surface's require-tag algebra
8611 // discriminated the teardown axis only by the RAW authored variant
8612 // (via `teardown-policy-<kind>`), never by the derived
8613 // [`ProcessPhase`] transition the stored policy fires on
8614 // ([`TeardownPolicy::should_teardown_on`]). Post-lift the shape
8615 // lives at ONE inherent method that byte-for-byte parallels
8616 // [`crate::lifetime::EphemeralLifetime::has_teardown_firing_on`]
8617 // on the point-surface carrier, and both surfaces' require-tag
8618 // classifiers publish a symmetric `teardown-fires-on-<phase>`
8619 // family through the SAME predicate.
8620
8621 /// TRUTH-TABLE DIAGONAL — for every [`TeardownPolicy`] variant,
8622 /// an [`EphemeralSpec`] whose `teardown` slot is set to that
8623 /// variant returns `has_teardown_firing_on(phase)` in agreement
8624 /// with [`TeardownPolicy::should_teardown_on`] for every
8625 /// [`ProcessPhase`] variant. Sweep [`TeardownPolicy::ALL`] ×
8626 /// [`ProcessPhase::ALL`] full cross so a regression that hard-
8627 /// coded the arm to a single policy, wired to the wrong field, or
8628 /// inverted the predicate direction fails HERE at the substrate
8629 /// primitive on the sugar surface (byte-for-byte peer of
8630 /// [`crate::lifetime::tests::ephemeral_lifetime_has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase`]
8631 /// on the point carrier).
8632 #[test]
8633 fn has_teardown_firing_on_matches_should_teardown_on_per_policy_per_phase_on_ephemeral() {
8634 for populated in TeardownPolicy::ALL {
8635 let spec = EphemeralSpec {
8636 teardown: populated,
8637 ..empty_ephemeral()
8638 };
8639 for phase in ProcessPhase::ALL {
8640 assert_eq!(
8641 spec.has_teardown_firing_on(phase),
8642 populated.should_teardown_on(phase),
8643 "teardown={populated:?}, phase={phase:?}: predicate drift from \
8644 should_teardown_on projection",
8645 );
8646 }
8647 }
8648 }
8649
8650 /// TWO-SURFACE PARITY PIN — for every [`TeardownPolicy`] variant
8651 /// and every [`ProcessPhase`] variant, the sugar-surface probe
8652 /// and the lowered point-surface probe agree. The `EphemeralSpec
8653 /// → ProcessSpec` lowering routes the stored `teardown` slot
8654 /// through the SAME [`TeardownPolicy::should_teardown_on`]
8655 /// projection on both sides, so the sugar caller and the lowered
8656 /// caller can never disagree — a regression that (a) drifted
8657 /// [`Self::teardown`] between sugar and lowered, (b) rewired
8658 /// either probe body to bypass the shared substrate primitive, or
8659 /// (c) skewed the (policy, phase) truth table between the two
8660 /// surfaces fails HERE at the two-surface boundary rather than at
8661 /// the operator-facing require-tag classifier.
8662 #[test]
8663 fn has_teardown_firing_on_matches_point_peer_through_lowered_teardown_policy() {
8664 for populated in TeardownPolicy::ALL {
8665 let sugar = EphemeralSpec {
8666 teardown: populated,
8667 ..empty_ephemeral()
8668 };
8669 let lowered: ProcessSpec = sugar.clone().into();
8670 let lowered_eph = lowered
8671 .lifetime
8672 .resolved_ephemeral()
8673 .expect("lowered spec must be ephemeral");
8674 for phase in ProcessPhase::ALL {
8675 assert_eq!(
8676 sugar.has_teardown_firing_on(phase),
8677 lowered_eph.has_teardown_firing_on(phase),
8678 "sugar-vs-lowered predicate drift for teardown={populated:?}, phase={phase:?}",
8679 );
8680 }
8681 }
8682 }
8683
8684 // ── EphemeralSpec::resolved_classification + has_point_type pins ─────
8685 //
8686 // Fail-before-pass-after granularity: `resolved_classification` and
8687 // `has_point_type` did not exist pre-lift on `impl EphemeralSpec` — every
8688 // caller wanting the resolved [`Classification`] on the ephemeral
8689 // sugar-surface (currently zero; future ephemeral-surface classification-
8690 // axis require-tag families in `tatara-reconciler::bin::tatara-check`,
8691 // typed audit hooks, documentation generators listing the ephemeral
8692 // surface's known require-tag vocabulary) restated the two-line
8693 // `self.classification.as_ref().unwrap_or(&default_ephemeral_class())`
8694 // resolver body at their site. Post-lift both callers of the resolver
8695 // (`Self::has_point_type` and every future classification-axis peer)
8696 // route through ONE inherent method that shares the fill-through with
8697 // the sibling `From<EphemeralSpec> for ProcessSpec` lowering
8698 // byte-for-byte. A regression that (a) inverted the arm (`Some` filled
8699 // through the default), (b) drifted the default from the sibling
8700 // primitive `Classification::gate_compute()`, or (c) shifted the
8701 // `Cow<'_, Classification>` return shape (a stray `.clone()` on the
8702 // populated arm) fails HERE at the substrate primitive rather than as
8703 // silent operator-facing drift at a future
8704 // `point-type-<kind>` ephemeral require-tag surface.
8705
8706 /// AUTHORED-slot pin — an [`EphemeralSpec`] whose
8707 /// [`EphemeralSpec::classification`] slot names a concrete
8708 /// [`Classification`] returns [`Cow::Borrowed`] pointing at that
8709 /// authored value from [`Self::resolved_classification`]. Pins the
8710 /// populated-arm zero-allocation contract: a caller reading past
8711 /// the resolver sees the SAME byte address the operator authored,
8712 /// so the resolver does not silently clone the authored slot on
8713 /// the populated arm.
8714 #[test]
8715 fn resolved_classification_borrows_authored_slot() {
8716 let mut spec = empty_ephemeral();
8717 let mut authored = Classification::gate_compute();
8718 authored.point_type = ConvergencePointType::Fork;
8719 spec.classification = Some(authored.clone());
8720 let resolved = spec.resolved_classification();
8721 assert!(matches!(resolved, Cow::Borrowed(_)));
8722 assert_eq!(&*resolved, &authored);
8723 }
8724
8725 /// ABSENT-slot pin — an [`EphemeralSpec`] whose
8726 /// [`EphemeralSpec::classification`] slot is `None` returns
8727 /// [`Cow::Owned`] with the SAME value the sibling
8728 /// [`default_ephemeral_class`] baseline produces. Pins the
8729 /// two-surface parity contract with `From<EphemeralSpec> for
8730 /// ProcessSpec`: both sites fill through the SAME baseline on
8731 /// `None`, so the ephemeral require-tag surface's future
8732 /// `point-type-<kind>` family reads identically on the authored
8733 /// spec and on the mechanically lowered `ProcessSpec`.
8734 #[test]
8735 fn resolved_classification_fills_default_on_absent_slot() {
8736 let spec = empty_ephemeral();
8737 assert!(spec.classification.is_none());
8738 let resolved = spec.resolved_classification();
8739 assert!(matches!(resolved, Cow::Owned(_)));
8740 assert_eq!(&*resolved, &default_ephemeral_class());
8741 }
8742
8743 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8744 /// [`EphemeralSpec::classification`] slot names a concrete
8745 /// [`Classification`] returns `true` from
8746 /// [`Self::has_point_type`] on the authored
8747 /// [`ConvergencePointType`] slot and `false` for every other
8748 /// variant. Sweep the [`ConvergencePointType::ALL`] × ALL cross so
8749 /// a regression that hard-coded the arm to a single kind or wired
8750 /// the closure to a fixed unrelated slot fails HERE at the
8751 /// substrate primitive. Byte-for-byte peer of
8752 /// [`crate::classification::tests`]'s point-surface
8753 /// [`Classification::has_point_type`] populated-slot sweep on the
8754 /// SAME closed-set primitive.
8755 #[test]
8756 fn has_point_type_returns_true_iff_authored_classification_matches_per_kind() {
8757 for populated in ConvergencePointType::ALL {
8758 let mut classification = Classification::gate_compute();
8759 classification.point_type = populated;
8760 let mut spec = empty_ephemeral();
8761 spec.classification = Some(classification);
8762 for query in ConvergencePointType::ALL {
8763 let expected = query == populated;
8764 assert_eq!(
8765 spec.has_point_type(query),
8766 expected,
8767 "ephemeral classification.point_type={populated:?}: query {query:?} drifted",
8768 );
8769 }
8770 }
8771 }
8772
8773 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8774 /// [`EphemeralSpec::classification`] slot is `None` returns
8775 /// `true` from [`Self::has_point_type`] on
8776 /// [`ConvergencePointType::Gate`] (the `default_ephemeral_class`
8777 /// baseline's `point_type`) and `false` on every other variant.
8778 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8779 /// default-arm short-circuit: on the ephemeral sugar surface the
8780 /// parent Option is filled through the workspace baseline rather
8781 /// than reading `false` on every variant like the encapsulation-
8782 /// mode / encapsulation-target / routing-form Option-parent
8783 /// corners.
8784 #[test]
8785 fn has_point_type_probes_gate_only_on_absent_classification() {
8786 let spec = empty_ephemeral();
8787 assert!(spec.classification.is_none());
8788 for kind in ConvergencePointType::ALL {
8789 let expected = kind == ConvergencePointType::Gate;
8790 assert_eq!(
8791 spec.has_point_type(kind),
8792 expected,
8793 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8794 );
8795 }
8796 }
8797
8798 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8799 /// identically through [`Self::has_point_type`] AND through
8800 /// `<eph.clone().into::<ProcessSpec>>()`
8801 /// `.classification.has_point_type(kind)` on the mechanically-
8802 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8803 /// classification on every [`ConvergencePointType::ALL`] variant)
8804 /// × ALL queries so a future regression on either side of the
8805 /// resolver (a shift in the ephemeral resolver's default, a
8806 /// shift in the `From<EphemeralSpec>` lowering's fill-through)
8807 /// fails HERE at the parity boundary.
8808 #[test]
8809 fn has_point_type_matches_point_peer_through_lowered_classification() {
8810 // Absent classification: both surfaces resolve through the SAME
8811 // default and agree on every variant.
8812 let eph = empty_ephemeral();
8813 let lowered: ProcessSpec = eph.clone().into();
8814 for query in ConvergencePointType::ALL {
8815 assert_eq!(
8816 eph.has_point_type(query),
8817 lowered.classification.has_point_type(query),
8818 "None-classification parity drift on query {query:?}",
8819 );
8820 }
8821 // Authored classification: both surfaces read the same authored
8822 // value verbatim.
8823 for populated in ConvergencePointType::ALL {
8824 let mut classification = Classification::gate_compute();
8825 classification.point_type = populated;
8826 let mut eph = empty_ephemeral();
8827 eph.classification = Some(classification);
8828 let lowered: ProcessSpec = eph.clone().into();
8829 for query in ConvergencePointType::ALL {
8830 assert_eq!(
8831 eph.has_point_type(query),
8832 lowered.classification.has_point_type(query),
8833 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
8834 );
8835 }
8836 }
8837 }
8838
8839 // ── EphemeralSpec::has_substrate pins ────────────────────────────
8840 //
8841 // Fail-before-pass-after granularity: [`Self::has_substrate`] did
8842 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
8843 // through `.resolved_classification().substrate == kind` or through
8844 // the lowered `ProcessSpec`'s `spec.classification.has_substrate`.
8845 // Post-lift the SECOND classification-axis peer on the ephemeral
8846 // sugar surface routes through the SAME
8847 // [`Self::resolved_classification`] resolver + the sibling closed-
8848 // set primitive [`Classification::has_substrate`], so a regression
8849 // that dropped the resolver hop, inverted the `Some`/`None`
8850 // fill-through, or wired the closure to a fixed unrelated slot
8851 // fails HERE.
8852
8853 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8854 /// [`EphemeralSpec::classification`] slot names a concrete
8855 /// [`Classification`] returns `true` from
8856 /// [`Self::has_substrate`] on the authored [`SubstrateType`] slot
8857 /// and `false` for every other variant. Sweep the
8858 /// [`SubstrateType::ALL`] × ALL cross so a regression that
8859 /// hard-coded the arm to a single kind or wired the closure to a
8860 /// fixed unrelated slot fails HERE at the substrate primitive.
8861 /// Byte-for-byte peer of the point-surface
8862 /// [`Classification::has_substrate`] populated-slot sweep on the
8863 /// SAME closed-set primitive.
8864 #[test]
8865 fn has_substrate_returns_true_iff_authored_classification_matches_per_kind() {
8866 for populated in SubstrateType::ALL {
8867 let mut classification = Classification::gate_compute();
8868 classification.substrate = populated;
8869 let mut spec = empty_ephemeral();
8870 spec.classification = Some(classification);
8871 for query in SubstrateType::ALL {
8872 let expected = query == populated;
8873 assert_eq!(
8874 spec.has_substrate(query),
8875 expected,
8876 "ephemeral classification.substrate={populated:?}: query {query:?} drifted",
8877 );
8878 }
8879 }
8880 }
8881
8882 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
8883 /// [`EphemeralSpec::classification`] slot is `None` returns
8884 /// `true` from [`Self::has_substrate`] on
8885 /// [`SubstrateType::Compute`] (the `default_ephemeral_class`
8886 /// baseline's `substrate`) and `false` on every other variant.
8887 /// Pins the (Option-parent × NON-DEFAULT-scalar-child) corner's
8888 /// default-arm short-circuit on the SECOND classification-axis
8889 /// peer: on the ephemeral sugar surface the parent Option is
8890 /// filled through the workspace baseline rather than reading
8891 /// `false` on every variant like the Option-parent encapsulates /
8892 /// routing corners.
8893 #[test]
8894 fn has_substrate_probes_compute_only_on_absent_classification() {
8895 let spec = empty_ephemeral();
8896 assert!(spec.classification.is_none());
8897 for kind in SubstrateType::ALL {
8898 let expected = kind == SubstrateType::Compute;
8899 assert_eq!(
8900 spec.has_substrate(kind),
8901 expected,
8902 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
8903 );
8904 }
8905 }
8906
8907 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
8908 /// identically through [`Self::has_substrate`] AND through
8909 /// `<eph.clone().into::<ProcessSpec>>()`
8910 /// `.classification.has_substrate(kind)` on the mechanically-
8911 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
8912 /// classification on every [`SubstrateType::ALL`] variant) × ALL
8913 /// queries so a future regression on either side of the resolver
8914 /// (a shift in the ephemeral resolver's default, a shift in the
8915 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
8916 /// the parity boundary. Byte-for-byte peer of the sibling
8917 /// [`Self::has_point_type`] two-surface parity pin on the SAME
8918 /// `Cow`-resolver carrier — the SECOND classification-axis
8919 /// two-surface parity contract on the ephemeral surface.
8920 #[test]
8921 fn has_substrate_matches_point_peer_through_lowered_classification() {
8922 // Absent classification: both surfaces resolve through the SAME
8923 // default and agree on every variant.
8924 let eph = empty_ephemeral();
8925 let lowered: ProcessSpec = eph.clone().into();
8926 for query in SubstrateType::ALL {
8927 assert_eq!(
8928 eph.has_substrate(query),
8929 lowered.classification.has_substrate(query),
8930 "None-classification parity drift on query {query:?}",
8931 );
8932 }
8933 // Authored classification: both surfaces read the same authored
8934 // value verbatim.
8935 for populated in SubstrateType::ALL {
8936 let mut classification = Classification::gate_compute();
8937 classification.substrate = populated;
8938 let mut eph = empty_ephemeral();
8939 eph.classification = Some(classification);
8940 let lowered: ProcessSpec = eph.clone().into();
8941 for query in SubstrateType::ALL {
8942 assert_eq!(
8943 eph.has_substrate(query),
8944 lowered.classification.has_substrate(query),
8945 "authored classification.substrate={populated:?}: parity drift on query {query:?}",
8946 );
8947 }
8948 }
8949 }
8950
8951 // ── EphemeralSpec::has_calm pins ─────────────────────────────────
8952 //
8953 // Fail-before-pass-after granularity: [`Self::has_calm`] did not
8954 // exist pre-lift on `impl EphemeralSpec` — every callsite went
8955 // through `.resolved_classification().calm == kind` or through the
8956 // lowered `ProcessSpec`'s `spec.classification.has_calm`. Post-
8957 // lift the THIRD classification-axis peer on the ephemeral sugar
8958 // surface routes through the SAME
8959 // [`Self::resolved_classification`] resolver + the sibling closed-
8960 // set primitive [`Classification::has_calm`], so a regression that
8961 // dropped the resolver hop, inverted the `Some`/`None` fill-
8962 // through, or wired the closure to a fixed unrelated slot fails
8963 // HERE. Distinct from the FIRST + SECOND peers on the (Option-
8964 // parent × NON-DEFAULT-scalar-child) corner: the (Option-parent ×
8965 // DEFAULTED-scalar-child) corner this peer opens has BOTH the
8966 // parent fill-through baseline (`default_ephemeral_class`) AND the
8967 // child's own `#[default]` land on the SAME variant
8968 // ([`CalmClassification::Monotone`]), a two-defaults composition
8969 // property the three pins below all exercise.
8970
8971 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
8972 /// [`EphemeralSpec::classification`] slot names a concrete
8973 /// [`Classification`] returns `true` from [`Self::has_calm`] on
8974 /// the authored [`CalmClassification`] slot and `false` for every
8975 /// other variant. Sweep the [`CalmClassification::ALL`] × ALL
8976 /// cross so a regression that hard-coded the arm to a single
8977 /// kind or wired the closure to a fixed unrelated slot fails HERE
8978 /// at the substrate primitive. Byte-for-byte peer of the point-
8979 /// surface [`Classification::has_calm`] populated-slot sweep on
8980 /// the SAME closed-set primitive.
8981 #[test]
8982 fn has_calm_returns_true_iff_authored_classification_matches_per_kind() {
8983 for populated in CalmClassification::ALL {
8984 let mut classification = Classification::gate_compute();
8985 classification.calm = populated;
8986 let mut spec = empty_ephemeral();
8987 spec.classification = Some(classification);
8988 for query in CalmClassification::ALL {
8989 let expected = query == populated;
8990 assert_eq!(
8991 spec.has_calm(query),
8992 expected,
8993 "ephemeral classification.calm={populated:?}: query {query:?} drifted",
8994 );
8995 }
8996 }
8997 }
8998
8999 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9000 /// [`EphemeralSpec::classification`] slot is `None` returns
9001 /// `true` from [`Self::has_calm`] on
9002 /// [`CalmClassification::Monotone`] (the `default_ephemeral_class`
9003 /// baseline's `calm` axis AND the [`CalmClassification`] child's
9004 /// own `#[default]` variant) and `false` on every other variant.
9005 /// Pins the (Option-parent × DEFAULTED-scalar-child ×
9006 /// operator-resolvable-baseline) corner's default-arm short-
9007 /// circuit on the THIRD classification-axis peer — distinct from
9008 /// the FIRST + SECOND peers on the (Option-parent × NON-DEFAULT-
9009 /// scalar-child) corner which default through a specific chosen
9010 /// baseline ([`ConvergencePointType::Gate`],
9011 /// [`SubstrateType::Compute`]) rather than through the child's
9012 /// own `#[default]`. Two-defaults composition property: both the
9013 /// parent fill-through and the child's `#[default]` land on the
9014 /// SAME variant, so the ephemeral sugar surface's `calm-Monotone`
9015 /// require-tag reads `true` on every operator-authored spec that
9016 /// omits both the `:classification` slot AND the `:calm` sub-slot,
9017 /// pinning the workspace's monotone-by-default posture.
9018 #[test]
9019 fn has_calm_probes_monotone_only_on_absent_classification() {
9020 let spec = empty_ephemeral();
9021 assert!(spec.classification.is_none());
9022 for kind in CalmClassification::ALL {
9023 let expected = kind == CalmClassification::Monotone;
9024 assert_eq!(
9025 spec.has_calm(kind),
9026 expected,
9027 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9028 );
9029 }
9030 }
9031
9032 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9033 /// identically through [`Self::has_calm`] AND through
9034 /// `<eph.clone().into::<ProcessSpec>>()`
9035 /// `.classification.has_calm(kind)` on the mechanically-
9036 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
9037 /// classification on every [`CalmClassification::ALL`] variant) ×
9038 /// ALL queries so a future regression on either side of the
9039 /// resolver (a shift in the ephemeral resolver's default, a shift
9040 /// in the `From<EphemeralSpec>` lowering's fill-through) fails
9041 /// HERE at the parity boundary. Byte-for-byte peer of the sibling
9042 /// [`Self::has_point_type`] + [`Self::has_substrate`] two-surface
9043 /// parity pins on the SAME `Cow`-resolver carrier — the THIRD
9044 /// classification-axis two-surface parity contract on the
9045 /// ephemeral surface, and the FIRST on the (Option-parent ×
9046 /// DEFAULTED-scalar-child) corner.
9047 #[test]
9048 fn has_calm_matches_point_peer_through_lowered_classification() {
9049 // Absent classification: both surfaces resolve through the SAME
9050 // default and agree on every variant.
9051 let eph = empty_ephemeral();
9052 let lowered: ProcessSpec = eph.clone().into();
9053 for query in CalmClassification::ALL {
9054 assert_eq!(
9055 eph.has_calm(query),
9056 lowered.classification.has_calm(query),
9057 "None-classification parity drift on query {query:?}",
9058 );
9059 }
9060 // Authored classification: both surfaces read the same authored
9061 // value verbatim.
9062 for populated in CalmClassification::ALL {
9063 let mut classification = Classification::gate_compute();
9064 classification.calm = populated;
9065 let mut eph = empty_ephemeral();
9066 eph.classification = Some(classification);
9067 let lowered: ProcessSpec = eph.clone().into();
9068 for query in CalmClassification::ALL {
9069 assert_eq!(
9070 eph.has_calm(query),
9071 lowered.classification.has_calm(query),
9072 "authored classification.calm={populated:?}: parity drift on query {query:?}",
9073 );
9074 }
9075 }
9076 }
9077
9078 // ── EphemeralSpec::has_data_classification pins ──────────────────
9079 //
9080 // Fail-before-pass-after granularity: [`Self::has_data_classification`]
9081 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
9082 // went through `.resolved_classification().data_classification ==
9083 // kind` or through the lowered `ProcessSpec`'s
9084 // `spec.classification.has_data_classification`. Post-lift the
9085 // FOURTH classification-axis peer on the ephemeral sugar surface
9086 // routes through the SAME [`Self::resolved_classification`]
9087 // resolver + the sibling closed-set primitive
9088 // [`crate::classification::Classification::has_data_classification`],
9089 // so a regression that dropped the resolver hop, inverted the
9090 // `Some`/`None` fill-through, or wired the closure to a fixed
9091 // unrelated slot fails HERE. SECOND occupant on the (Option-parent
9092 // × DEFAULTED-scalar-child × operator-resolvable-baseline) corner
9093 // alongside [`Self::has_calm`]: both the parent fill-through
9094 // baseline (`default_ephemeral_class`) AND the child's own
9095 // `#[default]` land on the SAME variant
9096 // ([`DataClassification::Internal`]), a two-defaults composition
9097 // property the three pins below all exercise.
9098
9099 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9100 /// [`EphemeralSpec::classification`] slot names a concrete
9101 /// [`Classification`] returns `true` from
9102 /// [`Self::has_data_classification`] on the authored
9103 /// [`DataClassification`] slot and `false` for every other
9104 /// variant. Sweep the [`DataClassification::ALL`] × ALL cross so
9105 /// a regression that hard-coded the arm to a single kind or
9106 /// wired the closure to a fixed unrelated slot fails HERE at the
9107 /// substrate primitive. Byte-for-byte peer of the point-surface
9108 /// [`Classification::has_data_classification`] populated-slot
9109 /// sweep on the SAME closed-set primitive.
9110 #[test]
9111 fn has_data_classification_returns_true_iff_authored_classification_matches_per_kind() {
9112 for populated in DataClassification::ALL {
9113 let mut classification = Classification::gate_compute();
9114 classification.data_classification = populated;
9115 let mut spec = empty_ephemeral();
9116 spec.classification = Some(classification);
9117 for query in DataClassification::ALL {
9118 let expected = query == populated;
9119 assert_eq!(
9120 spec.has_data_classification(query),
9121 expected,
9122 "ephemeral classification.data_classification={populated:?}: query {query:?} drifted",
9123 );
9124 }
9125 }
9126 }
9127
9128 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9129 /// [`EphemeralSpec::classification`] slot is `None` returns
9130 /// `true` from [`Self::has_data_classification`] on
9131 /// [`DataClassification::Internal`] (the `default_ephemeral_class`
9132 /// baseline's `data_classification` axis AND the
9133 /// [`DataClassification`] child's own `#[default]` variant) and
9134 /// `false` on every other variant. Pins the (Option-parent ×
9135 /// DEFAULTED-scalar-child × operator-resolvable-baseline) corner's
9136 /// default-arm short-circuit on the FOURTH classification-axis
9137 /// peer — SECOND occupant on that corner after [`Self::has_calm`]
9138 /// opened it. Two-defaults composition property: both the parent
9139 /// fill-through and the child's `#[default]` land on the SAME
9140 /// variant, so the ephemeral sugar surface's
9141 /// `data-classification-Internal` require-tag reads `true` on
9142 /// every operator-authored spec that omits both the
9143 /// `:classification` slot AND the `:data-classification` sub-slot,
9144 /// pinning the workspace's internal-by-default sensitivity posture.
9145 #[test]
9146 fn has_data_classification_probes_internal_only_on_absent_classification() {
9147 let spec = empty_ephemeral();
9148 assert!(spec.classification.is_none());
9149 for kind in DataClassification::ALL {
9150 let expected = kind == DataClassification::Internal;
9151 assert_eq!(
9152 spec.has_data_classification(kind),
9153 expected,
9154 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9155 );
9156 }
9157 }
9158
9159 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9160 /// identically through [`Self::has_data_classification`] AND
9161 /// through `<eph.clone().into::<ProcessSpec>>()`
9162 /// `.classification.has_data_classification(kind)` on the
9163 /// mechanically-lowered `ProcessSpec`. Sweeps (`None`
9164 /// classification, `Some(_)` classification on every
9165 /// [`DataClassification::ALL`] variant) × ALL queries so a
9166 /// future regression on either side of the resolver (a shift in
9167 /// the ephemeral resolver's default, a shift in the
9168 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
9169 /// the parity boundary. Byte-for-byte peer of the sibling
9170 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
9171 /// [`Self::has_calm`] two-surface parity pins on the SAME
9172 /// `Cow`-resolver carrier — the FOURTH classification-axis
9173 /// two-surface parity contract on the ephemeral surface, and the
9174 /// SECOND on the (Option-parent × DEFAULTED-scalar-child) corner.
9175 #[test]
9176 fn has_data_classification_matches_point_peer_through_lowered_classification() {
9177 // Absent classification: both surfaces resolve through the SAME
9178 // default and agree on every variant.
9179 let eph = empty_ephemeral();
9180 let lowered: ProcessSpec = eph.clone().into();
9181 for query in DataClassification::ALL {
9182 assert_eq!(
9183 eph.has_data_classification(query),
9184 lowered.classification.has_data_classification(query),
9185 "None-classification parity drift on query {query:?}",
9186 );
9187 }
9188 // Authored classification: both surfaces read the same authored
9189 // value verbatim.
9190 for populated in DataClassification::ALL {
9191 let mut classification = Classification::gate_compute();
9192 classification.data_classification = populated;
9193 let mut eph = empty_ephemeral();
9194 eph.classification = Some(classification);
9195 let lowered: ProcessSpec = eph.clone().into();
9196 for query in DataClassification::ALL {
9197 assert_eq!(
9198 eph.has_data_classification(query),
9199 lowered.classification.has_data_classification(query),
9200 "authored classification.data_classification={populated:?}: parity drift on query {query:?}",
9201 );
9202 }
9203 }
9204 }
9205
9206 // ── EphemeralSpec::has_horizon_kind pins ─────────────────────────
9207 //
9208 // Fail-before-pass-after granularity: [`Self::has_horizon_kind`]
9209 // did not exist pre-lift on `impl EphemeralSpec` — every callsite
9210 // went through `.resolved_classification().horizon.kind == kind`
9211 // or through the lowered `ProcessSpec`'s
9212 // `spec.classification.has_horizon_kind`. Post-lift the FIFTH
9213 // classification-axis peer on the ephemeral sugar surface routes
9214 // through the SAME [`Self::resolved_classification`] resolver +
9215 // the sibling closed-set primitive
9216 // [`crate::classification::Classification::has_horizon_kind`], so
9217 // a regression that dropped the resolver hop, inverted the
9218 // `Some`/`None` fill-through, or wired the closure to a fixed
9219 // unrelated slot fails HERE. OPENS a fresh (Option-parent ×
9220 // NESTED-STRUCT-scalar-child × operator-resolvable-baseline)
9221 // corner on the ephemeral surface — distinct from the four prior
9222 // scalar-carrier peers on the (Option-parent × NON-DEFAULT-scalar-
9223 // child) and (Option-parent × DEFAULTED-scalar-child) corners, all
9224 // of which reach a discriminator DIRECTLY off a scalar
9225 // [`Classification`] slot. Both the parent Option's fill-through
9226 // baseline (`default_ephemeral_class`, which fills
9227 // `horizon: Horizon::default()`) AND the child's own `#[default]`
9228 // land on the SAME variant ([`HorizonKind::Bounded`]) — a two-
9229 // defaults composition property the three pins below all
9230 // exercise.
9231
9232 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9233 /// [`EphemeralSpec::classification`] slot names a concrete
9234 /// [`Classification`] returns `true` from
9235 /// [`Self::has_horizon_kind`] on the authored [`HorizonKind`] slot
9236 /// and `false` for every other variant. Sweep the
9237 /// [`HorizonKind::ALL`] × ALL cross so a regression that hard-
9238 /// coded the arm to a single kind or wired the closure to a
9239 /// fixed unrelated slot (e.g. reading `self.classification` as if
9240 /// it were a scalar rather than routing through
9241 /// `resolved_classification().horizon.kind`) fails HERE at the
9242 /// substrate primitive. Byte-for-byte peer of the point-surface
9243 /// [`Classification::has_horizon_kind`] populated-slot sweep on
9244 /// the SAME closed-set primitive.
9245 #[test]
9246 fn has_horizon_kind_returns_true_iff_authored_classification_matches_per_kind() {
9247 for populated in HorizonKind::ALL {
9248 let classification = Classification::gate_compute_with_axis(populated);
9249 let mut spec = empty_ephemeral();
9250 spec.classification = Some(classification);
9251 for query in HorizonKind::ALL {
9252 let expected = query == populated;
9253 assert_eq!(
9254 spec.has_horizon_kind(query),
9255 expected,
9256 "ephemeral classification.horizon.kind={populated:?}: query {query:?} drifted",
9257 );
9258 }
9259 }
9260 }
9261
9262 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9263 /// [`EphemeralSpec::classification`] slot is `None` returns
9264 /// `true` from [`Self::has_horizon_kind`] on
9265 /// [`HorizonKind::Bounded`] (the `default_ephemeral_class`
9266 /// baseline's `horizon.kind` axis AND the [`HorizonKind`] child's
9267 /// own `#[default]` variant) and `false` on every other variant.
9268 /// Pins the fresh (Option-parent × NESTED-STRUCT-scalar-child ×
9269 /// operator-resolvable-baseline) corner's default-arm short-
9270 /// circuit on the FIFTH classification-axis peer. Two-defaults
9271 /// composition property through a NESTED-STRUCT hop: both the
9272 /// parent Option's fill-through baseline
9273 /// (`default_ephemeral_class` fills `horizon: Horizon::default()`)
9274 /// AND the child's own `#[default]` (`HorizonKind::Bounded` via
9275 /// `#[default]` on the closed set) land on the SAME variant, so
9276 /// the ephemeral sugar surface's `horizon-Bounded` require-tag
9277 /// reads `true` on every operator-authored spec that omits both
9278 /// the `:classification` slot AND the `:horizon` sub-slot,
9279 /// pinning the workspace's bounded-by-default lifetime posture.
9280 #[test]
9281 fn has_horizon_kind_probes_bounded_only_on_absent_classification() {
9282 let spec = empty_ephemeral();
9283 assert!(spec.classification.is_none());
9284 for kind in HorizonKind::ALL {
9285 let expected = kind == HorizonKind::Bounded;
9286 assert_eq!(
9287 spec.has_horizon_kind(kind),
9288 expected,
9289 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9290 );
9291 }
9292 }
9293
9294 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9295 /// identically through [`Self::has_horizon_kind`] AND through
9296 /// `<eph.clone().into::<ProcessSpec>>()`
9297 /// `.classification.has_horizon_kind(kind)` on the mechanically-
9298 /// lowered `ProcessSpec`. Sweeps (`None` classification, `Some(_)`
9299 /// classification on every [`HorizonKind::ALL`] variant) × ALL
9300 /// queries so a future regression on either side of the resolver
9301 /// (a shift in the ephemeral resolver's default, a shift in the
9302 /// `From<EphemeralSpec>` lowering's fill-through) fails HERE at
9303 /// the parity boundary. Byte-for-byte peer of the sibling
9304 /// [`Self::has_point_type`] + [`Self::has_substrate`] +
9305 /// [`Self::has_calm`] + [`Self::has_data_classification`] two-
9306 /// surface parity pins on the SAME `Cow`-resolver carrier — the
9307 /// FIFTH classification-axis two-surface parity contract on the
9308 /// ephemeral surface, and the FIRST on the (Option-parent ×
9309 /// NESTED-STRUCT-scalar-child) corner.
9310 #[test]
9311 fn has_horizon_kind_matches_point_peer_through_lowered_classification() {
9312 // Absent classification: both surfaces resolve through the SAME
9313 // default and agree on every variant.
9314 let eph = empty_ephemeral();
9315 let lowered: ProcessSpec = eph.clone().into();
9316 for query in HorizonKind::ALL {
9317 assert_eq!(
9318 eph.has_horizon_kind(query),
9319 lowered.classification.has_horizon_kind(query),
9320 "None-classification parity drift on query {query:?}",
9321 );
9322 }
9323 // Authored classification: both surfaces read the same authored
9324 // value verbatim.
9325 for populated in HorizonKind::ALL {
9326 let classification = Classification::gate_compute_with_axis(populated);
9327 let mut eph = empty_ephemeral();
9328 eph.classification = Some(classification);
9329 let lowered: ProcessSpec = eph.clone().into();
9330 for query in HorizonKind::ALL {
9331 assert_eq!(
9332 eph.has_horizon_kind(query),
9333 lowered.classification.has_horizon_kind(query),
9334 "authored classification.horizon.kind={populated:?}: parity drift on query {query:?}",
9335 );
9336 }
9337 }
9338 }
9339
9340 // ── EphemeralSpec::has_optimization_direction pins ───────────────
9341 //
9342 // Fail-before-pass-after granularity:
9343 // [`Self::has_optimization_direction`] did not exist pre-lift on
9344 // `impl EphemeralSpec` — every callsite went through
9345 // `.resolved_classification().horizon.direction.unwrap_or_default() == kind`
9346 // or through the lowered `ProcessSpec`'s
9347 // `spec.classification.has_optimization_direction`. Post-lift the
9348 // SIXTH classification-axis peer on the ephemeral sugar surface
9349 // routes through the SAME [`Self::resolved_classification`]
9350 // resolver + the sibling closed-set primitive
9351 // [`crate::classification::Classification::has_optimization_direction`],
9352 // so a regression that dropped the resolver hop, inverted the
9353 // `Some`/`None` fill-through, wired the closure to a fixed
9354 // unrelated slot, or flipped [`OptimizationDirection`]'s
9355 // `#[default]` off `Minimize` fails HERE. SECOND occupant on the
9356 // (Option-parent × NESTED-STRUCT-scalar-child × operator-
9357 // resolvable-baseline) corner alongside
9358 // [`Self::has_horizon_kind`] — pinning the corner as a proven-
9359 // repeatable primitive shape on the ephemeral surface with a
9360 // second nested-struct-child probe, and DEMONSTRATING that the
9361 // corner admits both direct-scalar and Option-scalar traversals
9362 // through the SAME nested [`Horizon`] intermediary via the closed
9363 // set's `Default` on the inner `Option<OptimizationDirection>`
9364 // slot.
9365
9366 /// AUTHORED-slot VARIANT-MATCH pin — an [`EphemeralSpec`] whose
9367 /// [`EphemeralSpec::classification`] slot names a concrete
9368 /// [`Classification`] whose [`crate::classification::Horizon::direction`]
9369 /// slot carries `Some(<direction>)` returns `true` from
9370 /// [`Self::has_optimization_direction`] on the authored
9371 /// [`OptimizationDirection`] variant and `false` for every other
9372 /// variant. Sweep the [`OptimizationDirection::ALL`] × ALL cross
9373 /// so a regression that hard-coded the arm to a single kind, or
9374 /// dropped the `Option::unwrap_or_default` collapse, or wired the
9375 /// closure to a fixed unrelated slot (e.g. reading `self.horizon.kind`)
9376 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9377 /// point-surface
9378 /// [`Classification::has_optimization_direction`] populated-slot
9379 /// sweep on the SAME closed-set primitive.
9380 #[test]
9381 fn has_optimization_direction_returns_true_iff_authored_direction_matches_per_kind() {
9382 for populated in OptimizationDirection::ALL {
9383 let classification = Classification::gate_compute_with_axis(populated);
9384 let mut spec = empty_ephemeral();
9385 spec.classification = Some(classification);
9386 for query in OptimizationDirection::ALL {
9387 let expected = query == populated;
9388 assert_eq!(
9389 spec.has_optimization_direction(query),
9390 expected,
9391 "ephemeral classification.horizon.direction=Some({populated:?}): query {query:?} drifted",
9392 );
9393 }
9394 }
9395 }
9396
9397 /// ABSENT-slot DEFAULT-ARM pin — an [`EphemeralSpec`] whose
9398 /// [`EphemeralSpec::classification`] slot is `None` returns
9399 /// `true` from [`Self::has_optimization_direction`] on
9400 /// [`OptimizationDirection::Minimize`] (the `default_ephemeral_class`
9401 /// baseline fills `horizon: Horizon::default()`, which in turn
9402 /// leaves `direction: None`, and the substrate's
9403 /// `Option::unwrap_or_default` collapse then reads
9404 /// [`OptimizationDirection::Minimize`] via the closed set's
9405 /// `#[default]`) and `false` on every other variant. Pins the
9406 /// (Option-parent × NESTED-STRUCT-scalar-child × operator-
9407 /// resolvable-baseline) corner's default-arm short-circuit on the
9408 /// SIXTH classification-axis peer through TWO Option-hops: parent
9409 /// `EphemeralSpec::classification` and inner `Horizon::direction`
9410 /// both `None`, both collapsing to the closed set's `#[default]`
9411 /// [`OptimizationDirection::Minimize`]. A regression that promoted
9412 /// [`OptimizationDirection::Maximize`] to `#[default]` (silently
9413 /// inverting every unadorned Process's rate-window evaluator
9414 /// polarity), dropped `Option::unwrap_or_default`, or wired the arm
9415 /// to a fixed variant answer fails HERE.
9416 #[test]
9417 fn has_optimization_direction_probes_minimize_only_on_absent_classification() {
9418 let spec = empty_ephemeral();
9419 assert!(spec.classification.is_none());
9420 for kind in OptimizationDirection::ALL {
9421 let expected = kind == OptimizationDirection::Minimize;
9422 assert_eq!(
9423 spec.has_optimization_direction(kind),
9424 expected,
9425 "absent classification (defaults to gate_compute): query {kind:?} must be {expected}",
9426 );
9427 }
9428 }
9429
9430 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9431 /// identically through [`Self::has_optimization_direction`] AND
9432 /// through
9433 /// `<eph.clone().into::<ProcessSpec>>().classification.has_optimization_direction(kind)`
9434 /// on the mechanically-lowered `ProcessSpec`. Sweeps three arms —
9435 /// (`None` classification), (`Some(_)` classification with
9436 /// `direction: None`), and (`Some(_)` classification on every
9437 /// [`OptimizationDirection::ALL`] variant) — × ALL queries so a
9438 /// future regression on either side of the resolver (an ephemeral-
9439 /// side fill-through drift, a lowering-side `From<EphemeralSpec>`
9440 /// `unwrap_or_else(default_ephemeral_class)` drift, an inner
9441 /// `Option::unwrap_or_default` collapse drift on either side)
9442 /// fails HERE at the parity boundary. Byte-for-byte peer of the
9443 /// sibling [`Self::has_point_type`] + [`Self::has_substrate`] +
9444 /// [`Self::has_calm`] + [`Self::has_data_classification`] +
9445 /// [`Self::has_horizon_kind`] two-surface parity pins on the SAME
9446 /// `Cow`-resolver carrier — the SIXTH classification-axis two-
9447 /// surface parity contract on the ephemeral surface, and the
9448 /// SECOND on the (Option-parent × NESTED-STRUCT-scalar-child)
9449 /// corner.
9450 #[test]
9451 fn has_optimization_direction_matches_point_peer_through_lowered_classification() {
9452 // Absent classification: both surfaces resolve through the SAME
9453 // default and agree on every variant.
9454 let eph = empty_ephemeral();
9455 let lowered: ProcessSpec = eph.clone().into();
9456 for query in OptimizationDirection::ALL {
9457 assert_eq!(
9458 eph.has_optimization_direction(query),
9459 lowered.classification.has_optimization_direction(query),
9460 "None-classification parity drift on query {query:?}",
9461 );
9462 }
9463 // Authored classification with `direction: None` — the inner
9464 // Option collapses through `unwrap_or_default` on both sides,
9465 // reading `Minimize`.
9466 let mut classification = Classification::gate_compute();
9467 classification.horizon = Horizon::default();
9468 let mut eph = empty_ephemeral();
9469 eph.classification = Some(classification);
9470 let lowered: ProcessSpec = eph.clone().into();
9471 for query in OptimizationDirection::ALL {
9472 assert_eq!(
9473 eph.has_optimization_direction(query),
9474 lowered.classification.has_optimization_direction(query),
9475 "authored classification with horizon.direction=None: parity drift on query {query:?}",
9476 );
9477 }
9478 // Authored classification with `direction: Some(_)` — both
9479 // surfaces read the same authored value verbatim.
9480 for populated in OptimizationDirection::ALL {
9481 let classification = Classification::gate_compute_with_axis(populated);
9482 let mut eph = empty_ephemeral();
9483 eph.classification = Some(classification);
9484 let lowered: ProcessSpec = eph.clone().into();
9485 for query in OptimizationDirection::ALL {
9486 assert_eq!(
9487 eph.has_optimization_direction(query),
9488 lowered.classification.has_optimization_direction(query),
9489 "authored classification.horizon.direction=Some({populated:?}): parity drift on query {query:?}",
9490 );
9491 }
9492 }
9493 }
9494
9495 // ── EphemeralSpec::has_input_arity pins ──────────────────────────
9496 //
9497 // Fail-before-pass-after granularity: [`Self::has_input_arity`] did
9498 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
9499 // through `.resolved_classification().point_type.input_arity() ==
9500 // kind` or through the lowered `ProcessSpec`'s
9501 // `spec.classification.has_input_arity`. Post-lift the SEVENTH
9502 // classification-axis peer on the ephemeral sugar surface routes
9503 // through the SAME [`Self::resolved_classification`] resolver + the
9504 // sibling closed-set primitive
9505 // [`crate::classification::Classification::has_input_arity`], so a
9506 // regression that dropped the resolver hop, dropped the
9507 // `.input_arity()` projection call, inverted the projection (`One
9508 // ↔ Many`), or crossed the wires with the sibling
9509 // [`ConvergencePointType::output_arity`] projection fails HERE.
9510 // OPENS the (Option-parent × NESTED-STRUCT-scalar-child ×
9511 // derived-typed-projection) corner on the ephemeral surface —
9512 // distinct from the two prior nested-scalar peers on the corner
9513 // (`has_horizon_kind` reads `horizon.kind` directly;
9514 // `has_optimization_direction` reads `horizon.direction` through an
9515 // Option collapse), both of which reach a discriminator DIRECTLY off
9516 // a scalar. This peer instead threads through a many-to-one closed-
9517 // set typed projection so the child's closed set is REACHED THROUGH
9518 // a projection layer, pinning the corner as admitting three
9519 // ephemeral-surface traversal shapes (direct-scalar, Option-scalar-
9520 // with-default, derived-typed-projection) through the SAME resolver
9521 // walk.
9522
9523 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9524 /// [`EphemeralSpec::classification`] slot names a concrete
9525 /// [`Classification`] with an authored [`ConvergencePointType`]
9526 /// returns `true` from [`Self::has_input_arity`] on the [`Arity`]
9527 /// value the projection [`ConvergencePointType::input_arity`] maps
9528 /// the authored point-type to and `false` for every other variant.
9529 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9530 /// a regression that (a) dropped the projection call, (b) inverted
9531 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9532 /// (d) crossed wires with [`ConvergencePointType::output_arity`]
9533 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9534 /// point-surface [`Classification::has_input_arity`] populated-slot
9535 /// sweep on the SAME closed-set primitive routed through the SAME
9536 /// projection.
9537 #[test]
9538 fn has_input_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9539 for populated in ConvergencePointType::ALL {
9540 let mut classification = Classification::gate_compute();
9541 classification.point_type = populated;
9542 let mut spec = empty_ephemeral();
9543 spec.classification = Some(classification);
9544 let projected = populated.input_arity();
9545 for query in Arity::ALL {
9546 let expected = query == projected;
9547 assert_eq!(
9548 spec.has_input_arity(query),
9549 expected,
9550 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9551 );
9552 }
9553 }
9554 }
9555
9556 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9557 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9558 /// from [`Self::has_input_arity`] on [`Arity::Many`] (the
9559 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9560 /// and [`ConvergencePointType::input_arity`] projects
9561 /// `Gate → Arity::Many`) and `false` on [`Arity::One`]. Pins the
9562 /// (Option-parent × NESTED-STRUCT-scalar-child × derived-typed-
9563 /// projection) corner's baseline projection on the SEVENTH
9564 /// classification-axis peer through a chain of TWO fill-throughs
9565 /// composed with ONE projection: the parent Option's
9566 /// `unwrap_or_else(default_ephemeral_class)` picks the substrate
9567 /// baseline, and the projection then collapses the baseline's
9568 /// point-type through the closed-set-driven many-to-one bucket
9569 /// walk. [`Arity`] carries no `#[default]`, so there is NO default-
9570 /// arm short-circuit shortcut here — the answer flows entirely
9571 /// through the projection's bucket-membership decision. A
9572 /// regression that promoted the baseline's `point_type` off `Gate`
9573 /// (silently flipping every unadorned Process's convergent-by-
9574 /// default input-side posture to endomorphic or diffusive), dropped
9575 /// the projection call, inverted the projection, or crossed wires
9576 /// with [`ConvergencePointType::output_arity`] (which would flip
9577 /// the baseline answer from `Many` to `One` for `Gate`) fails HERE.
9578 #[test]
9579 fn has_input_arity_probes_many_only_on_absent_classification() {
9580 let spec = empty_ephemeral();
9581 assert!(spec.classification.is_none());
9582 for kind in Arity::ALL {
9583 let expected = kind == Arity::Many;
9584 assert_eq!(
9585 spec.has_input_arity(kind),
9586 expected,
9587 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many): query {kind:?} must be {expected}",
9588 );
9589 }
9590 }
9591
9592 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9593 /// identically through [`Self::has_input_arity`] AND through
9594 /// `<eph.clone().into::<ProcessSpec>>().classification.has_input_arity(kind)`
9595 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9596 /// classification, `Some(_)` classification on every
9597 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9598 /// so a future regression on either side of the resolver (a shift
9599 /// in the ephemeral resolver's default, a shift in the
9600 /// `From<EphemeralSpec>` lowering's fill-through, a projection
9601 /// drift on either side) fails HERE at the parity boundary. Byte-
9602 /// for-byte peer of the sibling [`Self::has_point_type`] +
9603 /// [`Self::has_substrate`] + [`Self::has_calm`] +
9604 /// [`Self::has_data_classification`] + [`Self::has_horizon_kind`] +
9605 /// [`Self::has_optimization_direction`] two-surface parity pins on
9606 /// the SAME `Cow`-resolver carrier — the SEVENTH classification-
9607 /// axis two-surface parity contract on the ephemeral surface, and
9608 /// the FIRST on the (Option-parent × NESTED-STRUCT-scalar-child ×
9609 /// derived-typed-projection) corner.
9610 #[test]
9611 fn has_input_arity_matches_point_peer_through_lowered_classification() {
9612 // Absent classification: both surfaces resolve through the SAME
9613 // default and agree on every variant.
9614 let eph = empty_ephemeral();
9615 let lowered: ProcessSpec = eph.clone().into();
9616 for query in Arity::ALL {
9617 assert_eq!(
9618 eph.has_input_arity(query),
9619 lowered.classification.has_input_arity(query),
9620 "None-classification parity drift on query {query:?}",
9621 );
9622 }
9623 // Authored classification: both surfaces read the same authored
9624 // point_type and route through the same projection.
9625 for populated in ConvergencePointType::ALL {
9626 let mut classification = Classification::gate_compute();
9627 classification.point_type = populated;
9628 let mut eph = empty_ephemeral();
9629 eph.classification = Some(classification);
9630 let lowered: ProcessSpec = eph.clone().into();
9631 for query in Arity::ALL {
9632 assert_eq!(
9633 eph.has_input_arity(query),
9634 lowered.classification.has_input_arity(query),
9635 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9636 );
9637 }
9638 }
9639 }
9640
9641 // ── EphemeralSpec::has_output_arity pins ─────────────────────────
9642 //
9643 // Fail-before-pass-after granularity: [`Self::has_output_arity`] did
9644 // not exist pre-lift on `impl EphemeralSpec` — every callsite went
9645 // through `.resolved_classification().point_type.output_arity() ==
9646 // kind` or through the lowered `ProcessSpec`'s
9647 // `spec.classification.has_output_arity`. Post-lift the EIGHTH
9648 // classification-axis peer on the ephemeral sugar surface routes
9649 // through the SAME [`Self::resolved_classification`] resolver + the
9650 // sibling closed-set primitive
9651 // [`crate::classification::Classification::has_output_arity`], so a
9652 // regression that dropped the resolver hop, dropped the
9653 // `.output_arity()` projection call, inverted the projection (`One
9654 // ↔ Many`), or crossed the wires with the sibling
9655 // [`ConvergencePointType::input_arity`] projection fails HERE.
9656 // CLOSES the (Option-parent × NESTED-STRUCT-scalar-child ×
9657 // derived-typed-projection) corner on the ephemeral surface as the
9658 // SECOND occupant — co-tenant with [`Self::has_input_arity`] on the
9659 // SAME `point_type` scalar carrier through the SAME [`Arity`] closed
9660 // set but through the sibling many-to-one projection, closing the
9661 // DAG-composition arity pair on the ephemeral side.
9662
9663 /// AUTHORED-slot PROJECTED-VARIANT pin — an [`EphemeralSpec`] whose
9664 /// [`EphemeralSpec::classification`] slot names a concrete
9665 /// [`Classification`] with an authored [`ConvergencePointType`]
9666 /// returns `true` from [`Self::has_output_arity`] on the [`Arity`]
9667 /// value the projection [`ConvergencePointType::output_arity`] maps
9668 /// the authored point-type to and `false` for every other variant.
9669 /// Sweep the [`ConvergencePointType::ALL`] × [`Arity::ALL`] cross so
9670 /// a regression that (a) dropped the projection call, (b) inverted
9671 /// the projection, (c) probed [`ConvergencePointType`] directly, or
9672 /// (d) crossed wires with [`ConvergencePointType::input_arity`]
9673 /// fails HERE at the substrate primitive. Byte-for-byte peer of the
9674 /// point-surface [`Classification::has_output_arity`] populated-slot
9675 /// sweep on the SAME closed-set primitive routed through the SAME
9676 /// projection.
9677 #[test]
9678 fn has_output_arity_returns_true_iff_authored_point_type_projects_per_kind() {
9679 for populated in ConvergencePointType::ALL {
9680 let mut classification = Classification::gate_compute();
9681 classification.point_type = populated;
9682 let mut spec = empty_ephemeral();
9683 spec.classification = Some(classification);
9684 let projected = populated.output_arity();
9685 for query in Arity::ALL {
9686 let expected = query == projected;
9687 assert_eq!(
9688 spec.has_output_arity(query),
9689 expected,
9690 "ephemeral classification.point_type={populated:?} (projects to {projected:?}): query {query:?} drifted",
9691 );
9692 }
9693 }
9694 }
9695
9696 /// ABSENT-slot PROJECTED-BASELINE pin — an [`EphemeralSpec`] whose
9697 /// [`EphemeralSpec::classification`] slot is `None` returns `true`
9698 /// from [`Self::has_output_arity`] on [`Arity::One`] (the
9699 /// [`default_ephemeral_class`] baseline fills `point_type: Gate`,
9700 /// and [`ConvergencePointType::output_arity`] projects
9701 /// `Gate → Arity::One`) and `false` on [`Arity::Many`]. MIRROR of
9702 /// the [`Self::has_input_arity`] baseline (`Gate → input_arity =
9703 /// Many`) — the DAG-composition arity pair projects the same `Gate`
9704 /// baseline through the two projections to opposite [`Arity`] arms,
9705 /// so this pin locks the output-side half of that pair against a
9706 /// regression that (a) promoted the baseline's `point_type` off
9707 /// `Gate` (silently flipping every unadorned Process's convergent-
9708 /// by-default output-side posture to diffusive), (b) dropped the
9709 /// projection call, (c) inverted the projection, or (d) crossed
9710 /// wires with [`ConvergencePointType::input_arity`] (which would
9711 /// flip the baseline answer from `One` to `Many` for `Gate`).
9712 #[test]
9713 fn has_output_arity_probes_one_only_on_absent_classification() {
9714 let spec = empty_ephemeral();
9715 assert!(spec.classification.is_none());
9716 for kind in Arity::ALL {
9717 let expected = kind == Arity::One;
9718 assert_eq!(
9719 spec.has_output_arity(kind),
9720 expected,
9721 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One): query {kind:?} must be {expected}",
9722 );
9723 }
9724 }
9725
9726 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9727 /// identically through [`Self::has_output_arity`] AND through
9728 /// `<eph.clone().into::<ProcessSpec>>().classification.has_output_arity(kind)`
9729 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9730 /// classification, `Some(_)` classification on every
9731 /// [`ConvergencePointType::ALL`] variant) × [`Arity::ALL`] queries
9732 /// so a future regression on either side of the resolver fails HERE
9733 /// at the parity boundary. Byte-for-byte peer of the seven sibling
9734 /// two-surface parity pins on the SAME `Cow`-resolver carrier — the
9735 /// EIGHTH classification-axis two-surface parity contract on the
9736 /// ephemeral surface, closing the SECOND occupant of the (Option-
9737 /// parent × NESTED-STRUCT-scalar-child × derived-typed-projection)
9738 /// corner.
9739 #[test]
9740 fn has_output_arity_matches_point_peer_through_lowered_classification() {
9741 // Absent classification: both surfaces resolve through the SAME
9742 // default and agree on every variant.
9743 let eph = empty_ephemeral();
9744 let lowered: ProcessSpec = eph.clone().into();
9745 for query in Arity::ALL {
9746 assert_eq!(
9747 eph.has_output_arity(query),
9748 lowered.classification.has_output_arity(query),
9749 "None-classification parity drift on query {query:?}",
9750 );
9751 }
9752 // Authored classification: both surfaces read the same authored
9753 // point_type and route through the same projection.
9754 for populated in ConvergencePointType::ALL {
9755 let mut classification = Classification::gate_compute();
9756 classification.point_type = populated;
9757 let mut eph = empty_ephemeral();
9758 eph.classification = Some(classification);
9759 let lowered: ProcessSpec = eph.clone().into();
9760 for query in Arity::ALL {
9761 assert_eq!(
9762 eph.has_output_arity(query),
9763 lowered.classification.has_output_arity(query),
9764 "authored classification.point_type={populated:?}: parity drift on query {query:?}",
9765 );
9766 }
9767 }
9768 }
9769
9770 /// DAG-COMPOSITION ARITY-PAIR pin — the SEVENTH
9771 /// ([`Self::has_input_arity`]) and EIGHTH
9772 /// ([`Self::has_output_arity`]) classification-axis peers on the
9773 /// ephemeral surface walk the SAME `point_type` scalar carrier
9774 /// (routed through the SAME [`Self::resolved_classification`]
9775 /// resolver) through the SAME [`Arity`] closed set but through
9776 /// DIFFERENT typed projections
9777 /// ([`ConvergencePointType::input_arity`] vs.
9778 /// [`ConvergencePointType::output_arity`]). An [`EphemeralSpec`]
9779 /// with `classification.point_type = Fork` (the diffusive `(One,
9780 /// Many)` cell) MUST simultaneously answer `has_input_arity(One)`
9781 /// true AND `has_output_arity(Many)` true AND
9782 /// `has_input_arity(Many)` false AND `has_output_arity(One)` false.
9783 /// An [`EphemeralSpec`] with `point_type = Transform` (endomorphic
9784 /// `(One, One)`) MUST answer BOTH `has_input_arity(One)` and
9785 /// `has_output_arity(One)` true — the two projections AGREE in the
9786 /// endomorphic bucket. The absent-classification baseline (Gate,
9787 /// convergent `(Many, One)`) MUST answer
9788 /// `has_input_arity(Many)` true AND `has_output_arity(One)` true —
9789 /// the mirror of the Fork case. A regression that (a) collapsed
9790 /// `has_output_arity` onto `has_input_arity`, (b) swapped the
9791 /// projection direction, or (c) drifted the topology-bucket
9792 /// contract fails HERE at ONE narrow ephemeral-surface site,
9793 /// symmetric with the point-surface DAG-composition arity-pair pin.
9794 #[test]
9795 fn has_input_arity_and_has_output_arity_pin_dag_composition_pair() {
9796 // Diffusive cell: Fork carries (input, output) = (One, Many)
9797 let mut classification = Classification::gate_compute();
9798 classification.point_type = ConvergencePointType::Fork;
9799 let mut fork = empty_ephemeral();
9800 fork.classification = Some(classification);
9801 assert!(fork.has_input_arity(Arity::One));
9802 assert!(fork.has_output_arity(Arity::Many));
9803 assert!(!fork.has_input_arity(Arity::Many));
9804 assert!(!fork.has_output_arity(Arity::One));
9805
9806 // Endomorphic cell: Transform carries (input, output) = (One, One)
9807 let mut classification = Classification::gate_compute();
9808 classification.point_type = ConvergencePointType::Transform;
9809 let mut transform = empty_ephemeral();
9810 transform.classification = Some(classification);
9811 assert!(transform.has_input_arity(Arity::One));
9812 assert!(transform.has_output_arity(Arity::One));
9813 assert!(!transform.has_input_arity(Arity::Many));
9814 assert!(!transform.has_output_arity(Arity::Many));
9815
9816 // Convergent cell: absent classification defaults to Gate,
9817 // which carries (input, output) = (Many, One).
9818 let gate = empty_ephemeral();
9819 assert!(gate.classification.is_none());
9820 assert!(gate.has_input_arity(Arity::Many));
9821 assert!(gate.has_output_arity(Arity::One));
9822 assert!(!gate.has_input_arity(Arity::One));
9823 assert!(!gate.has_output_arity(Arity::Many));
9824 }
9825
9826 // ── EphemeralSpec::horizon_terminates pins ───────────────────────
9827 //
9828 // Fail-before-pass-after granularity: `horizon_terminates` did not
9829 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
9830 // the "does this ephemeral spec's horizon terminate?" question
9831 // went through `.resolved_classification().horizon.kind.terminates()`
9832 // or through the lowered `ProcessSpec`'s
9833 // `spec.classification.horizon.kind.terminates()`. Post-lift the
9834 // NINTH classification-axis peer on the ephemeral surface routes
9835 // through the SAME [`Self::resolved_classification`] resolver +
9836 // the sibling substrate primitive
9837 // [`crate::classification::Classification::horizon_terminates`],
9838 // so the two-surface parity contract holds by construction — a
9839 // regression on either side of the resolver fails at these pins
9840 // before landing at the operator-facing `terminating-horizon`
9841 // fixed tag in `tatara-check`.
9842
9843 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9844 /// [`Classification`] carries a specific [`HorizonKind`] variant
9845 /// answers [`Self::horizon_terminates`] matching the closed
9846 /// set's own [`HorizonKind::terminates`] truth table. Sweep
9847 /// [`HorizonKind::ALL`] so a regression that (a) hard-coded the
9848 /// body to a fixed answer, (b) inverted the projection, or (c)
9849 /// crossed the wires with the antisymmetric partner
9850 /// [`HorizonKind::requires_metric_axes`] fails HERE at the
9851 /// substrate primitive before drifting through the
9852 /// `terminating-horizon` fixed tag or the peer point surface.
9853 #[test]
9854 fn horizon_terminates_returns_horizon_kind_projection_per_kind() {
9855 for populated in HorizonKind::ALL {
9856 let classification = Classification::gate_compute_with_axis(populated);
9857 let mut spec = empty_ephemeral();
9858 spec.classification = Some(classification);
9859 assert_eq!(
9860 spec.horizon_terminates(),
9861 populated.terminates(),
9862 "authored horizon.kind={populated:?}: horizon_terminates() drift",
9863 );
9864 }
9865 }
9866
9867 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9868 /// with `classification: None` routes through the
9869 /// [`Self::resolved_classification`] resolver's substrate default
9870 /// [`Classification::gate_compute`], which uses
9871 /// [`crate::classification::Horizon::default`] whose `kind`
9872 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9873 /// [`HorizonKind::Bounded::terminates`] projects `true`, so
9874 /// [`Self::horizon_terminates`] returns `true`. Pins the default-
9875 /// arm short-circuit through THREE layers of `Default`
9876 /// ([`Classification::gate_compute`] → [`Horizon::default`] →
9877 /// [`HorizonKind::default`]) reaching this derived-nullary
9878 /// predicate — a regression that dropped the resolver hop
9879 /// (silently answering `false` on an absent classification, as
9880 /// if the operator's absence meant "no horizon at all") fails
9881 /// HERE at ONE narrow ephemeral-surface site.
9882 #[test]
9883 fn horizon_terminates_probes_true_on_absent_classification() {
9884 let spec = empty_ephemeral();
9885 assert!(spec.classification.is_none());
9886 assert!(
9887 spec.horizon_terminates(),
9888 "absent classification (defaults to gate_compute, horizon.kind=Bounded → terminates=true)",
9889 );
9890 }
9891
9892 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9893 /// identically through [`Self::horizon_terminates`] AND through
9894 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_terminates()`
9895 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
9896 /// classification, `Some(_)` classification on every
9897 /// [`HorizonKind::ALL`] variant) so a future regression on
9898 /// either side of the resolver fails HERE at the parity
9899 /// boundary. Byte-for-byte peer of the eight sibling two-surface
9900 /// parity pins on the SAME `Cow`-resolver carrier — the NINTH
9901 /// classification-axis two-surface parity contract on the
9902 /// ephemeral surface, and the FIRST via a derived-nullary-
9903 /// boolean predicate rather than a variant-equality probe.
9904 #[test]
9905 fn horizon_terminates_matches_point_peer_through_lowered_classification() {
9906 // Absent classification: both surfaces resolve through the SAME
9907 // default and agree.
9908 let eph = empty_ephemeral();
9909 let lowered: ProcessSpec = eph.clone().into();
9910 assert_eq!(
9911 eph.horizon_terminates(),
9912 lowered.classification.horizon_terminates(),
9913 "None-classification parity drift",
9914 );
9915 // Authored classification: both surfaces read the same authored
9916 // horizon.kind and route through the same projection.
9917 for populated in HorizonKind::ALL {
9918 let classification = Classification::gate_compute_with_axis(populated);
9919 let mut eph = empty_ephemeral();
9920 eph.classification = Some(classification);
9921 let lowered: ProcessSpec = eph.clone().into();
9922 assert_eq!(
9923 eph.horizon_terminates(),
9924 lowered.classification.horizon_terminates(),
9925 "authored horizon.kind={populated:?}: parity drift",
9926 );
9927 }
9928 }
9929
9930 // ── EphemeralSpec::horizon_requires_metric_axes pins ─────────────
9931 //
9932 // Fail-before-pass-after granularity: `horizon_requires_metric_axes`
9933 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
9934 // walking the "does this ephemeral spec's horizon require metric
9935 // axes?" question went through
9936 // `.resolved_classification().horizon.kind.requires_metric_axes()`
9937 // or through the lowered `ProcessSpec`'s
9938 // `spec.classification.horizon.kind.requires_metric_axes()`. Post-
9939 // lift the antisymmetric peer of `horizon_terminates` routes
9940 // through the SAME [`Self::resolved_classification`] resolver +
9941 // the sibling substrate primitive
9942 // [`crate::classification::Classification::horizon_requires_metric_axes`],
9943 // so the two-surface parity contract holds by construction — a
9944 // regression on either side of the resolver fails at these pins
9945 // before landing at the operator-facing `metric-axes-required`
9946 // fixed tag in `tatara-check`.
9947
9948 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
9949 /// [`Classification`] carries a specific [`HorizonKind`] variant
9950 /// answers [`Self::horizon_requires_metric_axes`] matching the
9951 /// closed set's own [`HorizonKind::requires_metric_axes`] truth
9952 /// table. Sweep [`HorizonKind::ALL`] so a regression that (a)
9953 /// hard-coded the body to a fixed answer, (b) inverted the
9954 /// projection, or (c) crossed the wires with the antisymmetric
9955 /// partner [`HorizonKind::terminates`] fails HERE at the
9956 /// substrate primitive before drifting through the
9957 /// `metric-axes-required` fixed tag or the peer point surface.
9958 #[test]
9959 fn horizon_requires_metric_axes_returns_horizon_kind_projection_per_kind() {
9960 for populated in HorizonKind::ALL {
9961 let classification = Classification::gate_compute_with_axis(populated);
9962 let mut spec = empty_ephemeral();
9963 spec.classification = Some(classification);
9964 assert_eq!(
9965 spec.horizon_requires_metric_axes(),
9966 populated.requires_metric_axes(),
9967 "authored horizon.kind={populated:?}: horizon_requires_metric_axes() drift",
9968 );
9969 }
9970 }
9971
9972 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
9973 /// with `classification: None` routes through the
9974 /// [`Self::resolved_classification`] resolver's substrate default
9975 /// [`Classification::gate_compute`], which uses
9976 /// [`crate::classification::Horizon::default`] whose `kind`
9977 /// defaults to [`HorizonKind::Bounded`] via `#[default]`, and
9978 /// [`HorizonKind::Bounded::requires_metric_axes`] projects
9979 /// `false`, so [`Self::horizon_requires_metric_axes`] returns
9980 /// `false`. Pins the default-arm short-circuit through THREE
9981 /// layers of `Default` ([`Classification::gate_compute`] →
9982 /// [`Horizon::default`] → [`HorizonKind::default`]) reaching this
9983 /// derived-nullary predicate — mirror image of
9984 /// `horizon_terminates_probes_true_on_absent_classification`.
9985 #[test]
9986 fn horizon_requires_metric_axes_probes_false_on_absent_classification() {
9987 let spec = empty_ephemeral();
9988 assert!(spec.classification.is_none());
9989 assert!(
9990 !spec.horizon_requires_metric_axes(),
9991 "absent classification (defaults to gate_compute, horizon.kind=Bounded → requires_metric_axes=false)",
9992 );
9993 }
9994
9995 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
9996 /// identically through [`Self::horizon_requires_metric_axes`]
9997 /// AND through
9998 /// `<eph.clone().into::<ProcessSpec>>().classification.horizon_requires_metric_axes()`
9999 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10000 /// classification, `Some(_)` classification on every
10001 /// [`HorizonKind::ALL`] variant) so a future regression on
10002 /// either side of the resolver fails HERE at the parity
10003 /// boundary. Byte-for-byte peer of the sibling
10004 /// `horizon_terminates_matches_point_peer_through_lowered_classification`.
10005 #[test]
10006 fn horizon_requires_metric_axes_matches_point_peer_through_lowered_classification() {
10007 // Absent classification.
10008 let eph = empty_ephemeral();
10009 let lowered: ProcessSpec = eph.clone().into();
10010 assert_eq!(
10011 eph.horizon_requires_metric_axes(),
10012 lowered.classification.horizon_requires_metric_axes(),
10013 "None-classification parity drift",
10014 );
10015 // Authored classification.
10016 for populated in HorizonKind::ALL {
10017 let classification = Classification::gate_compute_with_axis(populated);
10018 let mut eph = empty_ephemeral();
10019 eph.classification = Some(classification);
10020 let lowered: ProcessSpec = eph.clone().into();
10021 assert_eq!(
10022 eph.horizon_requires_metric_axes(),
10023 lowered.classification.horizon_requires_metric_axes(),
10024 "authored horizon.kind={populated:?}: parity drift",
10025 );
10026 }
10027 }
10028
10029 // ── EphemeralSpec::calm_requires_coordination pins ───────────────
10030 //
10031 // Fail-before-pass-after granularity: `calm_requires_coordination`
10032 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
10033 // walking the "does this ephemeral spec require coordination?"
10034 // question went through
10035 // `.resolved_classification().calm.requires_coordination()` or
10036 // through the lowered `ProcessSpec`'s
10037 // `spec.classification.calm.requires_coordination()`. Post-lift the
10038 // THIRD derived-nullary-boolean peer on the ephemeral surface
10039 // (first on the calm axis, after the two horizon-axis peers)
10040 // routes through the SAME [`Self::resolved_classification`]
10041 // resolver + the sibling substrate primitive
10042 // [`crate::classification::Classification::calm_requires_coordination`],
10043 // so the two-surface parity contract holds by construction — a
10044 // regression on either side of the resolver fails at these pins
10045 // before landing at the operator-facing `coordination-required`
10046 // fixed tag in `tatara-check`.
10047
10048 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10049 /// [`Classification`] carries a specific [`CalmClassification`]
10050 /// variant answers [`Self::calm_requires_coordination`] matching
10051 /// the closed set's own
10052 /// [`CalmClassification::requires_coordination`] truth table.
10053 /// Sweep [`CalmClassification::ALL`] so a regression that (a)
10054 /// hard-coded the body to a fixed answer, (b) inverted the
10055 /// projection, or (c) crossed the wires with a sibling
10056 /// classification-axis probe fails HERE at the substrate primitive
10057 /// before drifting through the `coordination-required` fixed tag
10058 /// or the peer point surface.
10059 #[test]
10060 fn calm_requires_coordination_returns_calm_projection_per_kind() {
10061 for populated in CalmClassification::ALL {
10062 let mut classification = Classification::gate_compute();
10063 classification.calm = populated;
10064 let mut spec = empty_ephemeral();
10065 spec.classification = Some(classification);
10066 assert_eq!(
10067 spec.calm_requires_coordination(),
10068 populated.requires_coordination(),
10069 "authored calm={populated:?}: calm_requires_coordination() drift",
10070 );
10071 }
10072 }
10073
10074 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10075 /// with `classification: None` routes through the
10076 /// [`Self::resolved_classification`] resolver's substrate default
10077 /// [`Classification::gate_compute`], which carries
10078 /// [`CalmClassification::default = Monotone`], and
10079 /// [`CalmClassification::Monotone::requires_coordination`] projects
10080 /// `false`, so [`Self::calm_requires_coordination`] returns
10081 /// `false`. Pins the default-arm short-circuit through TWO layers
10082 /// of `Default` ([`Classification::gate_compute`] →
10083 /// [`CalmClassification::default`]) reaching this derived-nullary
10084 /// predicate — distinct from the sibling `horizon_*` absent-
10085 /// classification pins by ONE structural degree (those walk THREE
10086 /// layers of `Default` because horizon has a nested-struct wrapper;
10087 /// this walks TWO because `calm` is a direct scalar). A regression
10088 /// that dropped the resolver hop (silently answering `true` on an
10089 /// absent classification, as if the operator's absence meant
10090 /// "requires coordination") fails HERE at ONE narrow ephemeral-
10091 /// surface site.
10092 #[test]
10093 fn calm_requires_coordination_probes_false_on_absent_classification() {
10094 let spec = empty_ephemeral();
10095 assert!(spec.classification.is_none());
10096 assert!(
10097 !spec.calm_requires_coordination(),
10098 "absent classification (defaults to gate_compute, calm=Monotone → requires_coordination=false)",
10099 );
10100 }
10101
10102 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10103 /// identically through [`Self::calm_requires_coordination`] AND
10104 /// through
10105 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_requires_coordination()`
10106 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10107 /// classification, `Some(_)` classification on every
10108 /// [`CalmClassification::ALL`] variant) so a future regression on
10109 /// either side of the resolver fails HERE at the parity boundary.
10110 /// Byte-for-byte peer of the sibling
10111 /// `horizon_terminates_matches_point_peer_through_lowered_classification`
10112 /// on the calm axis.
10113 #[test]
10114 fn calm_requires_coordination_matches_point_peer_through_lowered_classification() {
10115 // Absent classification.
10116 let eph = empty_ephemeral();
10117 let lowered: ProcessSpec = eph.clone().into();
10118 assert_eq!(
10119 eph.calm_requires_coordination(),
10120 lowered.classification.calm_requires_coordination(),
10121 "None-classification parity drift",
10122 );
10123 // Authored classification.
10124 for populated in CalmClassification::ALL {
10125 let mut classification = Classification::gate_compute();
10126 classification.calm = populated;
10127 let mut eph = empty_ephemeral();
10128 eph.classification = Some(classification);
10129 let lowered: ProcessSpec = eph.clone().into();
10130 assert_eq!(
10131 eph.calm_requires_coordination(),
10132 lowered.classification.calm_requires_coordination(),
10133 "authored calm={populated:?}: parity drift",
10134 );
10135 }
10136 }
10137
10138 // ── EphemeralSpec::data_is_regulated pins ────────────────────────
10139 //
10140 // Fail-before-pass-after granularity: `data_is_regulated` did not
10141 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10142 // the "does this ephemeral spec carry regulated data?" question
10143 // went through
10144 // `.resolved_classification().data_classification.is_regulated()`
10145 // or through the lowered `ProcessSpec`'s
10146 // `spec.classification.data_classification.is_regulated()`. Post-
10147 // lift the FOURTH derived-nullary-boolean peer on the ephemeral
10148 // surface (first on the data axis, after two horizon-axis peers
10149 // and one calm-axis peer) routes through the SAME
10150 // [`Self::resolved_classification`] resolver + the sibling
10151 // substrate primitive
10152 // [`crate::classification::Classification::data_is_regulated`],
10153 // so the two-surface parity contract holds by construction — a
10154 // regression on either side of the resolver fails at these pins
10155 // before landing at the operator-facing `data-regulated` fixed
10156 // tag in `tatara-check`.
10157
10158 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10159 /// [`Classification`] carries a specific [`DataClassification`]
10160 /// variant answers [`Self::data_is_regulated`] matching the
10161 /// closed set's own [`DataClassification::is_regulated`] truth
10162 /// table. Sweep [`DataClassification::ALL`] so a regression that
10163 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10164 /// projection, or (c) crossed the wires with a sibling
10165 /// classification-axis probe fails HERE at the substrate
10166 /// primitive before drifting through the `data-regulated` fixed
10167 /// tag or the peer point surface.
10168 #[test]
10169 fn data_is_regulated_returns_data_classification_projection_per_kind() {
10170 for populated in DataClassification::ALL {
10171 let mut classification = Classification::gate_compute();
10172 classification.data_classification = populated;
10173 let mut spec = empty_ephemeral();
10174 spec.classification = Some(classification);
10175 assert_eq!(
10176 spec.data_is_regulated(),
10177 populated.is_regulated(),
10178 "authored data_classification={populated:?}: data_is_regulated() drift",
10179 );
10180 }
10181 }
10182
10183 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10184 /// with `classification: None` routes through the
10185 /// [`Self::resolved_classification`] resolver's substrate default
10186 /// [`Classification::gate_compute`], which carries
10187 /// [`DataClassification::default = Internal`], and
10188 /// [`DataClassification::Internal::is_regulated`] projects
10189 /// `false`, so [`Self::data_is_regulated`] returns `false`. Pins
10190 /// the default-arm short-circuit through TWO layers of `Default`
10191 /// ([`Classification::gate_compute`] →
10192 /// [`DataClassification::default`]) reaching this derived-nullary
10193 /// predicate — byte-for-byte structural peer of the sibling
10194 /// `calm_requires_coordination_probes_false_on_absent_classification`
10195 /// on the classification-data axis, distinct from the two
10196 /// `horizon_*` absent-classification pins by ONE structural
10197 /// degree (those walk THREE layers because horizon has a nested-
10198 /// struct wrapper; this walks TWO because `data_classification`
10199 /// is a direct scalar). A regression that dropped the resolver
10200 /// hop (silently answering `true` on an absent classification,
10201 /// as if the operator's absence meant "regulated data") fails
10202 /// HERE at ONE narrow ephemeral-surface site.
10203 #[test]
10204 fn data_is_regulated_probes_false_on_absent_classification() {
10205 let spec = empty_ephemeral();
10206 assert!(spec.classification.is_none());
10207 assert!(
10208 !spec.data_is_regulated(),
10209 "absent classification (defaults to gate_compute, data_classification=Internal → is_regulated=false)",
10210 );
10211 }
10212
10213 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10214 /// identically through [`Self::data_is_regulated`] AND through
10215 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_regulated()`
10216 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10217 /// classification, `Some(_)` classification on every
10218 /// [`DataClassification::ALL`] variant) so a future regression on
10219 /// either side of the resolver fails HERE at the parity boundary.
10220 /// Byte-for-byte peer of the sibling
10221 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
10222 /// on the data axis.
10223 #[test]
10224 fn data_is_regulated_matches_point_peer_through_lowered_classification() {
10225 // Absent classification.
10226 let eph = empty_ephemeral();
10227 let lowered: ProcessSpec = eph.clone().into();
10228 assert_eq!(
10229 eph.data_is_regulated(),
10230 lowered.classification.data_is_regulated(),
10231 "None-classification parity drift",
10232 );
10233 // Authored classification.
10234 for populated in DataClassification::ALL {
10235 let mut classification = Classification::gate_compute();
10236 classification.data_classification = populated;
10237 let mut eph = empty_ephemeral();
10238 eph.classification = Some(classification);
10239 let lowered: ProcessSpec = eph.clone().into();
10240 assert_eq!(
10241 eph.data_is_regulated(),
10242 lowered.classification.data_is_regulated(),
10243 "authored data_classification={populated:?}: parity drift",
10244 );
10245 }
10246 }
10247
10248 // ── EphemeralSpec::data_is_restricted pins ───────────────────────
10249 //
10250 // Fail-before-pass-after granularity: `data_is_restricted` did not
10251 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10252 // the "does this ephemeral spec require access controls?" question
10253 // went through
10254 // `.resolved_classification().data_classification.is_restricted()`
10255 // or through the lowered `ProcessSpec`'s
10256 // `spec.classification.data_classification.is_restricted()`. Post-
10257 // lift the FIFTH derived-nullary-boolean peer on the ephemeral
10258 // surface (second on the data axis, after
10259 // [`Self::data_is_regulated`] opened the axis) routes through the
10260 // SAME [`Self::resolved_classification`] resolver + the sibling
10261 // substrate primitive
10262 // [`crate::classification::Classification::data_is_restricted`],
10263 // so the two-surface parity contract holds by construction — a
10264 // regression on either side of the resolver fails at these pins
10265 // before landing at the operator-facing `data-restricted` fixed
10266 // tag in `tatara-check`. FIRST direct-scalar ephemeral-surface
10267 // peer whose absent-classification baseline projects to `true`
10268 // rather than `false`.
10269
10270 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10271 /// [`Classification`] carries a specific [`DataClassification`]
10272 /// variant answers [`Self::data_is_restricted`] matching the
10273 /// closed set's own [`DataClassification::is_restricted`] truth
10274 /// table. Sweep [`DataClassification::ALL`] so a regression that
10275 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10276 /// projection, or (c) crossed the wires with the sibling
10277 /// [`DataClassification::is_regulated`] projection fails HERE at
10278 /// the substrate primitive before drifting through the
10279 /// `data-restricted` fixed tag or the peer point surface.
10280 #[test]
10281 fn data_is_restricted_returns_data_classification_projection_per_kind() {
10282 for populated in DataClassification::ALL {
10283 let mut classification = Classification::gate_compute();
10284 classification.data_classification = populated;
10285 let mut spec = empty_ephemeral();
10286 spec.classification = Some(classification);
10287 assert_eq!(
10288 spec.data_is_restricted(),
10289 populated.is_restricted(),
10290 "authored data_classification={populated:?}: data_is_restricted() drift",
10291 );
10292 }
10293 }
10294
10295 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10296 /// with `classification: None` routes through the
10297 /// [`Self::resolved_classification`] resolver's substrate default
10298 /// [`Classification::gate_compute`], which carries
10299 /// [`DataClassification::default = Internal`], and
10300 /// [`DataClassification::Internal::is_restricted`] projects
10301 /// `true`, so [`Self::data_is_restricted`] returns `true`. Pins
10302 /// the default-arm short-circuit through TWO layers of `Default`
10303 /// ([`Classification::gate_compute`] →
10304 /// [`DataClassification::default`]) reaching this derived-nullary
10305 /// predicate. FIRST direct-scalar ephemeral-surface peer whose
10306 /// absent-classification baseline answers `true`, not `false`
10307 /// (the four earlier direct-scalar peers on this surface —
10308 /// `data_is_regulated`, `calm_requires_coordination`, plus the
10309 /// nested-struct `horizon_requires_metric_axes` — all project
10310 /// `false` on the same absent classification, and only the
10311 /// sibling nested-struct `horizon_terminates` projects `true`).
10312 /// A regression that dropped the resolver hop (silently answering
10313 /// `false` on an absent classification, as if the operator's
10314 /// absence meant "freely distributable"), or that inverted the
10315 /// projection while the closed-set primitive stayed intact,
10316 /// fails HERE at ONE narrow ephemeral-surface site.
10317 #[test]
10318 fn data_is_restricted_probes_true_on_absent_classification() {
10319 let spec = empty_ephemeral();
10320 assert!(spec.classification.is_none());
10321 assert!(
10322 spec.data_is_restricted(),
10323 "absent classification (defaults to gate_compute, data_classification=Internal → is_restricted=true)",
10324 );
10325 }
10326
10327 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10328 /// identically through [`Self::data_is_restricted`] AND through
10329 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_restricted()`
10330 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10331 /// classification, `Some(_)` classification on every
10332 /// [`DataClassification::ALL`] variant) so a future regression on
10333 /// either side of the resolver fails HERE at the parity boundary.
10334 /// Byte-for-byte peer of the sibling
10335 /// `data_is_regulated_matches_point_peer_through_lowered_classification`
10336 /// on the same classification-data axis, published a second time
10337 /// through the antisymmetric closed-set projection.
10338 #[test]
10339 fn data_is_restricted_matches_point_peer_through_lowered_classification() {
10340 // Absent classification.
10341 let eph = empty_ephemeral();
10342 let lowered: ProcessSpec = eph.clone().into();
10343 assert_eq!(
10344 eph.data_is_restricted(),
10345 lowered.classification.data_is_restricted(),
10346 "None-classification parity drift",
10347 );
10348 // Authored classification.
10349 for populated in DataClassification::ALL {
10350 let mut classification = Classification::gate_compute();
10351 classification.data_classification = populated;
10352 let mut eph = empty_ephemeral();
10353 eph.classification = Some(classification);
10354 let lowered: ProcessSpec = eph.clone().into();
10355 assert_eq!(
10356 eph.data_is_restricted(),
10357 lowered.classification.data_is_restricted(),
10358 "authored data_classification={populated:?}: parity drift",
10359 );
10360 }
10361 }
10362
10363 /// COMPOSED IMPLICATION pin — the ephemeral-surface counterpart of
10364 /// the closed-set-internal
10365 /// `data_classification_regulated_implies_restricted` and its
10366 /// parent-composed peer
10367 /// `classification_data_is_regulated_implies_data_is_restricted_over_all`:
10368 /// for every ([`EphemeralSpec`] with authored classification
10369 /// carrying every [`DataClassification`] variant, plus the
10370 /// absent-classification case), the resolver-hop probe pair
10371 /// satisfies `data_is_regulated() ⇒ data_is_restricted()`. Pins
10372 /// the implication contract at the ephemeral-surface site so a
10373 /// regression that (a) inverted the ephemeral
10374 /// [`Self::data_is_regulated`] resolver hop, (b) inverted the
10375 /// ephemeral [`Self::data_is_restricted`] resolver hop, or (c)
10376 /// crossed their wires while the underlying substrate primitives
10377 /// stayed intact fails HERE. FIRST ephemeral-surface corner-peer
10378 /// pair whose two projections carry a non-trivial closed-set-
10379 /// internal implication relationship.
10380 #[test]
10381 fn ephemeral_data_is_regulated_implies_data_is_restricted_over_all() {
10382 // Absent classification.
10383 let eph = empty_ephemeral();
10384 assert!(
10385 !eph.data_is_regulated() || eph.data_is_restricted(),
10386 "None-classification: data_is_regulated ⇒ data_is_restricted violated",
10387 );
10388 // Authored classification.
10389 for populated in DataClassification::ALL {
10390 let mut classification = Classification::gate_compute();
10391 classification.data_classification = populated;
10392 let mut eph = empty_ephemeral();
10393 eph.classification = Some(classification);
10394 assert!(
10395 !eph.data_is_regulated() || eph.data_is_restricted(),
10396 "authored data_classification={populated:?}: data_is_regulated ⇒ data_is_restricted violated",
10397 );
10398 }
10399 }
10400
10401 // ── EphemeralSpec::point_is_endomorphic pins ─────────────────────
10402 //
10403 // Fail-before-pass-after granularity: `point_is_endomorphic` did
10404 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10405 // walking the "does this ephemeral spec's point-type project to
10406 // the 1→1 endomorphic bucket?" question went through
10407 // `.resolved_classification().point_type.is_endomorphic()` or the
10408 // lowered `ProcessSpec`'s
10409 // `spec.classification.point_type.is_endomorphic()`. Post-lift the
10410 // SIXTH derived-nullary-boolean peer on the ephemeral surface
10411 // (first on the `point_type` axis) routes through the SAME
10412 // [`Self::resolved_classification`] resolver + the sibling
10413 // substrate primitive
10414 // [`crate::classification::Classification::point_is_endomorphic`],
10415 // so the two-surface parity contract holds by construction — a
10416 // regression on either side of the resolver fails at these pins
10417 // before landing at the operator-facing `endomorphic-point` fixed
10418 // tag in `tatara-check`.
10419
10420 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10421 /// [`Classification`] carries a specific [`ConvergencePointType`]
10422 /// variant answers [`Self::point_is_endomorphic`] matching the
10423 /// closed set's own [`ConvergencePointType::is_endomorphic`] truth
10424 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10425 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10426 /// projection, or (c) crossed the wires with the sibling
10427 /// [`ConvergencePointType::is_diffusive`] /
10428 /// [`ConvergencePointType::is_convergent`] projections fails
10429 /// HERE at the substrate primitive before drifting through the
10430 /// `endomorphic-point` fixed tag or the peer point surface.
10431 #[test]
10432 fn point_is_endomorphic_returns_point_type_projection_per_kind() {
10433 for populated in ConvergencePointType::ALL {
10434 let mut classification = Classification::gate_compute();
10435 classification.point_type = populated;
10436 let mut spec = empty_ephemeral();
10437 spec.classification = Some(classification);
10438 assert_eq!(
10439 spec.point_is_endomorphic(),
10440 populated.is_endomorphic(),
10441 "authored point_type={populated:?}: point_is_endomorphic() drift",
10442 );
10443 }
10444 }
10445
10446 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10447 /// with `classification: None` routes through the
10448 /// [`Self::resolved_classification`] resolver's substrate default
10449 /// [`Classification::gate_compute`], which carries
10450 /// [`ConvergencePointType::Gate`] (a convergent barrier, not an
10451 /// endomorphism), and
10452 /// [`ConvergencePointType::Gate::is_endomorphic`] projects `false`,
10453 /// so [`Self::point_is_endomorphic`] returns `false`. Pins the
10454 /// resolver's chosen-field baseline at ONE narrow site — a
10455 /// regression that dropped the resolver hop, or that promoted
10456 /// [`ConvergencePointType::Transform`] to the gate-compute
10457 /// baseline (silently retargeting every unadorned ephemeral
10458 /// spec's topology bucket), fails HERE at ONE narrow ephemeral-
10459 /// surface site. FIRST direct-scalar ephemeral-surface peer whose
10460 /// absent-classification baseline is a chosen-field answer on the
10461 /// resolver's [`Classification::gate_compute`] default rather
10462 /// than a substrate-`#[default]` short-circuit on the closed-set
10463 /// side ([`ConvergencePointType`] has no `impl Default`).
10464 #[test]
10465 fn point_is_endomorphic_probes_false_on_absent_classification() {
10466 let spec = empty_ephemeral();
10467 assert!(spec.classification.is_none());
10468 assert!(
10469 !spec.point_is_endomorphic(),
10470 "absent classification (defaults to gate_compute, point_type=Gate → is_endomorphic=false)",
10471 );
10472 }
10473
10474 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10475 /// identically through [`Self::point_is_endomorphic`] AND through
10476 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_endomorphic()`
10477 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10478 /// classification, `Some(_)` classification on every
10479 /// [`ConvergencePointType::ALL`] variant) so a future regression
10480 /// on either side of the resolver fails HERE at the parity
10481 /// boundary. Byte-for-byte peer of the sibling
10482 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
10483 /// on a DIFFERENT closed-set axis, published a first time through
10484 /// the `point_type` closed-set projection.
10485 #[test]
10486 fn point_is_endomorphic_matches_point_peer_through_lowered_classification() {
10487 // Absent classification.
10488 let eph = empty_ephemeral();
10489 let lowered: ProcessSpec = eph.clone().into();
10490 assert_eq!(
10491 eph.point_is_endomorphic(),
10492 lowered.classification.point_is_endomorphic(),
10493 "None-classification parity drift",
10494 );
10495 // Authored classification.
10496 for populated in ConvergencePointType::ALL {
10497 let mut classification = Classification::gate_compute();
10498 classification.point_type = populated;
10499 let mut eph = empty_ephemeral();
10500 eph.classification = Some(classification);
10501 let lowered: ProcessSpec = eph.clone().into();
10502 assert_eq!(
10503 eph.point_is_endomorphic(),
10504 lowered.classification.point_is_endomorphic(),
10505 "authored point_type={populated:?}: parity drift",
10506 );
10507 }
10508 }
10509
10510 // ── EphemeralSpec::point_is_diffusive pins ───────────────────────
10511 //
10512 // Fail-before-pass-after granularity: `point_is_diffusive` did not
10513 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
10514 // the "does this ephemeral spec's point-type project to the 1→N
10515 // diffusive fan-out bucket?" question went through
10516 // `.resolved_classification().point_type.is_diffusive()` or the
10517 // lowered `ProcessSpec`'s
10518 // `spec.classification.point_type.is_diffusive()`. Post-lift the
10519 // SEVENTH derived-nullary-boolean peer on the ephemeral surface
10520 // (SECOND on the `point_type` axis) routes through the SAME
10521 // [`Self::resolved_classification`] resolver + the sibling
10522 // substrate primitive
10523 // [`crate::classification::Classification::point_is_diffusive`],
10524 // so the two-surface parity contract holds by construction.
10525
10526 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10527 /// [`Classification`] carries a specific [`ConvergencePointType`]
10528 /// variant answers [`Self::point_is_diffusive`] matching the
10529 /// closed set's own [`ConvergencePointType::is_diffusive`] truth
10530 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10531 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10532 /// projection, or (c) crossed the wires with the sibling
10533 /// [`ConvergencePointType::is_endomorphic`] /
10534 /// [`ConvergencePointType::is_convergent`] projections fails HERE
10535 /// at the substrate primitive before drifting through the
10536 /// `diffusive-point` fixed tag or the peer point surface.
10537 #[test]
10538 fn point_is_diffusive_returns_point_type_projection_per_kind() {
10539 for populated in ConvergencePointType::ALL {
10540 let mut classification = Classification::gate_compute();
10541 classification.point_type = populated;
10542 let mut spec = empty_ephemeral();
10543 spec.classification = Some(classification);
10544 assert_eq!(
10545 spec.point_is_diffusive(),
10546 populated.is_diffusive(),
10547 "authored point_type={populated:?}: point_is_diffusive() drift",
10548 );
10549 }
10550 }
10551
10552 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10553 /// with `classification: None` routes through the
10554 /// [`Self::resolved_classification`] resolver's substrate default
10555 /// [`Classification::gate_compute`], which carries
10556 /// [`ConvergencePointType::Gate`] (a convergent barrier, not a
10557 /// diffusive fan-out), and
10558 /// [`ConvergencePointType::Gate::is_diffusive`] projects `false`,
10559 /// so [`Self::point_is_diffusive`] returns `false`. Pins the
10560 /// resolver's chosen-field baseline at ONE narrow site.
10561 #[test]
10562 fn point_is_diffusive_probes_false_on_absent_classification() {
10563 let spec = empty_ephemeral();
10564 assert!(spec.classification.is_none());
10565 assert!(
10566 !spec.point_is_diffusive(),
10567 "absent classification (defaults to gate_compute, point_type=Gate → is_diffusive=false)",
10568 );
10569 }
10570
10571 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10572 /// identically through [`Self::point_is_diffusive`] AND through
10573 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_diffusive()`
10574 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10575 /// classification, `Some(_)` classification on every
10576 /// [`ConvergencePointType::ALL`] variant) so a future regression
10577 /// on either side of the resolver fails HERE at the parity
10578 /// boundary. Byte-for-byte peer of
10579 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10580 /// on the SAME closed-set axis via a sibling projection.
10581 #[test]
10582 fn point_is_diffusive_matches_point_peer_through_lowered_classification() {
10583 // Absent classification.
10584 let eph = empty_ephemeral();
10585 let lowered: ProcessSpec = eph.clone().into();
10586 assert_eq!(
10587 eph.point_is_diffusive(),
10588 lowered.classification.point_is_diffusive(),
10589 "None-classification parity drift",
10590 );
10591 // Authored classification.
10592 for populated in ConvergencePointType::ALL {
10593 let mut classification = Classification::gate_compute();
10594 classification.point_type = populated;
10595 let mut eph = empty_ephemeral();
10596 eph.classification = Some(classification);
10597 let lowered: ProcessSpec = eph.clone().into();
10598 assert_eq!(
10599 eph.point_is_diffusive(),
10600 lowered.classification.point_is_diffusive(),
10601 "authored point_type={populated:?}: parity drift",
10602 );
10603 }
10604 }
10605
10606 /// MUTEX pin — [`Self::point_is_endomorphic`] AND
10607 /// [`Self::point_is_diffusive`] are NEVER simultaneously true for
10608 /// ANY [`EphemeralSpec`] (authored or defaulted), since the
10609 /// underlying [`ConvergencePointType`] closed set carves its
10610 /// eight variants into THREE disjoint buckets. Sweep the absent-
10611 /// classification case + every [`ConvergencePointType::ALL`]
10612 /// variant so a regression that crossed the wires between the
10613 /// two ephemeral-surface corner peers (one probe silently
10614 /// composing the wrong closed-set arm at the resolver-hop layer)
10615 /// fails HERE rather than at every downstream consumer that
10616 /// trusts the two probes partition the resolver's output into
10617 /// disjoint buckets. FIRST ephemeral-surface corner-peer pair on
10618 /// the `point_type` axis whose two projections carry a non-
10619 /// trivial closed-set-internal MUTEX relationship (distinct from
10620 /// the sibling `data`-axis pair whose two projections carry a
10621 /// non-trivial IMPLICATION relationship, sealed by
10622 /// `ephemeral_data_is_regulated_implies_data_is_restricted_over_all`).
10623 #[test]
10624 fn ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all() {
10625 // Absent classification.
10626 let eph = empty_ephemeral();
10627 assert!(
10628 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10629 "None-classification: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10630 );
10631 // Authored classification.
10632 for populated in ConvergencePointType::ALL {
10633 let mut classification = Classification::gate_compute();
10634 classification.point_type = populated;
10635 let mut eph = empty_ephemeral();
10636 eph.classification = Some(classification);
10637 assert!(
10638 !(eph.point_is_endomorphic() && eph.point_is_diffusive()),
10639 "authored point_type={populated:?}: point_is_endomorphic AND point_is_diffusive both true (mutex violated)",
10640 );
10641 }
10642 }
10643
10644 // ── EphemeralSpec::point_is_convergent pins ──────────────────────
10645 //
10646 // Fail-before-pass-after granularity: `point_is_convergent` did
10647 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10648 // walking the "does this ephemeral spec's point-type project to
10649 // the N→1 convergent fan-in bucket?" question went through
10650 // `.resolved_classification().point_type.is_convergent()` or the
10651 // lowered `ProcessSpec`'s
10652 // `spec.classification.point_type.is_convergent()`. Post-lift the
10653 // EIGHTH derived-nullary-boolean peer on the ephemeral surface
10654 // (THIRD on the `point_type` axis) routes through the SAME
10655 // [`Self::resolved_classification`] resolver + the sibling
10656 // substrate primitive
10657 // [`crate::classification::Classification::point_is_convergent`],
10658 // so the two-surface parity contract holds by construction, AND
10659 // the THREE `point_type`-axis peers on this surface close into
10660 // the FULL three-way XOR partition contract.
10661
10662 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10663 /// [`Classification`] carries a specific [`ConvergencePointType`]
10664 /// variant answers [`Self::point_is_convergent`] matching the
10665 /// closed set's own [`ConvergencePointType::is_convergent`] truth
10666 /// table. Sweep [`ConvergencePointType::ALL`] so a regression that
10667 /// (a) hard-coded the body to a fixed answer, (b) inverted the
10668 /// projection, or (c) crossed the wires with the sibling
10669 /// [`ConvergencePointType::is_endomorphic`] /
10670 /// [`ConvergencePointType::is_diffusive`] projections fails HERE
10671 /// at the substrate primitive before drifting through the
10672 /// `convergent-point` fixed tag or the peer point surface.
10673 #[test]
10674 fn point_is_convergent_returns_point_type_projection_per_kind() {
10675 for populated in ConvergencePointType::ALL {
10676 let mut classification = Classification::gate_compute();
10677 classification.point_type = populated;
10678 let mut spec = empty_ephemeral();
10679 spec.classification = Some(classification);
10680 assert_eq!(
10681 spec.point_is_convergent(),
10682 populated.is_convergent(),
10683 "authored point_type={populated:?}: point_is_convergent() drift",
10684 );
10685 }
10686 }
10687
10688 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10689 /// with `classification: None` routes through the
10690 /// [`Self::resolved_classification`] resolver's substrate default
10691 /// [`Classification::gate_compute`], which carries
10692 /// [`ConvergencePointType::Gate`] (the canonical convergent
10693 /// barrier), and [`ConvergencePointType::Gate::is_convergent`]
10694 /// projects `true`, so [`Self::point_is_convergent`] returns
10695 /// `true`. Pins the resolver's chosen-field baseline at ONE
10696 /// narrow site — FIRST direct-scalar ephemeral-surface peer whose
10697 /// absent-classification baseline projects `true` through the
10698 /// resolver's chosen-field answer, mirror-inverted from the two
10699 /// sibling `point_is_endomorphic` / `point_is_diffusive`
10700 /// ephemeral-surface baselines which both project `false`.
10701 #[test]
10702 fn point_is_convergent_probes_true_on_absent_classification() {
10703 let spec = empty_ephemeral();
10704 assert!(spec.classification.is_none());
10705 assert!(
10706 spec.point_is_convergent(),
10707 "absent classification (defaults to gate_compute, point_type=Gate → is_convergent=true)",
10708 );
10709 }
10710
10711 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10712 /// identically through [`Self::point_is_convergent`] AND through
10713 /// `<eph.clone().into::<ProcessSpec>>().classification.point_is_convergent()`
10714 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10715 /// classification, `Some(_)` classification on every
10716 /// [`ConvergencePointType::ALL`] variant) so a future regression
10717 /// on either side of the resolver fails HERE at the parity
10718 /// boundary. Byte-for-byte peer of
10719 /// `point_is_endomorphic_matches_point_peer_through_lowered_classification`
10720 /// and
10721 /// `point_is_diffusive_matches_point_peer_through_lowered_classification`
10722 /// on the SAME closed-set axis via a sibling projection.
10723 #[test]
10724 fn point_is_convergent_matches_point_peer_through_lowered_classification() {
10725 // Absent classification.
10726 let eph = empty_ephemeral();
10727 let lowered: ProcessSpec = eph.clone().into();
10728 assert_eq!(
10729 eph.point_is_convergent(),
10730 lowered.classification.point_is_convergent(),
10731 "None-classification parity drift",
10732 );
10733 // Authored classification.
10734 for populated in ConvergencePointType::ALL {
10735 let mut classification = Classification::gate_compute();
10736 classification.point_type = populated;
10737 let mut eph = empty_ephemeral();
10738 eph.classification = Some(classification);
10739 let lowered: ProcessSpec = eph.clone().into();
10740 assert_eq!(
10741 eph.point_is_convergent(),
10742 lowered.classification.point_is_convergent(),
10743 "authored point_type={populated:?}: parity drift",
10744 );
10745 }
10746 }
10747
10748 /// THREE-WAY XOR PARTITION pin — for the absent-classification
10749 /// baseline AND every [`ConvergencePointType::ALL`] variant,
10750 /// EXACTLY ONE of [`Self::point_is_endomorphic`],
10751 /// [`Self::point_is_diffusive`], and [`Self::point_is_convergent`]
10752 /// returns `true`. Closes the mutex pair
10753 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`
10754 /// into the FULL ternary XOR partition contract on the ephemeral
10755 /// surface — the resolver-hop peer of the parent-composed
10756 /// `classification_point_type_probes_form_three_way_xor_partition_over_all`
10757 /// test. Guarantees the absent-classification case lands in the
10758 /// convergent bucket (`gate_compute` → Gate → is_convergent =
10759 /// true), so every unadorned `(defephemeral …)` audits under a
10760 /// definite non-empty topology bucket.
10761 #[test]
10762 fn ephemeral_point_type_probes_form_three_way_xor_partition_over_all() {
10763 // Absent classification.
10764 let eph = empty_ephemeral();
10765 let buckets = [
10766 eph.point_is_endomorphic(),
10767 eph.point_is_diffusive(),
10768 eph.point_is_convergent(),
10769 ];
10770 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10771 assert_eq!(
10772 hits, 1,
10773 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10774 );
10775 // Authored classification.
10776 for populated in ConvergencePointType::ALL {
10777 let mut classification = Classification::gate_compute();
10778 classification.point_type = populated;
10779 let mut eph = empty_ephemeral();
10780 eph.classification = Some(classification);
10781 let buckets = [
10782 eph.point_is_endomorphic(),
10783 eph.point_is_diffusive(),
10784 eph.point_is_convergent(),
10785 ];
10786 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
10787 assert_eq!(
10788 hits, 1,
10789 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
10790 );
10791 }
10792 }
10793
10794 // ── EphemeralSpec::substrate_is_resource pins ────────────────────
10795 //
10796 // Fail-before-pass-after granularity: `substrate_is_resource` did
10797 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10798 // walking the "does this ephemeral spec's substrate project to
10799 // the resource plane?" question went through
10800 // `.resolved_classification().substrate.is_resource()` or the
10801 // lowered `ProcessSpec`'s
10802 // `spec.classification.substrate.is_resource()`. Post-lift the
10803 // NINTH derived-nullary-boolean peer on the ephemeral surface
10804 // (FIRST on the `substrate` axis) routes through the SAME
10805 // [`Self::resolved_classification`] resolver + the sibling
10806 // substrate primitive
10807 // [`crate::classification::Classification::substrate_is_resource`],
10808 // so the two-surface parity contract holds by construction.
10809
10810 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10811 /// [`Classification`] carries a specific
10812 /// [`crate::classification::SubstrateType`] variant answers
10813 /// [`Self::substrate_is_resource`] matching the closed set's own
10814 /// [`crate::classification::SubstrateType::is_resource`] truth
10815 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10816 /// so a regression that (a) hard-coded the body to a fixed
10817 /// answer, (b) inverted the projection, or (c) crossed the wires
10818 /// with the sibling
10819 /// [`crate::classification::SubstrateType::is_policy`] /
10820 /// [`crate::classification::SubstrateType::is_telemetry`]
10821 /// projections fails HERE at the substrate primitive before
10822 /// drifting through the `resource-substrate` fixed tag or the
10823 /// peer point surface.
10824 #[test]
10825 fn substrate_is_resource_returns_substrate_projection_per_kind() {
10826 for populated in SubstrateType::ALL {
10827 let mut classification = Classification::gate_compute();
10828 classification.substrate = populated;
10829 let mut spec = empty_ephemeral();
10830 spec.classification = Some(classification);
10831 assert_eq!(
10832 spec.substrate_is_resource(),
10833 populated.is_resource(),
10834 "authored substrate={populated:?}: substrate_is_resource() drift",
10835 );
10836 }
10837 }
10838
10839 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10840 /// with `classification: None` routes through the
10841 /// [`Self::resolved_classification`] resolver's substrate default
10842 /// [`Classification::gate_compute`], which carries
10843 /// [`crate::classification::SubstrateType::Compute`] (the
10844 /// canonical resource-plane substrate), and
10845 /// [`crate::classification::SubstrateType::Compute::is_resource`]
10846 /// projects `true`, so [`Self::substrate_is_resource`] returns
10847 /// `true`. Pins the resolver's chosen-field baseline at ONE
10848 /// narrow site — mirror-aligned with the sibling
10849 /// `point_is_convergent_probes_true_on_absent_classification`
10850 /// baseline (both projections on `gate_compute` chosen fields
10851 /// answer `true`).
10852 #[test]
10853 fn substrate_is_resource_probes_true_on_absent_classification() {
10854 let spec = empty_ephemeral();
10855 assert!(spec.classification.is_none());
10856 assert!(
10857 spec.substrate_is_resource(),
10858 "absent classification (defaults to gate_compute, substrate=Compute → is_resource=true)",
10859 );
10860 }
10861
10862 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10863 /// identically through [`Self::substrate_is_resource`] AND through
10864 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_resource()`
10865 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10866 /// classification, `Some(_)` classification on every
10867 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10868 /// future regression on either side of the resolver fails HERE
10869 /// at the parity boundary. Byte-for-byte peer of
10870 /// `point_is_convergent_matches_point_peer_through_lowered_classification`
10871 /// on a sibling classification axis.
10872 #[test]
10873 fn substrate_is_resource_matches_point_peer_through_lowered_classification() {
10874 // Absent classification.
10875 let eph = empty_ephemeral();
10876 let lowered: ProcessSpec = eph.clone().into();
10877 assert_eq!(
10878 eph.substrate_is_resource(),
10879 lowered.classification.substrate_is_resource(),
10880 "None-classification parity drift",
10881 );
10882 // Authored classification.
10883 for populated in SubstrateType::ALL {
10884 let mut classification = Classification::gate_compute();
10885 classification.substrate = populated;
10886 let mut eph = empty_ephemeral();
10887 eph.classification = Some(classification);
10888 let lowered: ProcessSpec = eph.clone().into();
10889 assert_eq!(
10890 eph.substrate_is_resource(),
10891 lowered.classification.substrate_is_resource(),
10892 "authored substrate={populated:?}: parity drift",
10893 );
10894 }
10895 }
10896
10897 // ── EphemeralSpec::substrate_is_policy pins ──────────────────────
10898 //
10899 // Fail-before-pass-after granularity: `substrate_is_policy` did
10900 // not exist pre-lift on `impl EphemeralSpec` — every consumer
10901 // walking the "does this ephemeral spec's substrate project to
10902 // the policy plane?" question went through
10903 // `.resolved_classification().substrate.is_policy()` or the
10904 // lowered `ProcessSpec`'s
10905 // `spec.classification.substrate.is_policy()`. Post-lift the
10906 // TENTH derived-nullary-boolean peer on the ephemeral surface
10907 // (SECOND on the `substrate` axis) routes through the SAME
10908 // [`Self::resolved_classification`] resolver + the sibling
10909 // substrate primitive
10910 // [`crate::classification::Classification::substrate_is_policy`],
10911 // so the two-surface parity contract holds by construction, AND
10912 // the two `substrate`-axis peers on this surface open the
10913 // MUTEX pair on the axis via
10914 // `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`.
10915
10916 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
10917 /// [`Classification`] carries a specific
10918 /// [`crate::classification::SubstrateType`] variant answers
10919 /// [`Self::substrate_is_policy`] matching the closed set's own
10920 /// [`crate::classification::SubstrateType::is_policy`] truth
10921 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
10922 /// so a regression that (a) hard-coded the body to a fixed
10923 /// answer, (b) inverted the projection, or (c) crossed the wires
10924 /// with the sibling
10925 /// [`crate::classification::SubstrateType::is_resource`] /
10926 /// [`crate::classification::SubstrateType::is_telemetry`]
10927 /// projections fails HERE at the substrate primitive before
10928 /// drifting through the `policy-substrate` fixed tag or the
10929 /// peer point surface.
10930 #[test]
10931 fn substrate_is_policy_returns_substrate_projection_per_kind() {
10932 for populated in SubstrateType::ALL {
10933 let mut classification = Classification::gate_compute();
10934 classification.substrate = populated;
10935 let mut spec = empty_ephemeral();
10936 spec.classification = Some(classification);
10937 assert_eq!(
10938 spec.substrate_is_policy(),
10939 populated.is_policy(),
10940 "authored substrate={populated:?}: substrate_is_policy() drift",
10941 );
10942 }
10943 }
10944
10945 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
10946 /// with `classification: None` routes through the
10947 /// [`Self::resolved_classification`] resolver's substrate default
10948 /// [`Classification::gate_compute`], which carries
10949 /// [`crate::classification::SubstrateType::Compute`] (the
10950 /// canonical resource-plane substrate, NOT a policy plane), and
10951 /// [`crate::classification::SubstrateType::Compute::is_policy`]
10952 /// projects `false`, so [`Self::substrate_is_policy`] returns
10953 /// `false`. Pins the resolver's chosen-field baseline at ONE
10954 /// narrow site — mirror-inverted from the sibling
10955 /// `substrate_is_resource_probes_true_on_absent_classification`
10956 /// (both projections on `gate_compute`'s chosen `substrate`
10957 /// field, but the sibling answers `true` where this one
10958 /// answers `false` — the closed set's disjoint plane partition
10959 /// forbids both being true).
10960 #[test]
10961 fn substrate_is_policy_probes_false_on_absent_classification() {
10962 let spec = empty_ephemeral();
10963 assert!(spec.classification.is_none());
10964 assert!(
10965 !spec.substrate_is_policy(),
10966 "absent classification (defaults to gate_compute, substrate=Compute → is_policy=false)",
10967 );
10968 }
10969
10970 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
10971 /// identically through [`Self::substrate_is_policy`] AND through
10972 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_policy()`
10973 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
10974 /// classification, `Some(_)` classification on every
10975 /// [`crate::classification::SubstrateType::ALL`] variant) so a
10976 /// future regression on either side of the resolver fails HERE
10977 /// at the parity boundary. Byte-for-byte peer of
10978 /// `substrate_is_resource_matches_point_peer_through_lowered_classification`
10979 /// on the SAME closed-set axis via a sibling projection.
10980 #[test]
10981 fn substrate_is_policy_matches_point_peer_through_lowered_classification() {
10982 // Absent classification.
10983 let eph = empty_ephemeral();
10984 let lowered: ProcessSpec = eph.clone().into();
10985 assert_eq!(
10986 eph.substrate_is_policy(),
10987 lowered.classification.substrate_is_policy(),
10988 "None-classification parity drift",
10989 );
10990 // Authored classification.
10991 for populated in SubstrateType::ALL {
10992 let mut classification = Classification::gate_compute();
10993 classification.substrate = populated;
10994 let mut eph = empty_ephemeral();
10995 eph.classification = Some(classification);
10996 let lowered: ProcessSpec = eph.clone().into();
10997 assert_eq!(
10998 eph.substrate_is_policy(),
10999 lowered.classification.substrate_is_policy(),
11000 "authored substrate={populated:?}: parity drift",
11001 );
11002 }
11003 }
11004
11005 /// MUTEX pin — [`Self::substrate_is_resource`] AND
11006 /// [`Self::substrate_is_policy`] are NEVER simultaneously true
11007 /// for ANY [`EphemeralSpec`] (authored or defaulted), since the
11008 /// underlying [`crate::classification::SubstrateType`] closed set
11009 /// carves its eight variants into THREE disjoint buckets. Sweep
11010 /// the absent-classification case + every
11011 /// [`crate::classification::SubstrateType::ALL`] variant so a
11012 /// regression that crossed the wires between the two ephemeral-
11013 /// surface corner peers (one probe silently composing the wrong
11014 /// closed-set arm at the resolver-hop layer) fails HERE rather
11015 /// than at every downstream consumer that trusts the two probes
11016 /// partition the resolver's output into disjoint buckets.
11017 /// FIRST ephemeral-surface `substrate`-axis corner-peer pair
11018 /// carrying a non-trivial MUTEX relationship — structural twin
11019 /// of the sibling `point_type`-axis MUTEX pair sealed on this
11020 /// surface by
11021 /// `ephemeral_point_is_endomorphic_and_point_is_diffusive_are_mutex_over_all`.
11022 #[test]
11023 fn ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all() {
11024 // Absent classification.
11025 let eph = empty_ephemeral();
11026 assert!(
11027 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
11028 "None-classification: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
11029 );
11030 // Authored classification.
11031 for populated in SubstrateType::ALL {
11032 let mut classification = Classification::gate_compute();
11033 classification.substrate = populated;
11034 let mut eph = empty_ephemeral();
11035 eph.classification = Some(classification);
11036 assert!(
11037 !(eph.substrate_is_resource() && eph.substrate_is_policy()),
11038 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_policy both true (mutex violated)",
11039 );
11040 }
11041 }
11042
11043 // ── EphemeralSpec::substrate_is_telemetry pins ───────────────────
11044 //
11045 // Fail-before-pass-after granularity: `substrate_is_telemetry`
11046 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
11047 // walking the "does this ephemeral spec's substrate project to
11048 // the telemetry plane?" question went through
11049 // `.resolved_classification().substrate.is_telemetry()` or the
11050 // lowered `ProcessSpec`'s
11051 // `spec.classification.substrate.is_telemetry()`. Post-lift the
11052 // ELEVENTH derived-nullary-boolean peer on the ephemeral surface
11053 // (THIRD on the `substrate` axis) routes through the SAME
11054 // [`Self::resolved_classification`] resolver + the sibling
11055 // substrate primitive
11056 // [`crate::classification::Classification::substrate_is_telemetry`],
11057 // so the two-surface parity contract holds by construction, AND
11058 // the three `substrate`-axis peers on this surface CLOSE the
11059 // axis into the FULL three-way XOR partition contract via
11060 // `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11061
11062 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11063 /// [`Classification`] carries a specific
11064 /// [`crate::classification::SubstrateType`] variant answers
11065 /// [`Self::substrate_is_telemetry`] matching the closed set's own
11066 /// [`crate::classification::SubstrateType::is_telemetry`] truth
11067 /// table. Sweep [`crate::classification::SubstrateType::ALL`]
11068 /// so a regression that (a) hard-coded the body to a fixed
11069 /// answer, (b) inverted the projection, or (c) crossed the wires
11070 /// with the sibling
11071 /// [`crate::classification::SubstrateType::is_resource`] /
11072 /// [`crate::classification::SubstrateType::is_policy`]
11073 /// projections fails HERE at the substrate primitive before
11074 /// drifting through the `telemetry-substrate` fixed tag or the
11075 /// peer point surface.
11076 #[test]
11077 fn substrate_is_telemetry_returns_substrate_projection_per_kind() {
11078 for populated in SubstrateType::ALL {
11079 let mut classification = Classification::gate_compute();
11080 classification.substrate = populated;
11081 let mut spec = empty_ephemeral();
11082 spec.classification = Some(classification);
11083 assert_eq!(
11084 spec.substrate_is_telemetry(),
11085 populated.is_telemetry(),
11086 "authored substrate={populated:?}: substrate_is_telemetry() drift",
11087 );
11088 }
11089 }
11090
11091 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11092 /// with `classification: None` routes through the
11093 /// [`Self::resolved_classification`] resolver's substrate default
11094 /// [`Classification::gate_compute`], which carries
11095 /// [`crate::classification::SubstrateType::Compute`] (the
11096 /// canonical resource-plane substrate, NOT a telemetry plane),
11097 /// and
11098 /// [`crate::classification::SubstrateType::Compute::is_telemetry`]
11099 /// projects `false`, so [`Self::substrate_is_telemetry`] returns
11100 /// `false`. Pins the resolver's chosen-field baseline at ONE
11101 /// narrow site — aligned with the sibling
11102 /// `substrate_is_policy_probes_false_on_absent_classification`
11103 /// (both projections on `gate_compute`'s chosen `substrate`
11104 /// field project `false` since `Compute` lives in the resource
11105 /// plane), mirror-inverted from
11106 /// `substrate_is_resource_probes_true_on_absent_classification`.
11107 #[test]
11108 fn substrate_is_telemetry_probes_false_on_absent_classification() {
11109 let spec = empty_ephemeral();
11110 assert!(spec.classification.is_none());
11111 assert!(
11112 !spec.substrate_is_telemetry(),
11113 "absent classification (defaults to gate_compute, substrate=Compute → is_telemetry=false)",
11114 );
11115 }
11116
11117 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11118 /// identically through [`Self::substrate_is_telemetry`] AND
11119 /// through
11120 /// `<eph.clone().into::<ProcessSpec>>().classification.substrate_is_telemetry()`
11121 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11122 /// classification, `Some(_)` classification on every
11123 /// [`crate::classification::SubstrateType::ALL`] variant) so a
11124 /// future regression on either side of the resolver fails HERE
11125 /// at the parity boundary. Byte-for-byte peer of
11126 /// `substrate_is_policy_matches_point_peer_through_lowered_classification`
11127 /// on the SAME closed-set axis via a sibling projection.
11128 #[test]
11129 fn substrate_is_telemetry_matches_point_peer_through_lowered_classification() {
11130 // Absent classification.
11131 let eph = empty_ephemeral();
11132 let lowered: ProcessSpec = eph.clone().into();
11133 assert_eq!(
11134 eph.substrate_is_telemetry(),
11135 lowered.classification.substrate_is_telemetry(),
11136 "None-classification parity drift",
11137 );
11138 // Authored classification.
11139 for populated in SubstrateType::ALL {
11140 let mut classification = Classification::gate_compute();
11141 classification.substrate = populated;
11142 let mut eph = empty_ephemeral();
11143 eph.classification = Some(classification);
11144 let lowered: ProcessSpec = eph.clone().into();
11145 assert_eq!(
11146 eph.substrate_is_telemetry(),
11147 lowered.classification.substrate_is_telemetry(),
11148 "authored substrate={populated:?}: parity drift",
11149 );
11150 }
11151 }
11152
11153 /// MUTEX pin — [`Self::substrate_is_resource`] AND
11154 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
11155 /// for ANY [`EphemeralSpec`] (authored or defaulted). Second
11156 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
11157 /// peer of
11158 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11159 /// on a sibling closed-set projection.
11160 #[test]
11161 fn ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all() {
11162 // Absent classification.
11163 let eph = empty_ephemeral();
11164 assert!(
11165 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
11166 "None-classification: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
11167 );
11168 // Authored classification.
11169 for populated in SubstrateType::ALL {
11170 let mut classification = Classification::gate_compute();
11171 classification.substrate = populated;
11172 let mut eph = empty_ephemeral();
11173 eph.classification = Some(classification);
11174 assert!(
11175 !(eph.substrate_is_resource() && eph.substrate_is_telemetry()),
11176 "authored substrate={populated:?}: substrate_is_resource AND substrate_is_telemetry both true (mutex violated)",
11177 );
11178 }
11179 }
11180
11181 /// MUTEX pin — [`Self::substrate_is_policy`] AND
11182 /// [`Self::substrate_is_telemetry`] are NEVER simultaneously true
11183 /// for ANY [`EphemeralSpec`] (authored or defaulted). Third
11184 /// ephemeral-surface `substrate`-axis corner-peer MUTEX pin —
11185 /// completes the three pairwise MUTEX relations alongside
11186 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11187 /// and
11188 /// `ephemeral_substrate_is_resource_and_substrate_is_telemetry_are_mutex_over_all`.
11189 #[test]
11190 fn ephemeral_substrate_is_policy_and_substrate_is_telemetry_are_mutex_over_all() {
11191 // Absent classification.
11192 let eph = empty_ephemeral();
11193 assert!(
11194 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
11195 "None-classification: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
11196 );
11197 // Authored classification.
11198 for populated in SubstrateType::ALL {
11199 let mut classification = Classification::gate_compute();
11200 classification.substrate = populated;
11201 let mut eph = empty_ephemeral();
11202 eph.classification = Some(classification);
11203 assert!(
11204 !(eph.substrate_is_policy() && eph.substrate_is_telemetry()),
11205 "authored substrate={populated:?}: substrate_is_policy AND substrate_is_telemetry both true (mutex violated)",
11206 );
11207 }
11208 }
11209
11210 /// THREE-WAY XOR PARTITION pin — for the absent-classification
11211 /// baseline AND every [`crate::classification::SubstrateType::ALL`]
11212 /// variant, EXACTLY ONE of [`Self::substrate_is_resource`],
11213 /// [`Self::substrate_is_policy`], and
11214 /// [`Self::substrate_is_telemetry`] returns `true`. CLOSES the
11215 /// three pairwise MUTEX pins on the substrate axis
11216 /// (`substrate_is_resource ⇒ ¬substrate_is_policy`,
11217 /// `substrate_is_resource ⇒ ¬substrate_is_telemetry`,
11218 /// `substrate_is_policy ⇒ ¬substrate_is_telemetry`) into the
11219 /// FULL ternary XOR partition contract on the ephemeral surface
11220 /// — the resolver-hop peer of the parent-composed
11221 /// `classification_substrate_probes_form_three_way_xor_partition_over_all`
11222 /// test. Structural twin of the sibling `point_type`-axis
11223 /// ternary lift sealed on this surface by
11224 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`.
11225 /// Guarantees the absent-classification case lands in the
11226 /// resource bucket (`gate_compute` → Compute → is_resource =
11227 /// true), so every unadorned `(defephemeral …)` audits under a
11228 /// definite non-empty plane bucket.
11229 #[test]
11230 fn ephemeral_substrate_probes_form_three_way_xor_partition_over_all() {
11231 // Absent classification.
11232 let eph = empty_ephemeral();
11233 let buckets = [
11234 eph.substrate_is_resource(),
11235 eph.substrate_is_policy(),
11236 eph.substrate_is_telemetry(),
11237 ];
11238 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11239 assert_eq!(
11240 hits, 1,
11241 "None-classification: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
11242 );
11243 // Authored classification.
11244 for populated in SubstrateType::ALL {
11245 let mut classification = Classification::gate_compute();
11246 classification.substrate = populated;
11247 let mut eph = empty_ephemeral();
11248 eph.classification = Some(classification);
11249 let buckets = [
11250 eph.substrate_is_resource(),
11251 eph.substrate_is_policy(),
11252 eph.substrate_is_telemetry(),
11253 ];
11254 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11255 assert_eq!(
11256 hits, 1,
11257 "authored substrate={populated:?}: probes {buckets:?} — exactly one must be true (three-way XOR partition violated)",
11258 );
11259 }
11260 }
11261
11262 // ── EphemeralSpec::calm_is_monotone pins ─────────────────────────
11263 //
11264 // Fail-before-pass-after granularity: `calm_is_monotone` did not
11265 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11266 // the "can this ephemeral spec participate in gossip-only writes?"
11267 // question went through the antisymmetric
11268 // `!self.calm_requires_coordination()` or through
11269 // `.resolved_classification().calm.is_monotone()`. Post-lift the
11270 // TWELFTH derived-nullary-boolean peer on the ephemeral surface
11271 // (SECOND on the calm axis, closing that axis into a binary XOR
11272 // partition on this surface) routes through the SAME
11273 // [`Self::resolved_classification`] resolver + the sibling
11274 // substrate primitive
11275 // [`crate::classification::Classification::calm_is_monotone`], so
11276 // the two-surface parity contract holds by construction, AND the
11277 // two calm-axis peers on this surface CLOSE the axis into the
11278 // FULL binary XOR partition contract via
11279 // `ephemeral_calm_probes_form_binary_xor_partition_over_all`.
11280
11281 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11282 /// [`Classification`] carries a specific
11283 /// [`crate::classification::CalmClassification`] variant answers
11284 /// [`Self::calm_is_monotone`] matching the closed set's own
11285 /// [`crate::classification::CalmClassification::is_monotone`]
11286 /// truth table. Sweep
11287 /// [`crate::classification::CalmClassification::ALL`] so a
11288 /// regression that (a) hard-coded the body to a fixed answer,
11289 /// (b) inverted the projection, or (c) crossed the wires with
11290 /// the sibling
11291 /// [`crate::classification::CalmClassification::requires_coordination`]
11292 /// projection fails HERE at the substrate primitive before
11293 /// drifting through the `monotone-calm` fixed tag or the peer
11294 /// point surface.
11295 #[test]
11296 fn calm_is_monotone_returns_calm_projection_per_kind() {
11297 for populated in CalmClassification::ALL {
11298 let mut classification = Classification::gate_compute();
11299 classification.calm = populated;
11300 let mut spec = empty_ephemeral();
11301 spec.classification = Some(classification);
11302 assert_eq!(
11303 spec.calm_is_monotone(),
11304 populated.is_monotone(),
11305 "authored calm={populated:?}: calm_is_monotone() drift",
11306 );
11307 }
11308 }
11309
11310 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11311 /// with `classification: None` routes through the
11312 /// [`Self::resolved_classification`] resolver's substrate default
11313 /// [`Classification::gate_compute`], which carries
11314 /// [`crate::classification::CalmClassification::default = Monotone`]
11315 /// via `#[default]`, and
11316 /// [`crate::classification::CalmClassification::Monotone::is_monotone`]
11317 /// projects `true`, so [`Self::calm_is_monotone`] returns
11318 /// `true`. Pins the resolver's default-arm short-circuit through
11319 /// TWO layers of `Default` ([`Classification::gate_compute`] →
11320 /// [`crate::classification::CalmClassification::default`])
11321 /// reaching this derived-nullary predicate. Mirror-inverted from
11322 /// the sibling
11323 /// `calm_requires_coordination_probes_false_on_absent_classification`
11324 /// (both walk the SAME defaulted `calm` field, so
11325 /// `requires_coordination = false` ⇒ `is_monotone = true` on the
11326 /// closed set's disjoint XOR partition). Guarantees every
11327 /// unadorned `(defephemeral …)` reads as gossip-eligible under
11328 /// the positive CALM framing.
11329 #[test]
11330 fn calm_is_monotone_probes_true_on_absent_classification() {
11331 let spec = empty_ephemeral();
11332 assert!(spec.classification.is_none());
11333 assert!(
11334 spec.calm_is_monotone(),
11335 "absent classification (defaults to gate_compute, calm=Monotone → is_monotone=true)",
11336 );
11337 }
11338
11339 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11340 /// identically through [`Self::calm_is_monotone`] AND through
11341 /// `<eph.clone().into::<ProcessSpec>>().classification.calm_is_monotone()`
11342 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11343 /// classification, `Some(_)` classification on every
11344 /// [`crate::classification::CalmClassification::ALL`] variant) so
11345 /// a future regression on either side of the resolver fails HERE
11346 /// at the parity boundary. Byte-for-byte peer of
11347 /// `calm_requires_coordination_matches_point_peer_through_lowered_classification`
11348 /// on the SAME closed-set axis via the antisymmetric projection.
11349 #[test]
11350 fn calm_is_monotone_matches_point_peer_through_lowered_classification() {
11351 // Absent classification.
11352 let eph = empty_ephemeral();
11353 let lowered: ProcessSpec = eph.clone().into();
11354 assert_eq!(
11355 eph.calm_is_monotone(),
11356 lowered.classification.calm_is_monotone(),
11357 "None-classification parity drift",
11358 );
11359 // Authored classification.
11360 for populated in CalmClassification::ALL {
11361 let mut classification = Classification::gate_compute();
11362 classification.calm = populated;
11363 let mut eph = empty_ephemeral();
11364 eph.classification = Some(classification);
11365 let lowered: ProcessSpec = eph.clone().into();
11366 assert_eq!(
11367 eph.calm_is_monotone(),
11368 lowered.classification.calm_is_monotone(),
11369 "authored calm={populated:?}: parity drift",
11370 );
11371 }
11372 }
11373
11374 /// MUTEX pin — [`Self::calm_requires_coordination`] AND
11375 /// [`Self::calm_is_monotone`] are NEVER simultaneously true for
11376 /// ANY [`EphemeralSpec`] (authored or defaulted). FIRST
11377 /// ephemeral-surface `calm`-axis corner-peer MUTEX pin — the
11378 /// calm axis's counterpart to the sibling substrate-axis
11379 /// `ephemeral_substrate_is_resource_and_substrate_is_policy_are_mutex_over_all`
11380 /// on a binary (rather than ternary) closed set.
11381 #[test]
11382 fn ephemeral_calm_requires_coordination_and_calm_is_monotone_are_mutex_over_all() {
11383 // Absent classification.
11384 let eph = empty_ephemeral();
11385 assert!(
11386 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
11387 "None-classification: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
11388 );
11389 // Authored classification.
11390 for populated in CalmClassification::ALL {
11391 let mut classification = Classification::gate_compute();
11392 classification.calm = populated;
11393 let mut eph = empty_ephemeral();
11394 eph.classification = Some(classification);
11395 assert!(
11396 !(eph.calm_requires_coordination() && eph.calm_is_monotone()),
11397 "authored calm={populated:?}: calm_requires_coordination AND calm_is_monotone both true (mutex violated)",
11398 );
11399 }
11400 }
11401
11402 /// BINARY XOR PARTITION pin — for the absent-classification
11403 /// baseline AND every
11404 /// [`crate::classification::CalmClassification::ALL`] variant,
11405 /// EXACTLY ONE of [`Self::calm_is_monotone`] and
11406 /// [`Self::calm_requires_coordination`] returns `true`. CLOSES
11407 /// the calm-axis MUTEX pin
11408 /// (`calm_requires_coordination ⇒ ¬calm_is_monotone`) into the
11409 /// FULL binary XOR partition contract on the ephemeral surface
11410 /// — the resolver-hop peer of the parent-composed
11411 /// `classification_calm_probes_form_binary_xor_partition_over_all`
11412 /// test. Binary counterpart of the ternary XOR partitions sealed
11413 /// on the sibling `point_type` and `substrate` axes by
11414 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11415 /// and
11416 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11417 /// Guarantees the absent-classification case lands in the
11418 /// monotone bucket (`gate_compute` → CalmClassification::Monotone
11419 /// → is_monotone = true), so every unadorned `(defephemeral …)`
11420 /// audits under a definite non-empty CALM bucket.
11421 #[test]
11422 fn ephemeral_calm_probes_form_binary_xor_partition_over_all() {
11423 // Absent classification.
11424 let eph = empty_ephemeral();
11425 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
11426 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11427 assert_eq!(
11428 hits, 1,
11429 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11430 );
11431 // Authored classification.
11432 for populated in CalmClassification::ALL {
11433 let mut classification = Classification::gate_compute();
11434 classification.calm = populated;
11435 let mut eph = empty_ephemeral();
11436 eph.classification = Some(classification);
11437 let buckets = [eph.calm_is_monotone(), eph.calm_requires_coordination()];
11438 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11439 assert_eq!(
11440 hits, 1,
11441 "authored calm={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11442 );
11443 }
11444 }
11445
11446 // ── EphemeralSpec::data_is_public pins ───────────────────────────
11447 //
11448 // Fail-before-pass-after granularity: `data_is_public` did not
11449 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11450 // the "is this ephemeral spec's dataset publicly distributable?"
11451 // question went through the antisymmetric
11452 // `!self.data_is_restricted()` or through
11453 // `.resolved_classification().data_classification.is_public()`.
11454 // Post-lift the THIRTEENTH derived-nullary-boolean peer on the
11455 // ephemeral surface (THIRD on the data axis, closing that axis
11456 // into a binary XOR partition on this surface) routes through the
11457 // SAME [`Self::resolved_classification`] resolver + the sibling
11458 // substrate primitive
11459 // [`crate::classification::Classification::data_is_public`], so
11460 // the two-surface parity contract holds by construction, AND the
11461 // two-way public/restricted split on this surface CLOSES the
11462 // data axis into the FULL binary XOR partition contract via
11463 // `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11464
11465 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11466 /// [`Classification`] carries a specific
11467 /// [`crate::classification::DataClassification`] variant answers
11468 /// [`Self::data_is_public`] matching the closed set's own
11469 /// [`crate::classification::DataClassification::is_public`] truth
11470 /// table. Sweep
11471 /// [`crate::classification::DataClassification::ALL`] so a
11472 /// regression that (a) hard-coded the body to a fixed answer,
11473 /// (b) inverted the projection, or (c) crossed the wires with
11474 /// the sibling
11475 /// [`crate::classification::DataClassification::is_restricted`]
11476 /// projection fails HERE at the substrate primitive before
11477 /// drifting through the `public-data` fixed tag or the peer
11478 /// point surface.
11479 #[test]
11480 fn data_is_public_returns_data_projection_per_kind() {
11481 for populated in DataClassification::ALL {
11482 let mut classification = Classification::gate_compute();
11483 classification.data_classification = populated;
11484 let mut spec = empty_ephemeral();
11485 spec.classification = Some(classification);
11486 assert_eq!(
11487 spec.data_is_public(),
11488 populated.is_public(),
11489 "authored data_classification={populated:?}: data_is_public() drift",
11490 );
11491 }
11492 }
11493
11494 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11495 /// with `classification: None` routes through the
11496 /// [`Self::resolved_classification`] resolver's substrate default
11497 /// [`Classification::gate_compute`], which carries
11498 /// [`crate::classification::DataClassification::default = Internal`]
11499 /// via `#[default]`, and
11500 /// [`crate::classification::DataClassification::Internal::is_public`]
11501 /// projects `false`, so [`Self::data_is_public`] returns `false`.
11502 /// Pins the resolver's default-arm short-circuit through TWO
11503 /// layers of `Default` ([`Classification::gate_compute`] →
11504 /// [`crate::classification::DataClassification::default`])
11505 /// reaching this derived-nullary predicate. Mirror-inverted from
11506 /// the sibling
11507 /// `data_is_restricted_probes_true_on_absent_classification`
11508 /// (both walk the SAME defaulted `data_classification` field, so
11509 /// `is_restricted = true` ⇒ `is_public = false` on the closed
11510 /// set's disjoint XOR partition). Guarantees every unadorned
11511 /// `(defephemeral …)` audits under the access-controlled default
11512 /// rather than silently promoting an unadorned dataset onto the
11513 /// freely-distributable path.
11514 #[test]
11515 fn data_is_public_probes_false_on_absent_classification() {
11516 let spec = empty_ephemeral();
11517 assert!(spec.classification.is_none());
11518 assert!(
11519 !spec.data_is_public(),
11520 "absent classification (defaults to gate_compute, data_classification=Internal → is_public=false)",
11521 );
11522 }
11523
11524 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11525 /// identically through [`Self::data_is_public`] AND through
11526 /// `<eph.clone().into::<ProcessSpec>>().classification.data_is_public()`
11527 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11528 /// classification, `Some(_)` classification on every
11529 /// [`crate::classification::DataClassification::ALL`] variant) so
11530 /// a future regression on either side of the resolver fails HERE
11531 /// at the parity boundary. Byte-for-byte peer of
11532 /// `data_is_restricted_matches_point_peer_through_lowered_classification`
11533 /// on the SAME closed-set axis via the antisymmetric projection.
11534 #[test]
11535 fn data_is_public_matches_point_peer_through_lowered_classification() {
11536 // Absent classification.
11537 let eph = empty_ephemeral();
11538 let lowered: ProcessSpec = eph.clone().into();
11539 assert_eq!(
11540 eph.data_is_public(),
11541 lowered.classification.data_is_public(),
11542 "None-classification parity drift",
11543 );
11544 // Authored classification.
11545 for populated in DataClassification::ALL {
11546 let mut classification = Classification::gate_compute();
11547 classification.data_classification = populated;
11548 let mut eph = empty_ephemeral();
11549 eph.classification = Some(classification);
11550 let lowered: ProcessSpec = eph.clone().into();
11551 assert_eq!(
11552 eph.data_is_public(),
11553 lowered.classification.data_is_public(),
11554 "authored data_classification={populated:?}: parity drift",
11555 );
11556 }
11557 }
11558
11559 /// MUTEX pin — [`Self::data_is_regulated`] AND
11560 /// [`Self::data_is_public`] are NEVER simultaneously true for ANY
11561 /// [`EphemeralSpec`] (authored or defaulted). FIRST ephemeral-
11562 /// surface data-axis antisymmetric MUTEX pin against the
11563 /// positive-distribution framing: sealed on the closed set by
11564 /// `data_classification_regulated_implies_not_public` and lifted
11565 /// through the resolver hop as a substrate-wide contract on this
11566 /// surface.
11567 #[test]
11568 fn ephemeral_data_is_regulated_and_data_is_public_are_mutex_over_all() {
11569 // Absent classification.
11570 let eph = empty_ephemeral();
11571 assert!(
11572 !(eph.data_is_regulated() && eph.data_is_public()),
11573 "None-classification: data_is_regulated AND data_is_public both true (mutex violated)",
11574 );
11575 // Authored classification.
11576 for populated in DataClassification::ALL {
11577 let mut classification = Classification::gate_compute();
11578 classification.data_classification = populated;
11579 let mut eph = empty_ephemeral();
11580 eph.classification = Some(classification);
11581 assert!(
11582 !(eph.data_is_regulated() && eph.data_is_public()),
11583 "authored data_classification={populated:?}: data_is_regulated AND data_is_public both true (mutex violated)",
11584 );
11585 }
11586 }
11587
11588 /// BINARY XOR PARTITION pin — for the absent-classification
11589 /// baseline AND every
11590 /// [`crate::classification::DataClassification::ALL`] variant,
11591 /// EXACTLY ONE of [`Self::data_is_public`] and
11592 /// [`Self::data_is_restricted`] returns `true`. CLOSES the data-
11593 /// axis MUTEX pin (`data_is_regulated ⇒ ¬data_is_public`) into
11594 /// the FULL binary XOR partition contract on the ephemeral
11595 /// surface — the resolver-hop peer of the parent-composed
11596 /// `classification_data_probes_form_binary_xor_partition_over_all`
11597 /// test. Binary counterpart of the ternary XOR partitions sealed
11598 /// on the sibling `point_type` and `substrate` axes by
11599 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11600 /// and
11601 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`.
11602 /// Guarantees the absent-classification case lands in the
11603 /// access-controlled bucket (`gate_compute` →
11604 /// DataClassification::Internal → is_public = false,
11605 /// is_restricted = true), so every unadorned `(defephemeral …)`
11606 /// audits under a definite non-empty distribution bucket.
11607 #[test]
11608 fn ephemeral_data_probes_form_binary_xor_partition_over_all() {
11609 // Absent classification.
11610 let eph = empty_ephemeral();
11611 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11612 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11613 assert_eq!(
11614 hits, 1,
11615 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11616 );
11617 // Authored classification.
11618 for populated in DataClassification::ALL {
11619 let mut classification = Classification::gate_compute();
11620 classification.data_classification = populated;
11621 let mut eph = empty_ephemeral();
11622 eph.classification = Some(classification);
11623 let buckets = [eph.data_is_public(), eph.data_is_restricted()];
11624 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11625 assert_eq!(
11626 hits, 1,
11627 "authored data_classification={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11628 );
11629 }
11630 }
11631
11632 // ── EphemeralSpec::direction_prefers_lower pins ─────────────────
11633 //
11634 // Fail-before-pass-after granularity: `direction_prefers_lower`
11635 // did not exist pre-lift on `impl EphemeralSpec` — every consumer
11636 // walking the "does this ephemeral spec's rate-window evaluator
11637 // treat decreasing values as improvement?" question went through
11638 // `.resolved_classification().horizon.direction.unwrap_or_default().prefers_lower()`.
11639 // Post-lift the FOURTEENTH derived-nullary-boolean peer on the
11640 // ephemeral surface (FIRST on the optimization-direction axis,
11641 // opening the SIXTH classification axis into the fixed-tag algebra)
11642 // routes through the SAME [`Self::resolved_classification`] resolver
11643 // + the sibling substrate primitive
11644 // [`crate::classification::Classification::direction_prefers_lower`],
11645 // so the two-surface parity contract holds by construction.
11646
11647 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11648 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11649 /// answers [`Self::direction_prefers_lower`] matching the closed
11650 /// set's own
11651 /// [`crate::classification::OptimizationDirection::prefers_lower`]
11652 /// truth table. Sweep
11653 /// [`crate::classification::OptimizationDirection::ALL`] so a
11654 /// regression that (a) hard-coded the body to a fixed answer,
11655 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11656 /// hop, or (d) crossed the wires with a sibling classification-axis
11657 /// probe fails HERE at the substrate primitive before drifting
11658 /// through the `prefers-lower-direction` fixed tag or the peer
11659 /// point surface.
11660 #[test]
11661 fn direction_prefers_lower_returns_direction_projection_per_kind() {
11662 for populated in OptimizationDirection::ALL {
11663 let mut classification = Classification::gate_compute();
11664 classification.horizon.direction = Some(populated);
11665 let mut spec = empty_ephemeral();
11666 spec.classification = Some(classification);
11667 assert_eq!(
11668 spec.direction_prefers_lower(),
11669 populated.prefers_lower(),
11670 "authored horizon.direction={populated:?}: direction_prefers_lower() drift",
11671 );
11672 }
11673 }
11674
11675 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11676 /// with `classification: None` routes through the
11677 /// [`Self::resolved_classification`] resolver's substrate default
11678 /// [`Classification::gate_compute`], which carries
11679 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11680 /// so `unwrap_or_default()` defaults to
11681 /// [`crate::classification::OptimizationDirection::Minimize`] via
11682 /// `#[default]`, and `Minimize.prefers_lower()` projects `true`,
11683 /// so [`Self::direction_prefers_lower`] returns `true`. Pins the
11684 /// resolver's default-arm short-circuit through THREE layers of
11685 /// `Default` ([`Classification::gate_compute`] →
11686 /// [`crate::classification::Horizon::default`] with `direction: None`
11687 /// → [`crate::classification::OptimizationDirection::default =
11688 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11689 /// every unadorned `(defephemeral …)` reads under the lower-is-
11690 /// better polarity default (safe under the asymptotic-health
11691 /// rate-window evaluator convention: an operator must deliberately
11692 /// opt into Maximize polarity).
11693 #[test]
11694 fn direction_prefers_lower_probes_true_on_absent_classification() {
11695 let spec = empty_ephemeral();
11696 assert!(spec.classification.is_none());
11697 assert!(
11698 spec.direction_prefers_lower(),
11699 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_lower=true)",
11700 );
11701 }
11702
11703 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11704 /// identically through [`Self::direction_prefers_lower`] AND through
11705 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_lower()`
11706 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11707 /// classification, `Some(_)` classification on every
11708 /// [`crate::classification::OptimizationDirection::ALL`] variant) so
11709 /// a future regression on either side of the resolver fails HERE
11710 /// at the parity boundary. Byte-for-byte peer of
11711 /// `calm_is_monotone_matches_point_peer_through_lowered_classification`
11712 /// on the analog closed-set axis via the same resolver-hop shape.
11713 #[test]
11714 fn direction_prefers_lower_matches_point_peer_through_lowered_classification() {
11715 // Absent classification.
11716 let eph = empty_ephemeral();
11717 let lowered: ProcessSpec = eph.clone().into();
11718 assert_eq!(
11719 eph.direction_prefers_lower(),
11720 lowered.classification.direction_prefers_lower(),
11721 "None-classification parity drift",
11722 );
11723 // Authored classification.
11724 for populated in OptimizationDirection::ALL {
11725 let mut classification = Classification::gate_compute();
11726 classification.horizon.direction = Some(populated);
11727 let mut eph = empty_ephemeral();
11728 eph.classification = Some(classification);
11729 let lowered: ProcessSpec = eph.clone().into();
11730 assert_eq!(
11731 eph.direction_prefers_lower(),
11732 lowered.classification.direction_prefers_lower(),
11733 "authored horizon.direction={populated:?}: parity drift",
11734 );
11735 }
11736 }
11737
11738 // ── EphemeralSpec::direction_prefers_higher pins ────────────────
11739 //
11740 // Fail-before-pass-after granularity: `direction_prefers_higher`
11741 // did not exist pre-lift on `impl EphemeralSpec` — the positive
11742 // higher-is-better framing peer of
11743 // [`Self::direction_prefers_lower`] had no ephemeral-surface
11744 // substrate owner. Post-lift the FIFTEENTH derived-nullary-boolean
11745 // peer on the ephemeral surface (SECOND on the optimization-
11746 // direction axis, CLOSING the SIXTH classification axis into a
11747 // binary XOR partition on this surface) routes through the SAME
11748 // [`Self::resolved_classification`] resolver + the sibling
11749 // substrate primitive
11750 // [`crate::classification::Classification::direction_prefers_higher`],
11751 // so the two-surface parity contract holds by construction, AND
11752 // the two-way lower/higher split on this surface CLOSES the
11753 // optimization-direction axis into the FULL binary XOR partition
11754 // contract via
11755 // `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
11756
11757 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11758 /// [`Classification`] carries `Some(variant)` on `horizon.direction`
11759 /// answers [`Self::direction_prefers_higher`] matching the closed
11760 /// set's own
11761 /// [`crate::classification::OptimizationDirection::prefers_higher`]
11762 /// truth table. Sweep
11763 /// [`crate::classification::OptimizationDirection::ALL`] so a
11764 /// regression that (a) hard-coded the body to a fixed answer,
11765 /// (b) inverted the projection, (c) dropped the `.unwrap_or_default()`
11766 /// hop, or (d) crossed the wires with a sibling classification-
11767 /// axis probe fails HERE at the substrate primitive before
11768 /// drifting through the `prefers-higher-direction` fixed tag or
11769 /// the peer point surface.
11770 #[test]
11771 fn direction_prefers_higher_returns_direction_projection_per_kind() {
11772 for populated in OptimizationDirection::ALL {
11773 let mut classification = Classification::gate_compute();
11774 classification.horizon.direction = Some(populated);
11775 let mut spec = empty_ephemeral();
11776 spec.classification = Some(classification);
11777 assert_eq!(
11778 spec.direction_prefers_higher(),
11779 populated.prefers_higher(),
11780 "authored horizon.direction={populated:?}: direction_prefers_higher() drift",
11781 );
11782 }
11783 }
11784
11785 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11786 /// with `classification: None` routes through the
11787 /// [`Self::resolved_classification`] resolver's substrate default
11788 /// [`Classification::gate_compute`], which carries
11789 /// `horizon: Horizon::default()` whose `direction` field is `None`,
11790 /// so `unwrap_or_default()` defaults to
11791 /// [`crate::classification::OptimizationDirection::Minimize`] via
11792 /// `#[default]`, and `Minimize.prefers_higher()` projects `false`,
11793 /// so [`Self::direction_prefers_higher`] returns `false`. Pins
11794 /// the resolver's default-arm short-circuit through THREE layers
11795 /// of `Default` ([`Classification::gate_compute`] →
11796 /// [`crate::classification::Horizon::default`] with `direction:
11797 /// None` → [`crate::classification::OptimizationDirection::default =
11798 /// Minimize`]) reaching this derived-nullary predicate. Guarantees
11799 /// every unadorned `(defephemeral …)` reads UNDER the lower-is-
11800 /// better polarity default (safe under the asymptotic-health
11801 /// rate-window evaluator convention: an operator must
11802 /// deliberately opt into Maximize polarity). Mirror-inverted from
11803 /// the sibling `direction_prefers_lower_probes_true_on_absent_classification`
11804 /// baseline on the same resolver walk.
11805 #[test]
11806 fn direction_prefers_higher_probes_false_on_absent_classification() {
11807 let spec = empty_ephemeral();
11808 assert!(spec.classification.is_none());
11809 assert!(
11810 !spec.direction_prefers_higher(),
11811 "absent classification (defaults to gate_compute, horizon.direction=None → unwrap_or_default=Minimize → prefers_higher=false)",
11812 );
11813 }
11814
11815 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11816 /// identically through [`Self::direction_prefers_higher`] AND
11817 /// through
11818 /// `<eph.clone().into::<ProcessSpec>>().classification.direction_prefers_higher()`
11819 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11820 /// classification, `Some(_)` classification on every
11821 /// [`crate::classification::OptimizationDirection::ALL`] variant)
11822 /// so a future regression on either side of the resolver fails
11823 /// HERE at the parity boundary. Byte-for-byte peer of
11824 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11825 /// on the antisymmetric closed-set arm via the same resolver-hop
11826 /// shape.
11827 #[test]
11828 fn direction_prefers_higher_matches_point_peer_through_lowered_classification() {
11829 // Absent classification.
11830 let eph = empty_ephemeral();
11831 let lowered: ProcessSpec = eph.clone().into();
11832 assert_eq!(
11833 eph.direction_prefers_higher(),
11834 lowered.classification.direction_prefers_higher(),
11835 "None-classification parity drift",
11836 );
11837 // Authored classification.
11838 for populated in OptimizationDirection::ALL {
11839 let mut classification = Classification::gate_compute();
11840 classification.horizon.direction = Some(populated);
11841 let mut eph = empty_ephemeral();
11842 eph.classification = Some(classification);
11843 let lowered: ProcessSpec = eph.clone().into();
11844 assert_eq!(
11845 eph.direction_prefers_higher(),
11846 lowered.classification.direction_prefers_higher(),
11847 "authored horizon.direction={populated:?}: parity drift",
11848 );
11849 }
11850 }
11851
11852 /// BINARY XOR PARTITION pin — for the absent-classification
11853 /// baseline AND every
11854 /// [`crate::classification::OptimizationDirection::ALL`] variant,
11855 /// EXACTLY ONE of [`Self::direction_prefers_lower`] and
11856 /// [`Self::direction_prefers_higher`] returns `true`. CLOSES the
11857 /// optimization-direction axis into the FULL binary XOR partition
11858 /// contract on the ephemeral surface — the resolver-hop peer of
11859 /// the parent-composed
11860 /// `classification_direction_probes_form_binary_xor_partition_over_all`
11861 /// test. Binary counterpart of the ternary XOR partitions sealed
11862 /// on the sibling `point_type` and `substrate` axes by
11863 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
11864 /// and
11865 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
11866 /// structural twin of the calm/data binary partitions
11867 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all` and
11868 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
11869 /// This pin is the SIXTH (and final) classification axis to reach
11870 /// the closed XOR partition landmark on the ephemeral resolver-
11871 /// hop surface — ALL SIX classification axes (horizon, calm,
11872 /// data, point, substrate, optimization-direction) now have
11873 /// their partitions closed on the ephemeral surface at this
11874 /// corner. Guarantees the absent-classification case lands in
11875 /// the definite lower-is-better bucket (`gate_compute` →
11876 /// Horizon::default → direction: None →
11877 /// OptimizationDirection::default = Minimize → prefers_lower =
11878 /// true, prefers_higher = false), so every unadorned
11879 /// `(defephemeral …)` audits under a definite non-empty polarity
11880 /// bucket.
11881 #[test]
11882 fn ephemeral_direction_probes_form_binary_xor_partition_over_all() {
11883 // Absent classification.
11884 let eph = empty_ephemeral();
11885 let buckets = [
11886 eph.direction_prefers_lower(),
11887 eph.direction_prefers_higher(),
11888 ];
11889 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11890 assert_eq!(
11891 hits, 1,
11892 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11893 );
11894 // Authored classification.
11895 for populated in OptimizationDirection::ALL {
11896 let mut classification = Classification::gate_compute();
11897 classification.horizon.direction = Some(populated);
11898 let mut eph = empty_ephemeral();
11899 eph.classification = Some(classification);
11900 let buckets = [
11901 eph.direction_prefers_lower(),
11902 eph.direction_prefers_higher(),
11903 ];
11904 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
11905 assert_eq!(
11906 hits, 1,
11907 "authored horizon.direction={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
11908 );
11909 }
11910 }
11911
11912 // ── EphemeralSpec::input_arity_is_one pins ──────────────────────
11913 //
11914 // Fail-before-pass-after granularity: `input_arity_is_one` did not
11915 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
11916 // the "does this ephemeral spec's DAG-composition input port
11917 // accept a single upstream edge?" question went through
11918 // `.resolved_classification().point_type.input_arity().is_one()`.
11919 // Post-lift the SIXTEENTH derived-nullary-boolean peer on the
11920 // ephemeral surface (FIRST on the input-arity axis, opening the
11921 // SEVENTH classification axis into the fixed-tag algebra + the
11922 // derived-typed-projection stratum on this surface for the first
11923 // time) routes through the SAME [`Self::resolved_classification`]
11924 // resolver + the sibling substrate primitive
11925 // [`crate::classification::Classification::input_arity_is_one`],
11926 // so the two-surface parity contract holds by construction.
11927
11928 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
11929 /// [`Classification`] carries `point_type: kind` answers
11930 /// [`Self::input_arity_is_one`] matching the closed set's own
11931 /// [`crate::classification::ConvergencePointType::input_arity`]
11932 /// truth table projected through [`Arity::is_one`]. Sweep
11933 /// [`crate::classification::ConvergencePointType::ALL`] so a
11934 /// regression that (a) hard-coded the body to a fixed answer,
11935 /// (b) inverted the projection, (c) dropped the resolver hop, or
11936 /// (d) crossed the wires with the sibling `output_arity`
11937 /// projection (which disagrees on six of eight variants) fails
11938 /// HERE at the substrate primitive before drifting through the
11939 /// future `single-input-arity` fixed tag or the peer point
11940 /// surface.
11941 #[test]
11942 fn input_arity_is_one_returns_input_arity_projection_per_kind() {
11943 for populated in ConvergencePointType::ALL {
11944 let mut classification = Classification::gate_compute();
11945 classification.point_type = populated;
11946 let mut spec = empty_ephemeral();
11947 spec.classification = Some(classification);
11948 assert_eq!(
11949 spec.input_arity_is_one(),
11950 populated.input_arity().is_one(),
11951 "authored point_type={populated:?}: input_arity_is_one() drift",
11952 );
11953 }
11954 }
11955
11956 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
11957 /// with `classification: None` routes through the
11958 /// [`Self::resolved_classification`] resolver's substrate default
11959 /// [`Classification::gate_compute`], which carries `point_type:
11960 /// Gate` and `Gate.input_arity() = Many`, so
11961 /// [`Self::input_arity_is_one`] returns `false`. Pins the
11962 /// resolver's default-arm short-circuit reaching this derived-
11963 /// nullary predicate — every unadorned `(defephemeral …)` lands
11964 /// in the multi-input bucket under the substrate default. Mirror-
11965 /// inverted from the sibling `input_arity_is_many` baseline on
11966 /// the same resolver walk (the XOR partition forces exactly one
11967 /// bucket per baseline).
11968 #[test]
11969 fn input_arity_is_one_probes_false_on_absent_classification() {
11970 let spec = empty_ephemeral();
11971 assert!(spec.classification.is_none());
11972 assert!(
11973 !spec.input_arity_is_one(),
11974 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_one=false)",
11975 );
11976 }
11977
11978 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
11979 /// identically through [`Self::input_arity_is_one`] AND through
11980 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_one()`
11981 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
11982 /// classification, `Some(_)` classification on every
11983 /// [`crate::classification::ConvergencePointType::ALL`] variant)
11984 /// so a future regression on either side of the resolver fails
11985 /// HERE at the parity boundary. Byte-for-byte peer of
11986 /// `direction_prefers_lower_matches_point_peer_through_lowered_classification`
11987 /// on the same resolver-hop shape.
11988 #[test]
11989 fn input_arity_is_one_matches_point_peer_through_lowered_classification() {
11990 // Absent classification.
11991 let eph = empty_ephemeral();
11992 let lowered: ProcessSpec = eph.clone().into();
11993 assert_eq!(
11994 eph.input_arity_is_one(),
11995 lowered.classification.input_arity_is_one(),
11996 "None-classification parity drift",
11997 );
11998 // Authored classification.
11999 for populated in ConvergencePointType::ALL {
12000 let mut classification = Classification::gate_compute();
12001 classification.point_type = populated;
12002 let mut eph = empty_ephemeral();
12003 eph.classification = Some(classification);
12004 let lowered: ProcessSpec = eph.clone().into();
12005 assert_eq!(
12006 eph.input_arity_is_one(),
12007 lowered.classification.input_arity_is_one(),
12008 "authored point_type={populated:?}: parity drift",
12009 );
12010 }
12011 }
12012
12013 // ── EphemeralSpec::input_arity_is_many pins ─────────────────────
12014 //
12015 // Fail-before-pass-after granularity: `input_arity_is_many` did
12016 // not exist pre-lift on `impl EphemeralSpec` — the multi-input
12017 // framing peer of [`Self::input_arity_is_one`] had no ephemeral-
12018 // surface substrate owner. Post-lift the SEVENTEENTH derived-
12019 // nullary-boolean peer on the ephemeral surface (SECOND on the
12020 // input-arity axis, CLOSING the SEVENTH classification axis into
12021 // a binary XOR partition on this surface) routes through the SAME
12022 // [`Self::resolved_classification`] resolver + the sibling
12023 // substrate primitive
12024 // [`crate::classification::Classification::input_arity_is_many`],
12025 // so the two-surface parity contract holds by construction, AND
12026 // the two-way single/many split on this surface CLOSES the
12027 // input-arity axis into the FULL binary XOR partition contract
12028 // via `ephemeral_input_arity_probes_form_binary_xor_partition_over_all`.
12029
12030 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12031 /// [`Classification`] carries `point_type: kind` answers
12032 /// [`Self::input_arity_is_many`] matching the closed set's own
12033 /// [`crate::classification::ConvergencePointType::input_arity`]
12034 /// truth table projected through [`Arity::is_many`]. Sweep
12035 /// [`crate::classification::ConvergencePointType::ALL`] so a
12036 /// regression that (a) hard-coded the body to a fixed answer,
12037 /// (b) inverted the projection, (c) dropped the resolver hop, or
12038 /// (d) crossed the wires with the sibling `output_arity`
12039 /// projection fails HERE at the substrate primitive before
12040 /// drifting through the future `multi-input-arity` fixed tag or
12041 /// the peer point surface.
12042 #[test]
12043 fn input_arity_is_many_returns_input_arity_projection_per_kind() {
12044 for populated in ConvergencePointType::ALL {
12045 let mut classification = Classification::gate_compute();
12046 classification.point_type = populated;
12047 let mut spec = empty_ephemeral();
12048 spec.classification = Some(classification);
12049 assert_eq!(
12050 spec.input_arity_is_many(),
12051 populated.input_arity().is_many(),
12052 "authored point_type={populated:?}: input_arity_is_many() drift",
12053 );
12054 }
12055 }
12056
12057 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12058 /// with `classification: None` routes through the
12059 /// [`Self::resolved_classification`] resolver's substrate default
12060 /// [`Classification::gate_compute`], which carries `point_type:
12061 /// Gate` and `Gate.input_arity() = Many`, so
12062 /// [`Self::input_arity_is_many`] returns `true`. Pins the
12063 /// resolver's default-arm short-circuit reaching this derived-
12064 /// nullary predicate — every unadorned `(defephemeral …)` lands
12065 /// in the multi-input bucket under the substrate default. Mirror-
12066 /// inverted from the sibling `input_arity_is_one` baseline on
12067 /// the same resolver walk (the XOR partition forces exactly one
12068 /// bucket per baseline).
12069 #[test]
12070 fn input_arity_is_many_probes_true_on_absent_classification() {
12071 let spec = empty_ephemeral();
12072 assert!(spec.classification.is_none());
12073 assert!(
12074 spec.input_arity_is_many(),
12075 "absent classification (defaults to gate_compute, point_type=Gate → input_arity=Many → is_many=true)",
12076 );
12077 }
12078
12079 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12080 /// identically through [`Self::input_arity_is_many`] AND through
12081 /// `<eph.clone().into::<ProcessSpec>>().classification.input_arity_is_many()`
12082 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12083 /// classification, `Some(_)` classification on every
12084 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12085 /// so a future regression on either side of the resolver fails
12086 /// HERE at the parity boundary. Byte-for-byte peer of
12087 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
12088 /// on the antisymmetric closed-set arm via the same resolver-hop
12089 /// shape.
12090 #[test]
12091 fn input_arity_is_many_matches_point_peer_through_lowered_classification() {
12092 // Absent classification.
12093 let eph = empty_ephemeral();
12094 let lowered: ProcessSpec = eph.clone().into();
12095 assert_eq!(
12096 eph.input_arity_is_many(),
12097 lowered.classification.input_arity_is_many(),
12098 "None-classification parity drift",
12099 );
12100 // Authored classification.
12101 for populated in ConvergencePointType::ALL {
12102 let mut classification = Classification::gate_compute();
12103 classification.point_type = populated;
12104 let mut eph = empty_ephemeral();
12105 eph.classification = Some(classification);
12106 let lowered: ProcessSpec = eph.clone().into();
12107 assert_eq!(
12108 eph.input_arity_is_many(),
12109 lowered.classification.input_arity_is_many(),
12110 "authored point_type={populated:?}: parity drift",
12111 );
12112 }
12113 }
12114
12115 /// BINARY XOR PARTITION pin — for the absent-classification
12116 /// baseline AND every
12117 /// [`crate::classification::ConvergencePointType::ALL`] variant,
12118 /// EXACTLY ONE of [`Self::input_arity_is_one`] and
12119 /// [`Self::input_arity_is_many`] returns `true`. CLOSES the
12120 /// input-arity axis into the FULL binary XOR partition contract
12121 /// on the ephemeral surface — the resolver-hop peer of the
12122 /// parent-composed
12123 /// `classification_input_arity_probes_form_binary_xor_partition_over_all`
12124 /// test. Binary counterpart of the ternary XOR partitions sealed
12125 /// on the sibling `point_type` and `substrate` axes by
12126 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12127 /// and
12128 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12129 /// structural twin of the calm/data/direction binary partitions
12130 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`,
12131 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`,
12132 /// and
12133 /// `ephemeral_direction_probes_form_binary_xor_partition_over_all`.
12134 /// This pin is the SEVENTH classification axis to reach the
12135 /// closed XOR partition landmark on the ephemeral resolver-hop
12136 /// surface — the FIRST closed axis on the derived-typed-
12137 /// projection stratum of this surface, opening the stratum beyond
12138 /// the six stored classification slots. Guarantees the absent-
12139 /// classification case lands in the definite multi-input bucket
12140 /// (`gate_compute` → point_type=Gate → input_arity=Many →
12141 /// is_one=false, is_many=true), so every unadorned
12142 /// `(defephemeral …)` audits under a definite non-empty input-
12143 /// arity bucket.
12144 #[test]
12145 fn ephemeral_input_arity_probes_form_binary_xor_partition_over_all() {
12146 // Absent classification.
12147 let eph = empty_ephemeral();
12148 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
12149 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12150 assert_eq!(
12151 hits, 1,
12152 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12153 );
12154 // Authored classification.
12155 for populated in ConvergencePointType::ALL {
12156 let mut classification = Classification::gate_compute();
12157 classification.point_type = populated;
12158 let mut eph = empty_ephemeral();
12159 eph.classification = Some(classification);
12160 let buckets = [eph.input_arity_is_one(), eph.input_arity_is_many()];
12161 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12162 assert_eq!(
12163 hits, 1,
12164 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12165 );
12166 }
12167 }
12168
12169 // ── EphemeralSpec::output_arity_is_one pins ─────────────────────
12170 //
12171 // Fail-before-pass-after granularity: `output_arity_is_one` did not
12172 // exist pre-lift on `impl EphemeralSpec` — every consumer walking
12173 // the "does this ephemeral spec's DAG-composition output port emit
12174 // to a single downstream edge?" question went through
12175 // `.resolved_classification().point_type.output_arity().is_one()`.
12176 // Post-lift the EIGHTEENTH derived-nullary-boolean peer on the
12177 // ephemeral surface (FIRST on the output-arity axis, opening the
12178 // EIGHTH classification axis into the fixed-tag algebra + the
12179 // SECOND peer on the derived-typed-projection stratum after
12180 // [`Self::input_arity_is_one`]) routes through the SAME
12181 // [`Self::resolved_classification`] resolver + the sibling
12182 // substrate primitive
12183 // [`crate::classification::Classification::output_arity_is_one`],
12184 // so the two-surface parity contract holds by construction.
12185
12186 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12187 /// [`Classification`] carries `point_type: kind` answers
12188 /// [`Self::output_arity_is_one`] matching the closed set's own
12189 /// [`crate::classification::ConvergencePointType::output_arity`]
12190 /// truth table projected through [`Arity::is_one`]. Sweep
12191 /// [`crate::classification::ConvergencePointType::ALL`] so a
12192 /// regression that (a) hard-coded the body to a fixed answer,
12193 /// (b) inverted the projection, (c) dropped the resolver hop, or
12194 /// (d) crossed the wires with the sibling `input_arity`
12195 /// projection (which disagrees on six of eight variants) fails
12196 /// HERE at the substrate primitive before drifting through the
12197 /// future `single-output-arity` fixed tag or the peer point
12198 /// surface.
12199 #[test]
12200 fn output_arity_is_one_returns_output_arity_projection_per_kind() {
12201 for populated in ConvergencePointType::ALL {
12202 let mut classification = Classification::gate_compute();
12203 classification.point_type = populated;
12204 let mut spec = empty_ephemeral();
12205 spec.classification = Some(classification);
12206 assert_eq!(
12207 spec.output_arity_is_one(),
12208 populated.output_arity().is_one(),
12209 "authored point_type={populated:?}: output_arity_is_one() drift",
12210 );
12211 }
12212 }
12213
12214 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12215 /// with `classification: None` routes through the
12216 /// [`Self::resolved_classification`] resolver's substrate default
12217 /// [`Classification::gate_compute`], which carries `point_type:
12218 /// Gate` and `Gate.output_arity() = One`, so
12219 /// [`Self::output_arity_is_one`] returns `true`. Pins the
12220 /// resolver's default-arm short-circuit reaching this derived-
12221 /// nullary predicate — every unadorned `(defephemeral …)` lands
12222 /// in the single-output bucket under the substrate default.
12223 /// Mirror-inverted from the sibling `output_arity_is_many`
12224 /// baseline on the same resolver walk (the XOR partition forces
12225 /// exactly one bucket per baseline). Note the workspace-baseline
12226 /// answer FLIPS between the input-arity and output-arity axes on
12227 /// the exact same absent-classification baseline: the input-arity
12228 /// sibling `input_arity_is_one` answers `false`, but this
12229 /// output-arity peer answers `true` — direct evidence at the
12230 /// resolver-hop layer that the two axes carve the closed set
12231 /// into structurally different partitions.
12232 #[test]
12233 fn output_arity_is_one_probes_true_on_absent_classification() {
12234 let spec = empty_ephemeral();
12235 assert!(spec.classification.is_none());
12236 assert!(
12237 spec.output_arity_is_one(),
12238 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_one=true)",
12239 );
12240 }
12241
12242 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12243 /// identically through [`Self::output_arity_is_one`] AND through
12244 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_one()`
12245 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12246 /// classification, `Some(_)` classification on every
12247 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12248 /// so a future regression on either side of the resolver fails
12249 /// HERE at the parity boundary. Byte-for-byte peer of
12250 /// `input_arity_is_one_matches_point_peer_through_lowered_classification`
12251 /// on the sibling output-arity projection via the same
12252 /// resolver-hop shape.
12253 #[test]
12254 fn output_arity_is_one_matches_point_peer_through_lowered_classification() {
12255 // Absent classification.
12256 let eph = empty_ephemeral();
12257 let lowered: ProcessSpec = eph.clone().into();
12258 assert_eq!(
12259 eph.output_arity_is_one(),
12260 lowered.classification.output_arity_is_one(),
12261 "None-classification parity drift",
12262 );
12263 // Authored classification.
12264 for populated in ConvergencePointType::ALL {
12265 let mut classification = Classification::gate_compute();
12266 classification.point_type = populated;
12267 let mut eph = empty_ephemeral();
12268 eph.classification = Some(classification);
12269 let lowered: ProcessSpec = eph.clone().into();
12270 assert_eq!(
12271 eph.output_arity_is_one(),
12272 lowered.classification.output_arity_is_one(),
12273 "authored point_type={populated:?}: parity drift",
12274 );
12275 }
12276 }
12277
12278 // ── EphemeralSpec::output_arity_is_many pins ────────────────────
12279 //
12280 // Fail-before-pass-after granularity: `output_arity_is_many` did
12281 // not exist pre-lift on `impl EphemeralSpec` — the multi-output
12282 // framing peer of [`Self::output_arity_is_one`] had no ephemeral-
12283 // surface substrate owner. Post-lift the NINETEENTH derived-
12284 // nullary-boolean peer on the ephemeral surface (SECOND on the
12285 // output-arity axis, CLOSING the EIGHTH classification axis into
12286 // a binary XOR partition on this surface) routes through the SAME
12287 // [`Self::resolved_classification`] resolver + the sibling
12288 // substrate primitive
12289 // [`crate::classification::Classification::output_arity_is_many`],
12290 // so the two-surface parity contract holds by construction, AND
12291 // the two-way single/many split on this surface CLOSES the
12292 // output-arity axis into the FULL binary XOR partition contract
12293 // via `ephemeral_output_arity_probes_form_binary_xor_partition_over_all`,
12294 // completing the DAG-composition arity PAIR on the ephemeral
12295 // derived-typed-projection stratum.
12296
12297 /// PER-VARIANT pin — an [`EphemeralSpec`] whose authored
12298 /// [`Classification`] carries `point_type: kind` answers
12299 /// [`Self::output_arity_is_many`] matching the closed set's own
12300 /// [`crate::classification::ConvergencePointType::output_arity`]
12301 /// truth table projected through [`Arity::is_many`]. Sweep
12302 /// [`crate::classification::ConvergencePointType::ALL`] so a
12303 /// regression that (a) hard-coded the body to a fixed answer,
12304 /// (b) inverted the projection, (c) dropped the resolver hop, or
12305 /// (d) crossed the wires with the sibling `input_arity`
12306 /// projection fails HERE at the substrate primitive before
12307 /// drifting through the future `multi-output-arity` fixed tag or
12308 /// the peer point surface.
12309 #[test]
12310 fn output_arity_is_many_returns_output_arity_projection_per_kind() {
12311 for populated in ConvergencePointType::ALL {
12312 let mut classification = Classification::gate_compute();
12313 classification.point_type = populated;
12314 let mut spec = empty_ephemeral();
12315 spec.classification = Some(classification);
12316 assert_eq!(
12317 spec.output_arity_is_many(),
12318 populated.output_arity().is_many(),
12319 "authored point_type={populated:?}: output_arity_is_many() drift",
12320 );
12321 }
12322 }
12323
12324 /// ABSENT-CLASSIFICATION SHORT-CIRCUIT pin — an [`EphemeralSpec`]
12325 /// with `classification: None` routes through the
12326 /// [`Self::resolved_classification`] resolver's substrate default
12327 /// [`Classification::gate_compute`], which carries `point_type:
12328 /// Gate` and `Gate.output_arity() = One`, so
12329 /// [`Self::output_arity_is_many`] returns `false`. Pins the
12330 /// resolver's default-arm short-circuit reaching this derived-
12331 /// nullary predicate — every unadorned `(defephemeral …)` lands
12332 /// in the single-output bucket under the substrate default.
12333 /// Mirror-inverted from the sibling `output_arity_is_one`
12334 /// baseline on the same resolver walk (the XOR partition forces
12335 /// exactly one bucket per baseline).
12336 #[test]
12337 fn output_arity_is_many_probes_false_on_absent_classification() {
12338 let spec = empty_ephemeral();
12339 assert!(spec.classification.is_none());
12340 assert!(
12341 !spec.output_arity_is_many(),
12342 "absent classification (defaults to gate_compute, point_type=Gate → output_arity=One → is_many=false)",
12343 );
12344 }
12345
12346 /// TWO-SURFACE PARITY pin — the SAME [`EphemeralSpec`] classifies
12347 /// identically through [`Self::output_arity_is_many`] AND through
12348 /// `<eph.clone().into::<ProcessSpec>>().classification.output_arity_is_many()`
12349 /// on the mechanically-lowered `ProcessSpec`. Sweeps (`None`
12350 /// classification, `Some(_)` classification on every
12351 /// [`crate::classification::ConvergencePointType::ALL`] variant)
12352 /// so a future regression on either side of the resolver fails
12353 /// HERE at the parity boundary. Byte-for-byte peer of
12354 /// `output_arity_is_one_matches_point_peer_through_lowered_classification`
12355 /// on the antisymmetric closed-set arm via the same resolver-hop
12356 /// shape.
12357 #[test]
12358 fn output_arity_is_many_matches_point_peer_through_lowered_classification() {
12359 // Absent classification.
12360 let eph = empty_ephemeral();
12361 let lowered: ProcessSpec = eph.clone().into();
12362 assert_eq!(
12363 eph.output_arity_is_many(),
12364 lowered.classification.output_arity_is_many(),
12365 "None-classification parity drift",
12366 );
12367 // Authored classification.
12368 for populated in ConvergencePointType::ALL {
12369 let mut classification = Classification::gate_compute();
12370 classification.point_type = populated;
12371 let mut eph = empty_ephemeral();
12372 eph.classification = Some(classification);
12373 let lowered: ProcessSpec = eph.clone().into();
12374 assert_eq!(
12375 eph.output_arity_is_many(),
12376 lowered.classification.output_arity_is_many(),
12377 "authored point_type={populated:?}: parity drift",
12378 );
12379 }
12380 }
12381
12382 /// BINARY XOR PARTITION pin — for the absent-classification
12383 /// baseline AND every
12384 /// [`crate::classification::ConvergencePointType::ALL`] variant,
12385 /// EXACTLY ONE of [`Self::output_arity_is_one`] and
12386 /// [`Self::output_arity_is_many`] returns `true`. CLOSES the
12387 /// output-arity axis into the FULL binary XOR partition contract
12388 /// on the ephemeral surface — the resolver-hop peer of the
12389 /// parent-composed
12390 /// `classification_output_arity_probes_form_binary_xor_partition_over_all`
12391 /// test. Binary counterpart of the ternary XOR partitions sealed
12392 /// on the sibling `point_type` and `substrate` axes by
12393 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12394 /// and
12395 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12396 /// structural twin of the calm/data/direction/input-arity binary
12397 /// partitions on this surface. This pin is the EIGHTH
12398 /// classification axis to reach the closed XOR partition landmark
12399 /// on the ephemeral resolver-hop surface — the SECOND closed axis
12400 /// on the derived-typed-projection stratum of this surface,
12401 /// completing the DAG-composition arity PAIR on the ephemeral
12402 /// stratum after the input-arity closure. Guarantees the absent-
12403 /// classification case lands in the definite single-output bucket
12404 /// (`gate_compute` → point_type=Gate → output_arity=One →
12405 /// is_one=true, is_many=false), so every unadorned
12406 /// `(defephemeral …)` audits under a definite non-empty
12407 /// output-arity bucket.
12408 #[test]
12409 fn ephemeral_output_arity_probes_form_binary_xor_partition_over_all() {
12410 // Absent classification.
12411 let eph = empty_ephemeral();
12412 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
12413 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12414 assert_eq!(
12415 hits, 1,
12416 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12417 );
12418 // Authored classification.
12419 for populated in ConvergencePointType::ALL {
12420 let mut classification = Classification::gate_compute();
12421 classification.point_type = populated;
12422 let mut eph = empty_ephemeral();
12423 eph.classification = Some(classification);
12424 let buckets = [eph.output_arity_is_one(), eph.output_arity_is_many()];
12425 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12426 assert_eq!(
12427 hits, 1,
12428 "authored point_type={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12429 );
12430 }
12431 }
12432
12433 /// BINARY XOR PARTITION pin — for the absent-classification
12434 /// baseline AND every
12435 /// [`crate::classification::HorizonKind::ALL`] variant, EXACTLY
12436 /// ONE of [`Self::horizon_terminates`] and
12437 /// [`Self::horizon_requires_metric_axes`] returns `true`. CLOSES
12438 /// the horizon axis into the FULL binary XOR partition contract
12439 /// on the ephemeral surface — the resolver-hop peer of the
12440 /// parent-composed
12441 /// `classification_horizon_probes_form_binary_xor_partition_over_all`
12442 /// test. Binary counterpart of the ternary XOR partitions sealed
12443 /// on the sibling `point_type` and `substrate` axes by
12444 /// `ephemeral_point_type_probes_form_three_way_xor_partition_over_all`
12445 /// and
12446 /// `ephemeral_substrate_probes_form_three_way_xor_partition_over_all`,
12447 /// structural twin of the calm/data binary partitions
12448 /// `ephemeral_calm_probes_form_binary_xor_partition_over_all`
12449 /// and
12450 /// `ephemeral_data_probes_form_binary_xor_partition_over_all`.
12451 /// This pin is the FIFTH (and final) classification axis to reach
12452 /// the closed XOR partition landmark on the ephemeral resolver-
12453 /// hop surface, sealing every classification axis under the
12454 /// SAME `hits == 1` bucket-array contract. Guarantees the absent-
12455 /// classification case lands in the definite terminating bucket
12456 /// (`gate_compute` → HorizonKind::Bounded → terminates = true,
12457 /// requires_metric_axes = false), so every unadorned
12458 /// `(defephemeral …)` audits under a definite non-empty horizon
12459 /// bucket. Rewritten from the earlier binary-XOR-only form
12460 /// (walked as `a ^ b`) into the canonical bucket-array shape
12461 /// shared with the calm/data partitions.
12462 #[test]
12463 fn ephemeral_horizon_probes_form_binary_xor_partition_over_all() {
12464 // Absent classification.
12465 let eph = empty_ephemeral();
12466 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
12467 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12468 assert_eq!(
12469 hits, 1,
12470 "None-classification: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12471 );
12472 // Authored classification.
12473 for populated in HorizonKind::ALL {
12474 let classification = Classification::gate_compute_with_axis(populated);
12475 let mut eph = empty_ephemeral();
12476 eph.classification = Some(classification);
12477 let buckets = [eph.horizon_terminates(), eph.horizon_requires_metric_axes()];
12478 let hits: u32 = buckets.iter().map(|b| u32::from(*b)).sum();
12479 assert_eq!(
12480 hits, 1,
12481 "authored horizon.kind={populated:?}: probes {buckets:?} — exactly one must be true (binary XOR partition violated)",
12482 );
12483 }
12484 }
12485
12486 // ── EphemeralSpec::has_routing_form pins ─────────────────────────
12487 //
12488 // Fail-before-pass-after granularity: `has_routing_form` did not
12489 // exist pre-lift on `impl EphemeralSpec` — the point-surface
12490 // `routing-form-<kind>` prefix family in tatara-check routed
12491 // through `spec.routing.as_ref().is_some_and(|r| r.has_form(k))`
12492 // inline, so the ephemeral surface had no matching primitive to
12493 // publish the SAME `routing-form-<kind>` prefix family through
12494 // the `strip_and_classify_prefixed_kind` substrate. Post-lift the
12495 // Option-gated derived-scalar-child probe body lives at ONE
12496 // inherent site on [`EphemeralSpec`] and every consumer (this
12497 // module's peer-symmetry tests, tatara-check's ephemeral
12498 // require-tag classifier, any future audit dispatcher walking
12499 // [`RoutingForm::ALL`] over the ephemeral surface) binds through
12500 // the SAME `has_routing_form(kind)` shape.
12501
12502 fn routing_spec(is_stable: bool) -> RoutingSpec {
12503 use crate::routing::{RoutingBackend, RoutingHostname};
12504 RoutingSpec {
12505 hostnames: vec![RoutingHostname::content_hashed("api")],
12506 backend: RoutingBackend::plain("svc", 80),
12507 stable_name_claim: is_stable,
12508 priority: 0,
12509 }
12510 }
12511
12512 /// POPULATED-slot pin — a populated `routing` slot answers `true`
12513 /// exactly for the [`RoutingForm`] variant its
12514 /// [`RoutingSpec::has_form`] derived-scalar arm agrees with, and
12515 /// `false` for every other variant. Sweep the two-boolean × ALL
12516 /// cross so a regression that (a) hard-coded the arm to a single
12517 /// variant, (b) dropped the Option-parent gate (silently reading
12518 /// through `.unwrap_or_default()` on an absent routing slot), or
12519 /// (c) crossed the wires from
12520 /// [`RoutingForm::from_is_stable`] to a fixed variant fails
12521 /// HERE before landing at the operator-facing checks.lisp
12522 /// surface.
12523 #[test]
12524 fn has_routing_form_returns_true_iff_populated_routing_derives_form_per_kind() {
12525 for is_stable in [true, false] {
12526 let populated = RoutingForm::from_is_stable(is_stable);
12527 let mut spec = empty_ephemeral();
12528 spec.routing = Some(routing_spec(is_stable));
12529 for query in RoutingForm::ALL {
12530 let expected = query == populated;
12531 assert_eq!(
12532 spec.has_routing_form(query),
12533 expected,
12534 "ephemeral routing.stable_name_claim={is_stable} (derives {populated:?}): query {query:?} drifted",
12535 );
12536 }
12537 }
12538 }
12539
12540 /// OPTION-PARENT SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12541 /// `routing` slot is `None` returns `false` for every
12542 /// [`RoutingForm`] variant, INCLUDING the closed set's
12543 /// derived-default [`RoutingForm::Instance`]. Locks the
12544 /// Option-parent silencing contract so a regression that dropped
12545 /// the `spec.routing.as_ref()` gate (silently probing an absent
12546 /// routing slot as if it carried the defaulted `Instance` form)
12547 /// fails HERE. Peer to
12548 /// [`evaluate_point_require_tag_returns_false_on_absent_routing_for_every_routing_form_kind`]
12549 /// on the point surface — the two-surface symmetry means both
12550 /// classifiers publish the SAME Option-parent silencing at ONE
12551 /// substrate site per surface.
12552 #[test]
12553 fn has_routing_form_returns_false_on_absent_routing_for_every_kind() {
12554 let spec = empty_ephemeral();
12555 assert!(spec.routing.is_none());
12556 for kind in RoutingForm::ALL {
12557 assert!(
12558 !spec.has_routing_form(kind),
12559 "absent ephemeral routing must return false for {kind:?}",
12560 );
12561 }
12562 }
12563
12564 /// DEFAULT-ARM SHORT-CIRCUIT pin — an [`EphemeralSpec`] whose
12565 /// `routing` slot is a [`RoutingSpec`] with `stable_name_claim`
12566 /// at its `#[serde(default)]` (bool default = `false`) answers
12567 /// `true` on [`RoutingForm::Instance`] and `false` on every other
12568 /// variant WITHOUT the operator naming the routing-form axis on
12569 /// the routing spec. Peer to
12570 /// [`evaluate_point_require_tag_returns_true_on_default_routing_form_for_instance_only`]
12571 /// on the point surface — both surfaces read the derived-child
12572 /// arm through the ONE substrate composer
12573 /// [`RoutingForm::from_is_stable`], so a future normalization at
12574 /// the derivation lands at ONE site and every downstream
12575 /// (routing-form require-tag families on both surfaces,
12576 /// closed-set audit dispatchers) picks it up mechanically.
12577 #[test]
12578 fn has_routing_form_probes_instance_only_on_default_populated_routing() {
12579 let mut spec = empty_ephemeral();
12580 spec.routing = Some(routing_spec(bool::default()));
12581 for kind in RoutingForm::ALL {
12582 let expected = kind == RoutingForm::Instance;
12583 assert_eq!(
12584 spec.has_routing_form(kind),
12585 expected,
12586 "default-populated ephemeral routing (stable_name_claim=false → Instance) baseline: query {kind:?} must be {expected}",
12587 );
12588 }
12589 }
12590
12591 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12592 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12593 /// answer identically on every [`RoutingForm`] × `is_stable`
12594 /// combination. Locks the byte-for-byte parity between
12595 /// [`EphemeralSpec::has_routing_form`] (this new primitive) and
12596 /// the point surface's `spec.routing.as_ref().is_some_and(|r|
12597 /// r.has_form(k))` inline projection at the tatara-check dispatch
12598 /// site. A regression that (a) diverged the ephemeral probe from
12599 /// the lowered point probe (e.g., dropped the Option-parent gate
12600 /// on ONE side, crossed the derived-child arm on the OTHER), or
12601 /// (b) diverged the `From<EphemeralSpec>` lowering's
12602 /// `routing: e.routing` copy from byte-for-byte forwarding, fails
12603 /// HERE at the two-surface boundary.
12604 #[test]
12605 fn has_routing_form_matches_point_peer_through_lowered_routing() {
12606 for is_stable in [true, false] {
12607 let mut authored = empty_ephemeral();
12608 authored.routing = Some(routing_spec(is_stable));
12609 let lowered: ProcessSpec = authored.clone().into();
12610 for kind in RoutingForm::ALL {
12611 let ephemeral_answer = authored.has_routing_form(kind);
12612 let point_answer = lowered.routing.as_ref().is_some_and(|r| r.has_form(kind));
12613 assert_eq!(
12614 ephemeral_answer, point_answer,
12615 "two-surface routing-form parity drift: stable_name_claim={is_stable}, kind={kind:?}",
12616 );
12617 }
12618 }
12619 }
12620
12621 // ── EphemeralSpec::has_applicable_exports_at substrate pins ───────
12622 //
12623 // Fail-before-pass-after granularity: `has_applicable_exports_at`
12624 // did not exist pre-lift on `impl EphemeralSpec` — the peer
12625 // `EphemeralLifetime::has_applicable_exports` on the lowered
12626 // `ProcessSpec` surface routed through the compound
12627 // `.iter().any(|e| e.when.fires_on(phase))` chain inline, so the
12628 // sugar surface had no matching primitive to publish an
12629 // `exports-fire-on-<phase>` prefix family through the
12630 // `strip_and_classify_prefixed_kind` substrate. Post-lift the
12631 // compound-`(when, phase) → fires_on(phase)` probe body lives at
12632 // ONE slice-level substrate site (`ExportSpecSliceExt::has_applicable_at`),
12633 // this ephemeral surface routes through it directly, and the
12634 // point surface reaches the same primitive through
12635 // `spec.lifetime.resolved_ephemeral().is_some_and(|e|
12636 // e.exports.has_applicable_at(phase))`.
12637
12638 fn export_at(when: crate::export::ExportTrigger) -> ExportSpec {
12639 use crate::export::{ArtifactSource, ReceiptsSource, StdoutChannel, VectorChannel};
12640 ExportSpec {
12641 source: ArtifactSource {
12642 receipts: Some(ReceiptsSource::default()),
12643 ..ArtifactSource::default()
12644 },
12645 channel: VectorChannel {
12646 stdout: Some(StdoutChannel::default()),
12647 ..VectorChannel::default()
12648 },
12649 when,
12650 experiment_id_override: None,
12651 }
12652 }
12653
12654 /// EMPTY-EXPORTS pin — an ephemeral spec with an empty `exports`
12655 /// vec returns `false` for EVERY [`ProcessPhase`]. Sweep
12656 /// [`ProcessPhase::ALL`] so a new variant added without a matching
12657 /// arm in [`crate::export::ExportTrigger::fires_on`] surfaces at
12658 /// rustc's exhaustiveness gate on the `ALL` literal (arity forced
12659 /// by `[Self; 11]`) rather than as a silent false-positive at
12660 /// every downstream `exports-fire-on-<phase>` ephemeral require-tag
12661 /// callsite.
12662 #[test]
12663 fn has_applicable_exports_at_returns_false_on_empty_exports_for_every_phase() {
12664 let spec = empty_ephemeral();
12665 assert!(spec.exports.is_empty());
12666 for phase in ProcessPhase::ALL {
12667 assert!(
12668 !spec.has_applicable_exports_at(phase),
12669 "empty-exports ephemeral must return false for {phase:?}",
12670 );
12671 }
12672 }
12673
12674 /// PER-TRIGGER × PER-PHASE pin — an ephemeral spec with a single
12675 /// export answers `has_applicable_exports_at` identically to the
12676 /// [`crate::export::ExportTrigger::fires_on`] truth table on that
12677 /// (trigger, phase) pair, for every combination. Sweep the
12678 /// [`crate::export::ExportTrigger::ALL`] × [`ProcessPhase::ALL`]
12679 /// cross so a regression that (a) short-circuited to raw `when ==
12680 /// kind` equality, (b) missed `Always`'s dual-phase coverage, or
12681 /// (c) inverted a non-terminal phase to return `true` fails HERE
12682 /// at the substrate primitive rather than at each downstream
12683 /// `exports-fire-on-<phase>` classifier callsite.
12684 #[test]
12685 fn has_applicable_exports_at_matches_fires_on_truth_table_per_pair() {
12686 for trigger in crate::export::ExportTrigger::ALL {
12687 let mut spec = empty_ephemeral();
12688 spec.exports = vec![export_at(trigger)];
12689 for phase in ProcessPhase::ALL {
12690 let expected = trigger.fires_on(phase);
12691 assert_eq!(
12692 spec.has_applicable_exports_at(phase),
12693 expected,
12694 "ephemeral trigger={trigger:?} phase={phase:?} drifted from fires_on",
12695 );
12696 }
12697 }
12698 }
12699
12700 /// TWO-SURFACE SYMMETRY pin — an [`EphemeralSpec`] and the
12701 /// [`ProcessSpec`] it lowers to through `From<EphemeralSpec>`
12702 /// answer identically on every [`ProcessPhase`] × trigger
12703 /// combination. Locks the byte-for-byte parity between
12704 /// [`EphemeralSpec::has_applicable_exports_at`] (this new primitive)
12705 /// and the point surface's `spec.lifetime.resolved_ephemeral()
12706 /// .is_some_and(|e| e.exports.has_applicable_at(phase))` projection
12707 /// at the tatara-check dispatch site. A regression that (a)
12708 /// diverged the ephemeral probe from the lowered-lifetime probe,
12709 /// (b) diverged the `From<EphemeralSpec>` lowering's
12710 /// `exports: e.exports` copy from byte-for-byte forwarding, fails
12711 /// HERE at the two-surface boundary.
12712 #[test]
12713 fn has_applicable_exports_at_matches_point_peer_through_lowered_exports() {
12714 for trigger in crate::export::ExportTrigger::ALL {
12715 let mut authored = empty_ephemeral();
12716 authored.exports = vec![export_at(trigger)];
12717 let lowered: ProcessSpec = authored.clone().into();
12718 for phase in ProcessPhase::ALL {
12719 let ephemeral_answer = authored.has_applicable_exports_at(phase);
12720 let point_answer = lowered
12721 .lifetime
12722 .resolved_ephemeral()
12723 .is_some_and(|e| e.exports.has_applicable_at(phase));
12724 assert_eq!(
12725 ephemeral_answer, point_answer,
12726 "two-surface exports-fire-on parity drift: trigger={trigger:?}, phase={phase:?}",
12727 );
12728 }
12729 }
12730 }
12731
12732 /// SUBSTRATE-DELEGATION pin (EphemeralSpec saturation-predicate
12733 /// triad) — the three `is_*_kind_saturated` methods on
12734 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
12735 /// [`ConditionSliceExt::is_kind_saturated`] over the two
12736 /// `Vec<Condition>` slots (precondition + postcondition) and
12737 /// compose the union via `ConditionKind::ALL.iter().all(|k|
12738 /// has_condition_kind(*k))`. Two-surface parity pin against
12739 /// [`crate::boundary::Boundary::is_condition_kind_saturated`] on the
12740 /// point-domain [`ProcessSpec`] surface — the two struct-level
12741 /// saturation callers compose against the SAME slice-level
12742 /// substrate primitive so a regression at the per-slice `all`
12743 /// short-circuit fails at that primitive's tests rather than as
12744 /// silent drift at either sugar-surface arm.
12745 #[test]
12746 fn is_condition_kind_saturated_triad_delegates_to_slice_is_kind_saturated() {
12747 // Empty ephemeral spec — every arm returns false.
12748 let spec = empty_ephemeral();
12749 assert!(
12750 !spec.is_precondition_kind_saturated(),
12751 "empty ephemeral must return false on is_precondition_kind_saturated",
12752 );
12753 assert!(
12754 !spec.is_postcondition_kind_saturated(),
12755 "empty ephemeral must return false on is_postcondition_kind_saturated",
12756 );
12757 assert!(
12758 !spec.is_condition_kind_saturated(),
12759 "empty ephemeral must return false on is_condition_kind_saturated",
12760 );
12761 assert_eq!(
12762 spec.is_condition_kind_saturated(),
12763 spec.missing_condition_kinds().is_empty(),
12764 "empty is_condition_kind_saturated must equal missing_condition_kinds().is_empty()",
12765 );
12766
12767 // Single-populated per side — sweep ALL × ALL.
12768 for pre_kind in ConditionKind::ALL {
12769 for post_kind in ConditionKind::ALL {
12770 let mut spec = empty_ephemeral();
12771 spec.preconditions.push(cond(pre_kind));
12772 spec.postconditions.push(cond(post_kind));
12773 assert_eq!(
12774 spec.is_precondition_kind_saturated(),
12775 spec.preconditions.is_kind_saturated(),
12776 "EphemeralSpec::is_precondition_kind_saturated must delegate verbatim to \
12777 preconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12778 );
12779 assert_eq!(
12780 spec.is_postcondition_kind_saturated(),
12781 spec.postconditions.is_kind_saturated(),
12782 "EphemeralSpec::is_postcondition_kind_saturated must delegate verbatim to \
12783 postconditions.is_kind_saturated() for pre={pre_kind:?} post={post_kind:?}",
12784 );
12785 let expected_union = ConditionKind::ALL
12786 .iter()
12787 .all(|k| pre_kind == *k || post_kind == *k);
12788 assert_eq!(
12789 spec.is_condition_kind_saturated(),
12790 expected_union,
12791 "EphemeralSpec::is_condition_kind_saturated must equal all-ALL-covered-by-either-slice \
12792 for pre={pre_kind:?} post={post_kind:?}",
12793 );
12794
12795 // Two-surface parity: lowered ProcessSpec's Boundary
12796 // must agree bit-for-bit with the ephemeral sugar
12797 // triad on every arm.
12798 let lowered: ProcessSpec = spec.clone().into();
12799 assert_eq!(
12800 spec.is_precondition_kind_saturated(),
12801 lowered.boundary.is_precondition_kind_saturated(),
12802 "two-surface is_precondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12803 );
12804 assert_eq!(
12805 spec.is_postcondition_kind_saturated(),
12806 lowered.boundary.is_postcondition_kind_saturated(),
12807 "two-surface is_postcondition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12808 );
12809 assert_eq!(
12810 spec.is_condition_kind_saturated(),
12811 lowered.boundary.is_condition_kind_saturated(),
12812 "two-surface is_condition_kind_saturated parity drift for pre={pre_kind:?} post={post_kind:?}",
12813 );
12814 }
12815 }
12816
12817 // Saturated ephemeral — both slices carry every ConditionKind,
12818 // every arm returns true.
12819 let mut spec = empty_ephemeral();
12820 for k in ConditionKind::ALL {
12821 spec.preconditions.push(cond(k));
12822 spec.postconditions.push(cond(k));
12823 }
12824 assert!(
12825 spec.is_precondition_kind_saturated(),
12826 "saturated ephemeral must return true on is_precondition_kind_saturated",
12827 );
12828 assert!(
12829 spec.is_postcondition_kind_saturated(),
12830 "saturated ephemeral must return true on is_postcondition_kind_saturated",
12831 );
12832 assert!(
12833 spec.is_condition_kind_saturated(),
12834 "saturated ephemeral must return true on is_condition_kind_saturated",
12835 );
12836 }
12837
12838 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12839 /// triad) — the three `has_any_missing_*_condition_kind` methods
12840 /// on [`EphemeralSpec`] delegate to the slice-level substrate
12841 /// primitive
12842 /// [`crate::boundary::ConditionSliceExt::has_any_missing_kind`]
12843 /// over the two `Vec<Condition>` slots (precondition +
12844 /// postcondition) and compose the union via
12845 /// `!self.is_condition_kind_saturated()`. Two-surface parity pin
12846 /// against
12847 /// [`crate::boundary::Boundary::has_any_missing_condition_kind`] on
12848 /// the point-domain [`ProcessSpec`] surface — the two struct-level
12849 /// at-least-one halfspace callers compose against the SAME slice-
12850 /// level substrate primitive so a regression at the per-slice
12851 /// `all` short-circuit under negation fails at that primitive's
12852 /// tests rather than as silent drift at either sugar-surface arm.
12853 #[test]
12854 fn has_any_missing_condition_kind_triad_delegates_to_slice_has_any_missing_kind() {
12855 // Empty ephemeral spec — every arm returns true (every kind is
12856 // missing from every slice + from the union).
12857 let spec = empty_ephemeral();
12858 assert!(
12859 spec.has_any_missing_precondition_kind(),
12860 "empty ephemeral must return true on has_any_missing_precondition_kind",
12861 );
12862 assert!(
12863 spec.has_any_missing_postcondition_kind(),
12864 "empty ephemeral must return true on has_any_missing_postcondition_kind",
12865 );
12866 assert!(
12867 spec.has_any_missing_condition_kind(),
12868 "empty ephemeral must return true on has_any_missing_condition_kind",
12869 );
12870 assert_eq!(
12871 spec.has_any_missing_condition_kind(),
12872 !spec.is_condition_kind_saturated(),
12873 "empty has_any_missing_condition_kind must equal !is_condition_kind_saturated()",
12874 );
12875
12876 // Single-populated per side — sweep ALL × ALL, then pin the
12877 // (pre, post, union) triad + two-surface parity against the
12878 // lowered ProcessSpec's Boundary.
12879 for pre_kind in ConditionKind::ALL {
12880 for post_kind in ConditionKind::ALL {
12881 let mut spec = empty_ephemeral();
12882 spec.preconditions.push(cond(pre_kind));
12883 spec.postconditions.push(cond(post_kind));
12884 assert_eq!(
12885 spec.has_any_missing_precondition_kind(),
12886 spec.preconditions.has_any_missing_kind(),
12887 "EphemeralSpec::has_any_missing_precondition_kind must delegate verbatim to \
12888 preconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12889 );
12890 assert_eq!(
12891 spec.has_any_missing_postcondition_kind(),
12892 spec.postconditions.has_any_missing_kind(),
12893 "EphemeralSpec::has_any_missing_postcondition_kind must delegate verbatim to \
12894 postconditions.has_any_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
12895 );
12896 let expected_union = !ConditionKind::ALL
12897 .iter()
12898 .all(|k| pre_kind == *k || post_kind == *k);
12899 assert_eq!(
12900 spec.has_any_missing_condition_kind(),
12901 expected_union,
12902 "EphemeralSpec::has_any_missing_condition_kind must equal \
12903 !all-ALL-covered-by-either-slice \
12904 for pre={pre_kind:?} post={post_kind:?}",
12905 );
12906
12907 // Two-surface parity: lowered ProcessSpec's Boundary
12908 // must agree bit-for-bit with the ephemeral sugar
12909 // triad on every arm.
12910 let lowered: ProcessSpec = spec.clone().into();
12911 assert_eq!(
12912 spec.has_any_missing_precondition_kind(),
12913 lowered.boundary.has_any_missing_precondition_kind(),
12914 "two-surface has_any_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12915 );
12916 assert_eq!(
12917 spec.has_any_missing_postcondition_kind(),
12918 lowered.boundary.has_any_missing_postcondition_kind(),
12919 "two-surface has_any_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12920 );
12921 assert_eq!(
12922 spec.has_any_missing_condition_kind(),
12923 lowered.boundary.has_any_missing_condition_kind(),
12924 "two-surface has_any_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
12925 );
12926 }
12927 }
12928
12929 // Saturated ephemeral — both slices carry every ConditionKind,
12930 // every arm returns false.
12931 let mut spec = empty_ephemeral();
12932 for k in ConditionKind::ALL {
12933 spec.preconditions.push(cond(k));
12934 spec.postconditions.push(cond(k));
12935 }
12936 assert!(
12937 !spec.has_any_missing_precondition_kind(),
12938 "saturated ephemeral must return false on has_any_missing_precondition_kind",
12939 );
12940 assert!(
12941 !spec.has_any_missing_postcondition_kind(),
12942 "saturated ephemeral must return false on has_any_missing_postcondition_kind",
12943 );
12944 assert!(
12945 !spec.has_any_missing_condition_kind(),
12946 "saturated ephemeral must return false on has_any_missing_condition_kind",
12947 );
12948 }
12949
12950 /// SUBSTRATE-DELEGATION pin (EphemeralSpec at-least-one halfspace
12951 /// triad on the closed-set-inversion axis) — the three
12952 /// `has_any_distinct_*_condition_kind` methods on
12953 /// [`EphemeralSpec`] delegate to the slice-level substrate
12954 /// primitive
12955 /// [`crate::boundary::ConditionSliceExt::has_any_distinct_kind`]
12956 /// over the two `Vec<Condition>` slots (precondition +
12957 /// postcondition) and compose the union via a SHORT-CIRCUITING
12958 /// closed-set walk over [`ConditionKind::ALL`] under
12959 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
12960 /// against
12961 /// [`crate::boundary::Boundary::has_any_distinct_condition_kind`]
12962 /// on the point-domain [`ProcessSpec`] surface — the two struct-
12963 /// level at-least-one halfspace callers compose against the SAME
12964 /// slice-level substrate primitive so a regression at the per-
12965 /// slice `any` short-circuit fails at that primitive's tests
12966 /// rather than as silent drift at either sugar-surface arm.
12967 #[test]
12968 fn has_any_distinct_condition_kind_triad_delegates_to_slice_has_any_distinct_kind() {
12969 // Empty ephemeral spec — every arm returns false (no kind
12970 // present in either slice).
12971 let spec = empty_ephemeral();
12972 assert!(
12973 !spec.has_any_distinct_precondition_kind(),
12974 "empty ephemeral must return false on has_any_distinct_precondition_kind",
12975 );
12976 assert!(
12977 !spec.has_any_distinct_postcondition_kind(),
12978 "empty ephemeral must return false on has_any_distinct_postcondition_kind",
12979 );
12980 assert!(
12981 !spec.has_any_distinct_condition_kind(),
12982 "empty ephemeral must return false on has_any_distinct_condition_kind",
12983 );
12984
12985 // Single-populated per side — sweep ALL × ALL, then pin the
12986 // (pre, post, union) triad + two-surface parity against the
12987 // lowered ProcessSpec's Boundary.
12988 for pre_kind in ConditionKind::ALL {
12989 for post_kind in ConditionKind::ALL {
12990 let mut spec = empty_ephemeral();
12991 spec.preconditions.push(cond(pre_kind));
12992 spec.postconditions.push(cond(post_kind));
12993 assert_eq!(
12994 spec.has_any_distinct_precondition_kind(),
12995 spec.preconditions.has_any_distinct_kind(),
12996 "EphemeralSpec::has_any_distinct_precondition_kind must delegate verbatim to \
12997 preconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
12998 );
12999 assert_eq!(
13000 spec.has_any_distinct_postcondition_kind(),
13001 spec.postconditions.has_any_distinct_kind(),
13002 "EphemeralSpec::has_any_distinct_postcondition_kind must delegate verbatim to \
13003 postconditions.has_any_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13004 );
13005 assert!(
13006 spec.has_any_distinct_precondition_kind(),
13007 "single-populated preconditions must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
13008 );
13009 assert!(
13010 spec.has_any_distinct_postcondition_kind(),
13011 "single-populated postconditions must return true on has_any_distinct_postcondition_kind for post={post_kind:?}",
13012 );
13013 assert!(
13014 spec.has_any_distinct_condition_kind(),
13015 "single-populated-per-side must return true on has_any_distinct_condition_kind for pre={pre_kind:?} post={post_kind:?}",
13016 );
13017
13018 // Two-surface parity: lowered ProcessSpec's Boundary
13019 // must agree bit-for-bit with the ephemeral sugar
13020 // triad on every arm.
13021 let lowered: ProcessSpec = spec.clone().into();
13022 assert_eq!(
13023 spec.has_any_distinct_precondition_kind(),
13024 lowered.boundary.has_any_distinct_precondition_kind(),
13025 "two-surface has_any_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13026 );
13027 assert_eq!(
13028 spec.has_any_distinct_postcondition_kind(),
13029 lowered.boundary.has_any_distinct_postcondition_kind(),
13030 "two-surface has_any_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13031 );
13032 assert_eq!(
13033 spec.has_any_distinct_condition_kind(),
13034 lowered.boundary.has_any_distinct_condition_kind(),
13035 "two-surface has_any_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13036 );
13037 }
13038 }
13039
13040 // Single-populated precondition only — precondition arm true,
13041 // postcondition arm false, union true.
13042 for pre_kind in ConditionKind::ALL {
13043 let mut spec = empty_ephemeral();
13044 spec.preconditions.push(cond(pre_kind));
13045 assert!(
13046 spec.has_any_distinct_precondition_kind(),
13047 "pre-only ephemeral must return true on has_any_distinct_precondition_kind for pre={pre_kind:?}",
13048 );
13049 assert!(
13050 !spec.has_any_distinct_postcondition_kind(),
13051 "pre-only ephemeral must return false on has_any_distinct_postcondition_kind for pre={pre_kind:?}",
13052 );
13053 assert!(
13054 spec.has_any_distinct_condition_kind(),
13055 "pre-only ephemeral must return true on has_any_distinct_condition_kind for pre={pre_kind:?}",
13056 );
13057 }
13058
13059 // Saturated ephemeral — both slices carry every ConditionKind,
13060 // every arm returns true.
13061 let mut spec = empty_ephemeral();
13062 for k in ConditionKind::ALL {
13063 spec.preconditions.push(cond(k));
13064 spec.postconditions.push(cond(k));
13065 }
13066 assert!(
13067 spec.has_any_distinct_precondition_kind(),
13068 "saturated ephemeral must return true on has_any_distinct_precondition_kind",
13069 );
13070 assert!(
13071 spec.has_any_distinct_postcondition_kind(),
13072 "saturated ephemeral must return true on has_any_distinct_postcondition_kind",
13073 );
13074 assert!(
13075 spec.has_any_distinct_condition_kind(),
13076 "saturated ephemeral must return true on has_any_distinct_condition_kind",
13077 );
13078 }
13079
13080 /// SUBSTRATE-DELEGATION pin (EphemeralSpec singleton-coverage
13081 /// triad on the closed-set-inversion axis) — the three
13082 /// `has_unique_distinct_*_condition_kind` methods on
13083 /// [`EphemeralSpec`] delegate to the slice-level substrate
13084 /// primitive
13085 /// [`crate::boundary::ConditionSliceExt::has_unique_distinct_kind`]
13086 /// over the two `Vec<Condition>` slots (precondition +
13087 /// postcondition) and compose the union via a two-step-short-
13088 /// circuit walk over [`ConditionKind::ALL`] under
13089 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13090 /// against
13091 /// [`crate::boundary::Boundary::has_unique_distinct_condition_kind`]
13092 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13093 /// level singleton-coverage callers compose against the SAME
13094 /// slice-level substrate primitive so a regression at the per-
13095 /// slice two-step short-circuit walk fails at that primitive's
13096 /// tests rather than as silent drift at either sugar-surface arm.
13097 #[test]
13098 fn has_unique_distinct_condition_kind_triad_delegates_to_slice_has_unique_distinct_kind() {
13099 // Empty ephemeral spec — every arm returns false (0 distinct,
13100 // not exactly 1).
13101 let spec = empty_ephemeral();
13102 assert!(
13103 !spec.has_unique_distinct_precondition_kind(),
13104 "empty ephemeral must return false on has_unique_distinct_precondition_kind",
13105 );
13106 assert!(
13107 !spec.has_unique_distinct_postcondition_kind(),
13108 "empty ephemeral must return false on has_unique_distinct_postcondition_kind",
13109 );
13110 assert!(
13111 !spec.has_unique_distinct_condition_kind(),
13112 "empty ephemeral must return false on has_unique_distinct_condition_kind",
13113 );
13114 assert_eq!(
13115 spec.has_unique_distinct_condition_kind(),
13116 spec.distinct_condition_kind_count() == 1,
13117 "empty has_unique_distinct_condition_kind must equal (distinct_condition_kind_count() == 1)",
13118 );
13119
13120 // Single-populated per side — sweep ALL × ALL. Every per-
13121 // slice arm returns true; the union returns true iff the two
13122 // populated kinds coincide (union covers exactly one kind).
13123 for pre_kind in ConditionKind::ALL {
13124 for post_kind in ConditionKind::ALL {
13125 let mut spec = empty_ephemeral();
13126 spec.preconditions.push(cond(pre_kind));
13127 spec.postconditions.push(cond(post_kind));
13128 assert_eq!(
13129 spec.has_unique_distinct_precondition_kind(),
13130 spec.preconditions.has_unique_distinct_kind(),
13131 "EphemeralSpec::has_unique_distinct_precondition_kind must delegate verbatim to \
13132 preconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13133 );
13134 assert_eq!(
13135 spec.has_unique_distinct_postcondition_kind(),
13136 spec.postconditions.has_unique_distinct_kind(),
13137 "EphemeralSpec::has_unique_distinct_postcondition_kind must delegate verbatim to \
13138 postconditions.has_unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13139 );
13140 let covered_count = ConditionKind::ALL
13141 .into_iter()
13142 .filter(|k| *k == pre_kind || *k == post_kind)
13143 .count();
13144 let expected_union = covered_count == 1;
13145 assert_eq!(
13146 spec.has_unique_distinct_condition_kind(),
13147 expected_union,
13148 "EphemeralSpec::has_unique_distinct_condition_kind must equal \
13149 (covered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
13150 );
13151
13152 // Two-surface parity: lowered ProcessSpec's Boundary
13153 // must agree bit-for-bit with the ephemeral sugar
13154 // triad on every arm.
13155 let lowered: ProcessSpec = spec.clone().into();
13156 assert_eq!(
13157 spec.has_unique_distinct_precondition_kind(),
13158 lowered.boundary.has_unique_distinct_precondition_kind(),
13159 "two-surface has_unique_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13160 );
13161 assert_eq!(
13162 spec.has_unique_distinct_postcondition_kind(),
13163 lowered.boundary.has_unique_distinct_postcondition_kind(),
13164 "two-surface has_unique_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13165 );
13166 assert_eq!(
13167 spec.has_unique_distinct_condition_kind(),
13168 lowered.boundary.has_unique_distinct_condition_kind(),
13169 "two-surface has_unique_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13170 );
13171 }
13172 }
13173
13174 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
13175 // distinct, not exactly 1).
13176 if ConditionKind::ALL.len() >= 2 {
13177 let mut spec = empty_ephemeral();
13178 for k in ConditionKind::ALL {
13179 spec.preconditions.push(cond(k));
13180 spec.postconditions.push(cond(k));
13181 }
13182 assert!(
13183 !spec.has_unique_distinct_precondition_kind(),
13184 "saturated ephemeral must return false on has_unique_distinct_precondition_kind",
13185 );
13186 assert!(
13187 !spec.has_unique_distinct_postcondition_kind(),
13188 "saturated ephemeral must return false on has_unique_distinct_postcondition_kind",
13189 );
13190 assert!(
13191 !spec.has_unique_distinct_condition_kind(),
13192 "saturated ephemeral must return false on has_unique_distinct_condition_kind",
13193 );
13194 }
13195 }
13196
13197 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
13198 /// triad on the closed-set-inversion axis) — the three
13199 /// `has_multiple_distinct_*_condition_kind` methods on
13200 /// [`EphemeralSpec`] delegate to the slice-level substrate
13201 /// primitive
13202 /// [`crate::boundary::ConditionSliceExt::has_multiple_distinct_kinds`]
13203 /// over the two `Vec<Condition>` slots (precondition +
13204 /// postcondition) and compose the union via a two-step-short-
13205 /// circuit walk over [`ConditionKind::ALL`] under
13206 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13207 /// against
13208 /// [`crate::boundary::Boundary::has_multiple_distinct_condition_kind`]
13209 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13210 /// level many-distinct callers compose against the SAME slice-
13211 /// level substrate primitive so a regression at the per-slice
13212 /// two-step short-circuit walk fails at that primitive's tests
13213 /// rather than as silent drift at either sugar-surface arm.
13214 #[test]
13215 fn has_multiple_distinct_condition_kind_triad_delegates_to_slice_has_multiple_distinct_kinds() {
13216 // Empty ephemeral spec — every arm returns false (0 distinct,
13217 // not ≥ 2).
13218 let spec = empty_ephemeral();
13219 assert!(
13220 !spec.has_multiple_distinct_precondition_kind(),
13221 "empty ephemeral must return false on has_multiple_distinct_precondition_kind",
13222 );
13223 assert!(
13224 !spec.has_multiple_distinct_postcondition_kind(),
13225 "empty ephemeral must return false on has_multiple_distinct_postcondition_kind",
13226 );
13227 assert!(
13228 !spec.has_multiple_distinct_condition_kind(),
13229 "empty ephemeral must return false on has_multiple_distinct_condition_kind",
13230 );
13231 assert_eq!(
13232 spec.has_multiple_distinct_condition_kind(),
13233 spec.distinct_condition_kind_count() >= 2,
13234 "empty has_multiple_distinct_condition_kind must equal (distinct_condition_kind_count() >= 2)",
13235 );
13236
13237 // Single-populated per side — sweep ALL × ALL. Every per-slice
13238 // arm returns false (1 distinct per slice, not ≥ 2); the
13239 // union returns true iff the two kinds DIFFER (union covers 2
13240 // distinct kinds).
13241 assert!(
13242 ConditionKind::ALL.len() >= 2,
13243 "test assumes ConditionKind::ALL has ≥ 2 variants",
13244 );
13245 for pre_kind in ConditionKind::ALL {
13246 for post_kind in ConditionKind::ALL {
13247 let mut spec = empty_ephemeral();
13248 spec.preconditions.push(cond(pre_kind));
13249 spec.postconditions.push(cond(post_kind));
13250 assert_eq!(
13251 spec.has_multiple_distinct_precondition_kind(),
13252 spec.preconditions.has_multiple_distinct_kinds(),
13253 "EphemeralSpec::has_multiple_distinct_precondition_kind must delegate verbatim to \
13254 preconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
13255 );
13256 assert_eq!(
13257 spec.has_multiple_distinct_postcondition_kind(),
13258 spec.postconditions.has_multiple_distinct_kinds(),
13259 "EphemeralSpec::has_multiple_distinct_postcondition_kind must delegate verbatim to \
13260 postconditions.has_multiple_distinct_kinds() for pre={pre_kind:?} post={post_kind:?}",
13261 );
13262 let covered_count = ConditionKind::ALL
13263 .into_iter()
13264 .filter(|k| *k == pre_kind || *k == post_kind)
13265 .count();
13266 let expected_union = covered_count >= 2;
13267 assert_eq!(
13268 spec.has_multiple_distinct_condition_kind(),
13269 expected_union,
13270 "EphemeralSpec::has_multiple_distinct_condition_kind must equal \
13271 (covered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
13272 );
13273
13274 // Two-surface parity: lowered ProcessSpec's Boundary
13275 // must agree bit-for-bit with the ephemeral sugar
13276 // triad on every arm.
13277 let lowered: ProcessSpec = spec.clone().into();
13278 assert_eq!(
13279 spec.has_multiple_distinct_precondition_kind(),
13280 lowered.boundary.has_multiple_distinct_precondition_kind(),
13281 "two-surface has_multiple_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13282 );
13283 assert_eq!(
13284 spec.has_multiple_distinct_postcondition_kind(),
13285 lowered.boundary.has_multiple_distinct_postcondition_kind(),
13286 "two-surface has_multiple_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13287 );
13288 assert_eq!(
13289 spec.has_multiple_distinct_condition_kind(),
13290 lowered.boundary.has_multiple_distinct_condition_kind(),
13291 "two-surface has_multiple_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13292 );
13293 }
13294 }
13295
13296 // Saturated ephemeral — every arm returns true on N ≥ 2 (N
13297 // distinct, ≥ 2).
13298 let mut spec = empty_ephemeral();
13299 for k in ConditionKind::ALL {
13300 spec.preconditions.push(cond(k));
13301 spec.postconditions.push(cond(k));
13302 }
13303 assert!(
13304 spec.has_multiple_distinct_precondition_kind(),
13305 "saturated ephemeral must return true on has_multiple_distinct_precondition_kind",
13306 );
13307 assert!(
13308 spec.has_multiple_distinct_postcondition_kind(),
13309 "saturated ephemeral must return true on has_multiple_distinct_postcondition_kind",
13310 );
13311 assert!(
13312 spec.has_multiple_distinct_condition_kind(),
13313 "saturated ephemeral must return true on has_multiple_distinct_condition_kind",
13314 );
13315 }
13316
13317 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1" triad
13318 /// on the closed-set-inversion axis) — the three
13319 /// `has_at_most_one_distinct_*_condition_kind` methods on
13320 /// [`EphemeralSpec`] delegate to the slice-level substrate
13321 /// primitive
13322 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_distinct_kind`]
13323 /// over the two `Vec<Condition>` slots (precondition +
13324 /// postcondition) and compose the union via a definitional
13325 /// negation of the many-arm two-step-short-circuit walk over
13326 /// [`ConditionKind::ALL`] under
13327 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13328 /// against
13329 /// [`crate::boundary::Boundary::has_at_most_one_distinct_condition_kind`]
13330 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13331 /// level empty-or-singleton callers compose against the SAME
13332 /// slice-level substrate primitive so a regression at the per-
13333 /// slice "≤ 1" negation fails at that primitive's tests rather
13334 /// than as silent drift at either sugar-surface arm.
13335 #[test]
13336 fn has_at_most_one_distinct_condition_kind_triad_delegates_to_slice_has_at_most_one_distinct_kind(
13337 ) {
13338 // Empty ephemeral spec — every arm returns true (0 distinct,
13339 // ≤ 1).
13340 let spec = empty_ephemeral();
13341 assert!(
13342 spec.has_at_most_one_distinct_precondition_kind(),
13343 "empty ephemeral must return true on has_at_most_one_distinct_precondition_kind",
13344 );
13345 assert!(
13346 spec.has_at_most_one_distinct_postcondition_kind(),
13347 "empty ephemeral must return true on has_at_most_one_distinct_postcondition_kind",
13348 );
13349 assert!(
13350 spec.has_at_most_one_distinct_condition_kind(),
13351 "empty ephemeral must return true on has_at_most_one_distinct_condition_kind",
13352 );
13353 assert_eq!(
13354 spec.has_at_most_one_distinct_condition_kind(),
13355 spec.distinct_condition_kind_count() <= 1,
13356 "empty has_at_most_one_distinct_condition_kind must equal (distinct_condition_kind_count() <= 1)",
13357 );
13358
13359 // Single-populated per side — sweep ALL × ALL. Every per-slice
13360 // arm returns true (1 distinct per slice, ≤ 1); the union
13361 // returns true iff the two kinds COINCIDE (union has 1
13362 // distinct), otherwise the union has 2 distinct and drops to
13363 // false.
13364 assert!(
13365 ConditionKind::ALL.len() >= 2,
13366 "test assumes ConditionKind::ALL has ≥ 2 variants",
13367 );
13368 for pre_kind in ConditionKind::ALL {
13369 for post_kind in ConditionKind::ALL {
13370 let mut spec = empty_ephemeral();
13371 spec.preconditions.push(cond(pre_kind));
13372 spec.postconditions.push(cond(post_kind));
13373 assert_eq!(
13374 spec.has_at_most_one_distinct_precondition_kind(),
13375 spec.preconditions.has_at_most_one_distinct_kind(),
13376 "EphemeralSpec::has_at_most_one_distinct_precondition_kind must delegate verbatim to \
13377 preconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13378 );
13379 assert_eq!(
13380 spec.has_at_most_one_distinct_postcondition_kind(),
13381 spec.postconditions.has_at_most_one_distinct_kind(),
13382 "EphemeralSpec::has_at_most_one_distinct_postcondition_kind must delegate verbatim to \
13383 postconditions.has_at_most_one_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
13384 );
13385 let covered_count = ConditionKind::ALL
13386 .into_iter()
13387 .filter(|k| *k == pre_kind || *k == post_kind)
13388 .count();
13389 let expected_union = covered_count <= 1;
13390 assert_eq!(
13391 spec.has_at_most_one_distinct_condition_kind(),
13392 expected_union,
13393 "EphemeralSpec::has_at_most_one_distinct_condition_kind must equal \
13394 (covered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
13395 );
13396
13397 // Two-surface parity: lowered ProcessSpec's Boundary
13398 // must agree bit-for-bit with the ephemeral sugar
13399 // triad on every arm.
13400 let lowered: ProcessSpec = spec.clone().into();
13401 assert_eq!(
13402 spec.has_at_most_one_distinct_precondition_kind(),
13403 lowered.boundary.has_at_most_one_distinct_precondition_kind(),
13404 "two-surface has_at_most_one_distinct_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13405 );
13406 assert_eq!(
13407 spec.has_at_most_one_distinct_postcondition_kind(),
13408 lowered.boundary.has_at_most_one_distinct_postcondition_kind(),
13409 "two-surface has_at_most_one_distinct_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13410 );
13411 assert_eq!(
13412 spec.has_at_most_one_distinct_condition_kind(),
13413 lowered.boundary.has_at_most_one_distinct_condition_kind(),
13414 "two-surface has_at_most_one_distinct_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13415 );
13416 }
13417 }
13418
13419 // Saturated ephemeral — every arm returns false on N ≥ 2 (N
13420 // distinct, not ≤ 1).
13421 let mut spec = empty_ephemeral();
13422 for k in ConditionKind::ALL {
13423 spec.preconditions.push(cond(k));
13424 spec.postconditions.push(cond(k));
13425 }
13426 assert!(
13427 !spec.has_at_most_one_distinct_precondition_kind(),
13428 "saturated ephemeral must return false on has_at_most_one_distinct_precondition_kind",
13429 );
13430 assert!(
13431 !spec.has_at_most_one_distinct_postcondition_kind(),
13432 "saturated ephemeral must return false on has_at_most_one_distinct_postcondition_kind",
13433 );
13434 assert!(
13435 !spec.has_at_most_one_distinct_condition_kind(),
13436 "saturated ephemeral must return false on has_at_most_one_distinct_condition_kind",
13437 );
13438 }
13439
13440 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality zero-
13441 /// endpoint triad) — the three `is_*_condition_kind_empty` methods
13442 /// on [`EphemeralSpec`] delegate to the slice-level substrate
13443 /// primitive
13444 /// [`crate::boundary::ConditionSliceExt::is_kind_empty`] over the
13445 /// two `Vec<Condition>` slots (precondition + postcondition) and
13446 /// compose the union via a definitional negation of the at-least-
13447 /// one halfspace primitive
13448 /// [`EphemeralSpec::has_any_distinct_condition_kind`]. Two-surface
13449 /// parity pin against
13450 /// [`crate::boundary::Boundary::is_condition_kind_empty`] on the
13451 /// point-domain [`ProcessSpec`] surface — the two struct-level
13452 /// zero-endpoint callers compose against the SAME slice-level
13453 /// substrate primitive so a regression at the per-slice zero-
13454 /// endpoint short-circuit fails at that primitive's tests rather
13455 /// than as silent drift at either sugar-surface arm.
13456 #[test]
13457 fn is_condition_kind_empty_triad_delegates_to_slice_is_kind_empty() {
13458 // Empty ephemeral spec — every arm returns true (0 distinct,
13459 // = 0).
13460 let spec = empty_ephemeral();
13461 assert!(
13462 spec.is_precondition_kind_empty(),
13463 "empty ephemeral must return true on is_precondition_kind_empty",
13464 );
13465 assert!(
13466 spec.is_postcondition_kind_empty(),
13467 "empty ephemeral must return true on is_postcondition_kind_empty",
13468 );
13469 assert!(
13470 spec.is_condition_kind_empty(),
13471 "empty ephemeral must return true on is_condition_kind_empty",
13472 );
13473
13474 // Two-surface parity: EphemeralSpec's three arms are byte-for-
13475 // byte equal to the lowered ProcessSpec's Boundary arms across
13476 // every sweep arm.
13477 let lowered: ProcessSpec = spec.clone().into();
13478 assert_eq!(
13479 spec.is_precondition_kind_empty(),
13480 lowered.boundary.is_precondition_kind_empty(),
13481 "empty ephemeral is_precondition_kind_empty must equal lowered Boundary is_precondition_kind_empty",
13482 );
13483 assert_eq!(
13484 spec.is_postcondition_kind_empty(),
13485 lowered.boundary.is_postcondition_kind_empty(),
13486 "empty ephemeral is_postcondition_kind_empty must equal lowered Boundary is_postcondition_kind_empty",
13487 );
13488 assert_eq!(
13489 spec.is_condition_kind_empty(),
13490 lowered.boundary.is_condition_kind_empty(),
13491 "empty ephemeral is_condition_kind_empty must equal lowered Boundary is_condition_kind_empty",
13492 );
13493
13494 // Single-populated per side — every per-slice arm returns
13495 // false; the union always returns false.
13496 assert!(
13497 !ConditionKind::ALL.is_empty(),
13498 "test assumes ConditionKind::ALL has ≥ 1 variants",
13499 );
13500 for pre_kind in ConditionKind::ALL {
13501 for post_kind in ConditionKind::ALL {
13502 let mut spec = empty_ephemeral();
13503 spec.preconditions.push(cond(pre_kind));
13504 spec.postconditions.push(cond(post_kind));
13505 assert_eq!(
13506 spec.is_precondition_kind_empty(),
13507 spec.preconditions.is_kind_empty(),
13508 "EphemeralSpec::is_precondition_kind_empty must delegate verbatim to \
13509 preconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13510 );
13511 assert_eq!(
13512 spec.is_postcondition_kind_empty(),
13513 spec.postconditions.is_kind_empty(),
13514 "EphemeralSpec::is_postcondition_kind_empty must delegate verbatim to \
13515 postconditions.is_kind_empty() for pre={pre_kind:?} post={post_kind:?}",
13516 );
13517 assert!(
13518 !spec.is_precondition_kind_empty(),
13519 "single-populated preconditions must return false on is_precondition_kind_empty for pre={pre_kind:?}",
13520 );
13521 assert!(
13522 !spec.is_postcondition_kind_empty(),
13523 "single-populated postconditions must return false on is_postcondition_kind_empty for post={post_kind:?}",
13524 );
13525 assert!(
13526 !spec.is_condition_kind_empty(),
13527 "single-populated union must return false on is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13528 );
13529 assert_eq!(
13530 spec.is_condition_kind_empty(),
13531 !spec.has_any_distinct_condition_kind(),
13532 "EphemeralSpec::is_condition_kind_empty must equal !has_any_distinct_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
13533 );
13534 // Two-surface parity with lowered Boundary.
13535 let lowered: ProcessSpec = spec.clone().into();
13536 assert_eq!(
13537 spec.is_precondition_kind_empty(),
13538 lowered.boundary.is_precondition_kind_empty(),
13539 "EphemeralSpec::is_precondition_kind_empty must equal lowered Boundary::is_precondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13540 );
13541 assert_eq!(
13542 spec.is_postcondition_kind_empty(),
13543 lowered.boundary.is_postcondition_kind_empty(),
13544 "EphemeralSpec::is_postcondition_kind_empty must equal lowered Boundary::is_postcondition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13545 );
13546 assert_eq!(
13547 spec.is_condition_kind_empty(),
13548 lowered.boundary.is_condition_kind_empty(),
13549 "EphemeralSpec::is_condition_kind_empty must equal lowered Boundary::is_condition_kind_empty for pre={pre_kind:?} post={post_kind:?}",
13550 );
13551 }
13552 }
13553
13554 // Saturated ephemeral spec — every arm returns false on N ≥ 1
13555 // (every kind PRESENT across the union, not = 0).
13556 let mut spec = empty_ephemeral();
13557 for k in ConditionKind::ALL {
13558 spec.preconditions.push(cond(k));
13559 spec.postconditions.push(cond(k));
13560 }
13561 assert!(
13562 !spec.is_precondition_kind_empty(),
13563 "saturated ephemeral must return false on is_precondition_kind_empty",
13564 );
13565 assert!(
13566 !spec.is_postcondition_kind_empty(),
13567 "saturated ephemeral must return false on is_postcondition_kind_empty",
13568 );
13569 assert!(
13570 !spec.is_condition_kind_empty(),
13571 "saturated ephemeral must return false on is_condition_kind_empty",
13572 );
13573 }
13574
13575 /// SUBSTRATE-DELEGATION pin (EphemeralSpec parent-state middle-arm
13576 /// triad) — the three `is_*_condition_kind_partially_covered`
13577 /// methods on [`EphemeralSpec`] delegate to the slice-level
13578 /// substrate primitive
13579 /// [`crate::boundary::ConditionSliceExt::is_kind_partially_covered`]
13580 /// over the two `Vec<Condition>` slots (precondition +
13581 /// postcondition) and compose the union via the paired-halfspace
13582 /// body `has_any_distinct_condition_kind() && has_any_missing_condition_kind()`.
13583 /// Two-surface parity pin against
13584 /// [`crate::boundary::Boundary::is_condition_kind_partially_covered`]
13585 /// on the point-domain [`ProcessSpec`] surface — the two
13586 /// struct-level middle-arm callers compose against the SAME
13587 /// slice-level substrate primitive so a regression at the per-
13588 /// slice fused short-circuit walk fails at that primitive's tests
13589 /// rather than as silent drift at either sugar-surface arm.
13590 #[test]
13591 fn is_condition_kind_partially_covered_triad_delegates_to_slice_is_kind_partially_covered() {
13592 // Empty ephemeral spec — every arm returns false on any N ≥ 1
13593 // closed set (0 distinct hits the empty arm).
13594 assert!(
13595 !ConditionKind::ALL.is_empty(),
13596 "test assumes ConditionKind::ALL has ≥ 1 variants",
13597 );
13598 let spec = empty_ephemeral();
13599 assert!(
13600 !spec.is_precondition_kind_partially_covered(),
13601 "empty ephemeral must return false on is_precondition_kind_partially_covered",
13602 );
13603 assert!(
13604 !spec.is_postcondition_kind_partially_covered(),
13605 "empty ephemeral must return false on is_postcondition_kind_partially_covered",
13606 );
13607 assert!(
13608 !spec.is_condition_kind_partially_covered(),
13609 "empty ephemeral must return false on is_condition_kind_partially_covered",
13610 );
13611
13612 // Two-surface parity: EphemeralSpec's three arms are byte-for-
13613 // byte equal to the lowered ProcessSpec's Boundary arms.
13614 let lowered: ProcessSpec = spec.clone().into();
13615 assert_eq!(
13616 spec.is_precondition_kind_partially_covered(),
13617 lowered.boundary.is_precondition_kind_partially_covered(),
13618 "empty ephemeral is_precondition_kind_partially_covered must equal lowered Boundary is_precondition_kind_partially_covered",
13619 );
13620 assert_eq!(
13621 spec.is_postcondition_kind_partially_covered(),
13622 lowered.boundary.is_postcondition_kind_partially_covered(),
13623 "empty ephemeral is_postcondition_kind_partially_covered must equal lowered Boundary is_postcondition_kind_partially_covered",
13624 );
13625 assert_eq!(
13626 spec.is_condition_kind_partially_covered(),
13627 lowered.boundary.is_condition_kind_partially_covered(),
13628 "empty ephemeral is_condition_kind_partially_covered must equal lowered Boundary is_condition_kind_partially_covered",
13629 );
13630
13631 // Single-populated per side — every per-slice arm returns
13632 // true on any N ≥ 2 closed set; union true iff coverage
13633 // leaves ≥ 1 ALL variant uncovered.
13634 if ConditionKind::ALL.len() >= 2 {
13635 for pre_kind in ConditionKind::ALL {
13636 for post_kind in ConditionKind::ALL {
13637 let mut spec = empty_ephemeral();
13638 spec.preconditions.push(cond(pre_kind));
13639 spec.postconditions.push(cond(post_kind));
13640 assert_eq!(
13641 spec.is_precondition_kind_partially_covered(),
13642 spec.preconditions.is_kind_partially_covered(),
13643 "EphemeralSpec::is_precondition_kind_partially_covered must delegate verbatim to \
13644 preconditions.is_kind_partially_covered() for pre={pre_kind:?} post={post_kind:?}",
13645 );
13646 assert_eq!(
13647 spec.is_postcondition_kind_partially_covered(),
13648 spec.postconditions.is_kind_partially_covered(),
13649 "EphemeralSpec::is_postcondition_kind_partially_covered must delegate verbatim to \
13650 postconditions.is_kind_partially_covered() for pre={pre_kind:?} post={post_kind:?}",
13651 );
13652 assert!(
13653 spec.is_precondition_kind_partially_covered(),
13654 "single-populated preconditions must return true on is_precondition_kind_partially_covered for pre={pre_kind:?}",
13655 );
13656 assert!(
13657 spec.is_postcondition_kind_partially_covered(),
13658 "single-populated postconditions must return true on is_postcondition_kind_partially_covered for post={post_kind:?}",
13659 );
13660 let covered_count = if pre_kind == post_kind { 1 } else { 2 };
13661 let expected_union = ConditionKind::ALL.len() > covered_count;
13662 assert_eq!(
13663 spec.is_condition_kind_partially_covered(),
13664 expected_union,
13665 "EphemeralSpec::is_condition_kind_partially_covered must equal \
13666 (ConditionKind::ALL.len() > covered-kinds-count) for pre={pre_kind:?} post={post_kind:?}",
13667 );
13668 // Two-surface parity with lowered Boundary.
13669 let lowered: ProcessSpec = spec.clone().into();
13670 assert_eq!(
13671 spec.is_precondition_kind_partially_covered(),
13672 lowered.boundary.is_precondition_kind_partially_covered(),
13673 "EphemeralSpec::is_precondition_kind_partially_covered must equal lowered Boundary::is_precondition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13674 );
13675 assert_eq!(
13676 spec.is_postcondition_kind_partially_covered(),
13677 lowered.boundary.is_postcondition_kind_partially_covered(),
13678 "EphemeralSpec::is_postcondition_kind_partially_covered must equal lowered Boundary::is_postcondition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13679 );
13680 assert_eq!(
13681 spec.is_condition_kind_partially_covered(),
13682 lowered.boundary.is_condition_kind_partially_covered(),
13683 "EphemeralSpec::is_condition_kind_partially_covered must equal lowered Boundary::is_condition_kind_partially_covered for pre={pre_kind:?} post={post_kind:?}",
13684 );
13685 // Trichotomy partition on the union axis.
13686 assert_eq!(
13687 usize::from(spec.is_condition_kind_empty())
13688 + usize::from(spec.is_condition_kind_partially_covered())
13689 + usize::from(spec.is_condition_kind_saturated()),
13690 1,
13691 "EphemeralSpec union trichotomy partition violated for pre={pre_kind:?} post={post_kind:?}",
13692 );
13693 }
13694 }
13695 }
13696
13697 // Saturated ephemeral spec — every arm returns false on any
13698 // N ≥ 1 closed set (0 missing hits the saturated arm).
13699 let mut spec = empty_ephemeral();
13700 for k in ConditionKind::ALL {
13701 spec.preconditions.push(cond(k));
13702 spec.postconditions.push(cond(k));
13703 }
13704 assert!(
13705 !spec.is_precondition_kind_partially_covered(),
13706 "saturated ephemeral must return false on is_precondition_kind_partially_covered",
13707 );
13708 assert!(
13709 !spec.is_postcondition_kind_partially_covered(),
13710 "saturated ephemeral must return false on is_postcondition_kind_partially_covered",
13711 );
13712 assert!(
13713 !spec.is_condition_kind_partially_covered(),
13714 "saturated ephemeral must return false on is_condition_kind_partially_covered",
13715 );
13716 }
13717
13718 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-mid-endpoint
13719 /// triad) — the three `has_unique_missing_*_condition_kind`
13720 /// methods on [`EphemeralSpec`] delegate to the slice-level
13721 /// substrate primitive
13722 /// [`crate::boundary::ConditionSliceExt::has_unique_missing_kind`]
13723 /// over the two `Vec<Condition>` slots (precondition +
13724 /// postcondition) and compose the union via a two-step-short-
13725 /// circuit walk over [`ConditionKind::ALL`] under negated
13726 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13727 /// against
13728 /// [`crate::boundary::Boundary::has_unique_missing_condition_kind`]
13729 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13730 /// level near-saturation-endpoint callers compose against the
13731 /// SAME slice-level substrate primitive so a regression at the
13732 /// per-slice two-step short-circuit walk under negation fails at
13733 /// that primitive's tests rather than as silent drift at either
13734 /// sugar-surface arm.
13735 #[test]
13736 fn has_unique_missing_condition_kind_triad_delegates_to_slice_has_unique_missing_kind() {
13737 // Empty ephemeral spec — every arm returns false (all N
13738 // missing, not exactly 1) on any N ≥ 2 closed set.
13739 assert!(
13740 ConditionKind::ALL.len() >= 2,
13741 "test assumes ConditionKind::ALL has ≥ 2 variants",
13742 );
13743 let spec = empty_ephemeral();
13744 assert!(
13745 !spec.has_unique_missing_precondition_kind(),
13746 "empty ephemeral must return false on has_unique_missing_precondition_kind",
13747 );
13748 assert!(
13749 !spec.has_unique_missing_postcondition_kind(),
13750 "empty ephemeral must return false on has_unique_missing_postcondition_kind",
13751 );
13752 assert!(
13753 !spec.has_unique_missing_condition_kind(),
13754 "empty ephemeral must return false on has_unique_missing_condition_kind",
13755 );
13756 assert_eq!(
13757 spec.has_unique_missing_condition_kind(),
13758 spec.missing_condition_kind_count() == 1,
13759 "empty has_unique_missing_condition_kind must equal (missing_condition_kind_count() == 1)",
13760 );
13761
13762 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
13763 // sets. Every per-slice arm returns false; the union returns
13764 // true iff exactly one ALL variant is uncovered.
13765 if ConditionKind::ALL.len() >= 3 {
13766 for pre_kind in ConditionKind::ALL {
13767 for post_kind in ConditionKind::ALL {
13768 let mut spec = empty_ephemeral();
13769 spec.preconditions.push(cond(pre_kind));
13770 spec.postconditions.push(cond(post_kind));
13771 assert_eq!(
13772 spec.has_unique_missing_precondition_kind(),
13773 spec.preconditions.has_unique_missing_kind(),
13774 "EphemeralSpec::has_unique_missing_precondition_kind must delegate verbatim to \
13775 preconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13776 );
13777 assert_eq!(
13778 spec.has_unique_missing_postcondition_kind(),
13779 spec.postconditions.has_unique_missing_kind(),
13780 "EphemeralSpec::has_unique_missing_postcondition_kind must delegate verbatim to \
13781 postconditions.has_unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
13782 );
13783 let uncovered = ConditionKind::ALL
13784 .into_iter()
13785 .filter(|k| *k != pre_kind && *k != post_kind)
13786 .count();
13787 let expected_union = uncovered == 1;
13788 assert_eq!(
13789 spec.has_unique_missing_condition_kind(),
13790 expected_union,
13791 "EphemeralSpec::has_unique_missing_condition_kind must equal \
13792 (uncovered-ALL-count == 1) for pre={pre_kind:?} post={post_kind:?}",
13793 );
13794
13795 // Two-surface parity: lowered ProcessSpec's
13796 // Boundary must agree bit-for-bit with the
13797 // ephemeral sugar triad on every arm.
13798 let lowered: ProcessSpec = spec.clone().into();
13799 assert_eq!(
13800 spec.has_unique_missing_precondition_kind(),
13801 lowered.boundary.has_unique_missing_precondition_kind(),
13802 "two-surface has_unique_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13803 );
13804 assert_eq!(
13805 spec.has_unique_missing_postcondition_kind(),
13806 lowered.boundary.has_unique_missing_postcondition_kind(),
13807 "two-surface has_unique_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13808 );
13809 assert_eq!(
13810 spec.has_unique_missing_condition_kind(),
13811 lowered.boundary.has_unique_missing_condition_kind(),
13812 "two-surface has_unique_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13813 );
13814 }
13815 }
13816 }
13817
13818 // Near-saturation-endpoint per side — each slice carries
13819 // every ConditionKind except one. Every per-slice arm returns
13820 // true; the union returns true iff BOTH slices omit the SAME
13821 // kind.
13822 for pre_omit in ConditionKind::ALL {
13823 for post_omit in ConditionKind::ALL {
13824 let mut spec = empty_ephemeral();
13825 for k in ConditionKind::ALL {
13826 if k != pre_omit {
13827 spec.preconditions.push(cond(k));
13828 }
13829 if k != post_omit {
13830 spec.postconditions.push(cond(k));
13831 }
13832 }
13833 assert!(
13834 spec.has_unique_missing_precondition_kind(),
13835 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_unique_missing_precondition_kind",
13836 );
13837 assert!(
13838 spec.has_unique_missing_postcondition_kind(),
13839 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_unique_missing_postcondition_kind",
13840 );
13841 let expected_union = pre_omit == post_omit;
13842 assert_eq!(
13843 spec.has_unique_missing_condition_kind(),
13844 expected_union,
13845 "EphemeralSpec::has_unique_missing_condition_kind on both-slices-near-saturated must equal (pre_omit == post_omit) for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13846 );
13847
13848 // Two-surface parity for near-saturation arm.
13849 let lowered: ProcessSpec = spec.clone().into();
13850 assert_eq!(
13851 spec.has_unique_missing_precondition_kind(),
13852 lowered.boundary.has_unique_missing_precondition_kind(),
13853 "two-surface has_unique_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13854 );
13855 assert_eq!(
13856 spec.has_unique_missing_postcondition_kind(),
13857 lowered.boundary.has_unique_missing_postcondition_kind(),
13858 "two-surface has_unique_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13859 );
13860 assert_eq!(
13861 spec.has_unique_missing_condition_kind(),
13862 lowered.boundary.has_unique_missing_condition_kind(),
13863 "two-surface has_unique_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
13864 );
13865 }
13866 }
13867
13868 // Saturated ephemeral — every arm returns false (0 missing,
13869 // not exactly 1).
13870 let mut spec = empty_ephemeral();
13871 for k in ConditionKind::ALL {
13872 spec.preconditions.push(cond(k));
13873 spec.postconditions.push(cond(k));
13874 }
13875 assert!(
13876 !spec.has_unique_missing_precondition_kind(),
13877 "saturated ephemeral must return false on has_unique_missing_precondition_kind",
13878 );
13879 assert!(
13880 !spec.has_unique_missing_postcondition_kind(),
13881 "saturated ephemeral must return false on has_unique_missing_postcondition_kind",
13882 );
13883 assert!(
13884 !spec.has_unique_missing_condition_kind(),
13885 "saturated ephemeral must return false on has_unique_missing_condition_kind",
13886 );
13887 }
13888
13889 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality-many-arm
13890 /// triad) — the three `has_multiple_missing_*_condition_kind`
13891 /// methods on [`EphemeralSpec`] delegate to the slice-level
13892 /// substrate primitive
13893 /// [`crate::boundary::ConditionSliceExt::has_multiple_missing_kinds`]
13894 /// over the two `Vec<Condition>` slots (precondition +
13895 /// postcondition) and compose the union via a two-step-short-
13896 /// circuit walk over [`ConditionKind::ALL`] under negated
13897 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
13898 /// against
13899 /// [`crate::boundary::Boundary::has_multiple_missing_condition_kind`]
13900 /// on the point-domain [`ProcessSpec`] surface — the two struct-
13901 /// level cardinality-many-arm callers compose against the SAME
13902 /// slice-level substrate primitive so a regression at the per-
13903 /// slice two-step short-circuit walk under negation fails at that
13904 /// primitive's tests rather than as silent drift at either sugar-
13905 /// surface arm.
13906 #[test]
13907 fn has_multiple_missing_condition_kind_triad_delegates_to_slice_has_multiple_missing_kinds() {
13908 // Empty ephemeral spec — every arm returns true (all N
13909 // missing, ≥ 2) on any N ≥ 2 closed set.
13910 assert!(
13911 ConditionKind::ALL.len() >= 2,
13912 "test assumes ConditionKind::ALL has ≥ 2 variants",
13913 );
13914 let spec = empty_ephemeral();
13915 assert!(
13916 spec.has_multiple_missing_precondition_kind(),
13917 "empty ephemeral must return true on has_multiple_missing_precondition_kind",
13918 );
13919 assert!(
13920 spec.has_multiple_missing_postcondition_kind(),
13921 "empty ephemeral must return true on has_multiple_missing_postcondition_kind",
13922 );
13923 assert!(
13924 spec.has_multiple_missing_condition_kind(),
13925 "empty ephemeral must return true on has_multiple_missing_condition_kind",
13926 );
13927 assert_eq!(
13928 spec.has_multiple_missing_condition_kind(),
13929 spec.missing_condition_kind_count() >= 2,
13930 "empty has_multiple_missing_condition_kind must equal (missing_condition_kind_count() >= 2)",
13931 );
13932
13933 // Single-populated per side — sweep ALL × ALL on N ≥ 3 closed
13934 // sets. Every per-slice arm returns true; the union returns
13935 // true iff ≥ 2 ALL variants are uncovered.
13936 if ConditionKind::ALL.len() >= 3 {
13937 for pre_kind in ConditionKind::ALL {
13938 for post_kind in ConditionKind::ALL {
13939 let mut spec = empty_ephemeral();
13940 spec.preconditions.push(cond(pre_kind));
13941 spec.postconditions.push(cond(post_kind));
13942 assert_eq!(
13943 spec.has_multiple_missing_precondition_kind(),
13944 spec.preconditions.has_multiple_missing_kinds(),
13945 "EphemeralSpec::has_multiple_missing_precondition_kind must delegate verbatim to \
13946 preconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
13947 );
13948 assert_eq!(
13949 spec.has_multiple_missing_postcondition_kind(),
13950 spec.postconditions.has_multiple_missing_kinds(),
13951 "EphemeralSpec::has_multiple_missing_postcondition_kind must delegate verbatim to \
13952 postconditions.has_multiple_missing_kinds() for pre={pre_kind:?} post={post_kind:?}",
13953 );
13954 let uncovered = ConditionKind::ALL
13955 .into_iter()
13956 .filter(|k| *k != pre_kind && *k != post_kind)
13957 .count();
13958 let expected_union = uncovered >= 2;
13959 assert_eq!(
13960 spec.has_multiple_missing_condition_kind(),
13961 expected_union,
13962 "EphemeralSpec::has_multiple_missing_condition_kind must equal \
13963 (uncovered-ALL-count >= 2) for pre={pre_kind:?} post={post_kind:?}",
13964 );
13965
13966 // Two-surface parity: lowered ProcessSpec's
13967 // Boundary must agree bit-for-bit with the
13968 // ephemeral sugar triad on every arm.
13969 let lowered: ProcessSpec = spec.clone().into();
13970 assert_eq!(
13971 spec.has_multiple_missing_precondition_kind(),
13972 lowered.boundary.has_multiple_missing_precondition_kind(),
13973 "two-surface has_multiple_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13974 );
13975 assert_eq!(
13976 spec.has_multiple_missing_postcondition_kind(),
13977 lowered.boundary.has_multiple_missing_postcondition_kind(),
13978 "two-surface has_multiple_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13979 );
13980 assert_eq!(
13981 spec.has_multiple_missing_condition_kind(),
13982 lowered.boundary.has_multiple_missing_condition_kind(),
13983 "two-surface has_multiple_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
13984 );
13985 }
13986 }
13987 }
13988
13989 // Near-saturation-endpoint per side — each slice carries
13990 // every ConditionKind except one. Every per-slice arm returns
13991 // false (exactly 1 missing per slice, not ≥ 2). The union
13992 // has at most 1 missing (pre and post's omissions either
13993 // coincide → 1 missing, or differ → 0 missing), so the union
13994 // is always false on this arm.
13995 for pre_omit in ConditionKind::ALL {
13996 for post_omit in ConditionKind::ALL {
13997 let mut spec = empty_ephemeral();
13998 for k in ConditionKind::ALL {
13999 if k != pre_omit {
14000 spec.preconditions.push(cond(k));
14001 }
14002 if k != post_omit {
14003 spec.postconditions.push(cond(k));
14004 }
14005 }
14006 assert!(
14007 !spec.has_multiple_missing_precondition_kind(),
14008 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return false on has_multiple_missing_precondition_kind",
14009 );
14010 assert!(
14011 !spec.has_multiple_missing_postcondition_kind(),
14012 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return false on has_multiple_missing_postcondition_kind",
14013 );
14014 assert!(
14015 !spec.has_multiple_missing_condition_kind(),
14016 "EphemeralSpec::has_multiple_missing_condition_kind on both-slices-near-saturated must always be false (union missing ≤ 1) for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14017 );
14018
14019 // Two-surface parity for near-saturation arm.
14020 let lowered: ProcessSpec = spec.clone().into();
14021 assert_eq!(
14022 spec.has_multiple_missing_precondition_kind(),
14023 lowered.boundary.has_multiple_missing_precondition_kind(),
14024 "two-surface has_multiple_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14025 );
14026 assert_eq!(
14027 spec.has_multiple_missing_postcondition_kind(),
14028 lowered.boundary.has_multiple_missing_postcondition_kind(),
14029 "two-surface has_multiple_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14030 );
14031 assert_eq!(
14032 spec.has_multiple_missing_condition_kind(),
14033 lowered.boundary.has_multiple_missing_condition_kind(),
14034 "two-surface has_multiple_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14035 );
14036 }
14037 }
14038
14039 // Saturated ephemeral — every arm returns false (0 missing,
14040 // not ≥ 2).
14041 let mut spec = empty_ephemeral();
14042 for k in ConditionKind::ALL {
14043 spec.preconditions.push(cond(k));
14044 spec.postconditions.push(cond(k));
14045 }
14046 assert!(
14047 !spec.has_multiple_missing_precondition_kind(),
14048 "saturated ephemeral must return false on has_multiple_missing_precondition_kind",
14049 );
14050 assert!(
14051 !spec.has_multiple_missing_postcondition_kind(),
14052 "saturated ephemeral must return false on has_multiple_missing_postcondition_kind",
14053 );
14054 assert!(
14055 !spec.has_multiple_missing_condition_kind(),
14056 "saturated ephemeral must return false on has_multiple_missing_condition_kind",
14057 );
14058 }
14059
14060 /// SUBSTRATE-DELEGATION pin (EphemeralSpec cardinality "≤ 1"
14061 /// triad) — the three `has_at_most_one_missing_*_condition_kind`
14062 /// methods on [`EphemeralSpec`] delegate to the slice-level
14063 /// substrate primitive
14064 /// [`crate::boundary::ConditionSliceExt::has_at_most_one_missing_kind`]
14065 /// over the two `Vec<Condition>` slots (precondition +
14066 /// postcondition) and compose the union via
14067 /// `!self.has_multiple_missing_condition_kind()` — a definitional
14068 /// negation of the many-arm union primitive. Two-surface parity
14069 /// pin against
14070 /// [`crate::boundary::Boundary::has_at_most_one_missing_condition_kind`]
14071 /// on the point-domain [`ProcessSpec`] surface — the two struct-
14072 /// level cardinality "≤ 1" callers compose against the SAME
14073 /// slice-level substrate primitive so a regression at the per-
14074 /// slice "≤ 1" negation fails at that primitive's tests rather
14075 /// than as silent drift at either sugar-surface arm.
14076 #[test]
14077 fn has_at_most_one_missing_condition_kind_triad_delegates_to_slice_has_at_most_one_missing_kind(
14078 ) {
14079 // Empty ephemeral spec — every arm returns false (all N
14080 // missing, not ≤ 1) on any N ≥ 2 closed set.
14081 assert!(
14082 ConditionKind::ALL.len() >= 2,
14083 "test assumes ConditionKind::ALL has ≥ 2 variants",
14084 );
14085 let spec = empty_ephemeral();
14086 assert!(
14087 !spec.has_at_most_one_missing_precondition_kind(),
14088 "empty ephemeral must return false on has_at_most_one_missing_precondition_kind",
14089 );
14090 assert!(
14091 !spec.has_at_most_one_missing_postcondition_kind(),
14092 "empty ephemeral must return false on has_at_most_one_missing_postcondition_kind",
14093 );
14094 assert!(
14095 !spec.has_at_most_one_missing_condition_kind(),
14096 "empty ephemeral must return false on has_at_most_one_missing_condition_kind",
14097 );
14098 assert_eq!(
14099 spec.has_at_most_one_missing_condition_kind(),
14100 spec.missing_condition_kind_count() <= 1,
14101 "empty has_at_most_one_missing_condition_kind must equal (missing_condition_kind_count() <= 1)",
14102 );
14103
14104 // Single-populated per side — sweep ALL × ALL on N ≥ 3
14105 // closed sets. Every per-slice arm returns false; the union
14106 // returns true iff ≤ 1 ALL variant is uncovered.
14107 if ConditionKind::ALL.len() >= 3 {
14108 for pre_kind in ConditionKind::ALL {
14109 for post_kind in ConditionKind::ALL {
14110 let mut spec = empty_ephemeral();
14111 spec.preconditions.push(cond(pre_kind));
14112 spec.postconditions.push(cond(post_kind));
14113 assert_eq!(
14114 spec.has_at_most_one_missing_precondition_kind(),
14115 spec.preconditions.has_at_most_one_missing_kind(),
14116 "EphemeralSpec::has_at_most_one_missing_precondition_kind must delegate verbatim to \
14117 preconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14118 );
14119 assert_eq!(
14120 spec.has_at_most_one_missing_postcondition_kind(),
14121 spec.postconditions.has_at_most_one_missing_kind(),
14122 "EphemeralSpec::has_at_most_one_missing_postcondition_kind must delegate verbatim to \
14123 postconditions.has_at_most_one_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14124 );
14125 let uncovered = ConditionKind::ALL
14126 .into_iter()
14127 .filter(|k| *k != pre_kind && *k != post_kind)
14128 .count();
14129 let expected_union = uncovered <= 1;
14130 assert_eq!(
14131 spec.has_at_most_one_missing_condition_kind(),
14132 expected_union,
14133 "EphemeralSpec::has_at_most_one_missing_condition_kind must equal \
14134 (uncovered-ALL-count <= 1) for pre={pre_kind:?} post={post_kind:?}",
14135 );
14136
14137 // Two-surface parity: lowered ProcessSpec's
14138 // Boundary must agree bit-for-bit with the
14139 // ephemeral sugar triad on every arm.
14140 let lowered: ProcessSpec = spec.clone().into();
14141 assert_eq!(
14142 spec.has_at_most_one_missing_precondition_kind(),
14143 lowered.boundary.has_at_most_one_missing_precondition_kind(),
14144 "two-surface has_at_most_one_missing_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14145 );
14146 assert_eq!(
14147 spec.has_at_most_one_missing_postcondition_kind(),
14148 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
14149 "two-surface has_at_most_one_missing_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14150 );
14151 assert_eq!(
14152 spec.has_at_most_one_missing_condition_kind(),
14153 lowered.boundary.has_at_most_one_missing_condition_kind(),
14154 "two-surface has_at_most_one_missing_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?}",
14155 );
14156 }
14157 }
14158 }
14159
14160 // Near-saturation-endpoint per side — each slice carries
14161 // every ConditionKind except one. Every per-slice arm returns
14162 // true (exactly 1 missing per slice, ≤ 1). The union has ≤ 1
14163 // missing (pre and post's omissions either coincide → 1
14164 // missing, or differ → 0 missing), so the union is always
14165 // true on this arm.
14166 for pre_omit in ConditionKind::ALL {
14167 for post_omit in ConditionKind::ALL {
14168 let mut spec = empty_ephemeral();
14169 for k in ConditionKind::ALL {
14170 if k != pre_omit {
14171 spec.preconditions.push(cond(k));
14172 }
14173 if k != post_omit {
14174 spec.postconditions.push(cond(k));
14175 }
14176 }
14177 assert!(
14178 spec.has_at_most_one_missing_precondition_kind(),
14179 "near-saturation-endpoint precondition slice (omitting {pre_omit:?}) must return true on has_at_most_one_missing_precondition_kind",
14180 );
14181 assert!(
14182 spec.has_at_most_one_missing_postcondition_kind(),
14183 "near-saturation-endpoint postcondition slice (omitting {post_omit:?}) must return true on has_at_most_one_missing_postcondition_kind",
14184 );
14185 assert!(
14186 spec.has_at_most_one_missing_condition_kind(),
14187 "EphemeralSpec::has_at_most_one_missing_condition_kind on both-slices-near-saturated must always be true (union missing ≤ 1) for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14188 );
14189
14190 // Two-surface parity for near-saturation arm.
14191 let lowered: ProcessSpec = spec.clone().into();
14192 assert_eq!(
14193 spec.has_at_most_one_missing_precondition_kind(),
14194 lowered.boundary.has_at_most_one_missing_precondition_kind(),
14195 "two-surface has_at_most_one_missing_precondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14196 );
14197 assert_eq!(
14198 spec.has_at_most_one_missing_postcondition_kind(),
14199 lowered.boundary.has_at_most_one_missing_postcondition_kind(),
14200 "two-surface has_at_most_one_missing_postcondition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14201 );
14202 assert_eq!(
14203 spec.has_at_most_one_missing_condition_kind(),
14204 lowered.boundary.has_at_most_one_missing_condition_kind(),
14205 "two-surface has_at_most_one_missing_condition_kind near-saturation parity drift for pre_omit={pre_omit:?} post_omit={post_omit:?}",
14206 );
14207 }
14208 }
14209
14210 // Saturated ephemeral — every arm returns true (0 missing,
14211 // ≤ 1).
14212 let mut spec = empty_ephemeral();
14213 for k in ConditionKind::ALL {
14214 spec.preconditions.push(cond(k));
14215 spec.postconditions.push(cond(k));
14216 }
14217 assert!(
14218 spec.has_at_most_one_missing_precondition_kind(),
14219 "saturated ephemeral must return true on has_at_most_one_missing_precondition_kind",
14220 );
14221 assert!(
14222 spec.has_at_most_one_missing_postcondition_kind(),
14223 "saturated ephemeral must return true on has_at_most_one_missing_postcondition_kind",
14224 );
14225 assert!(
14226 spec.has_at_most_one_missing_condition_kind(),
14227 "saturated ephemeral must return true on has_at_most_one_missing_condition_kind",
14228 );
14229 }
14230
14231 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind-complement
14232 /// triad) — the three `lacks_*_condition_kind` methods on
14233 /// [`EphemeralSpec`] delegate to the slice-level substrate primitive
14234 /// [`ConditionSliceExt::lacks_kind`] over the two `Vec<Condition>`
14235 /// slots (precondition + postcondition) and compose the union via
14236 /// `!self.has_condition_kind(kind)`. Two-surface parity pin against
14237 /// [`crate::boundary::Boundary::lacks_condition_kind`] on the
14238 /// point-domain [`ProcessSpec`] surface — the two struct-level
14239 /// per-kind-complement callers compose against the SAME slice-level
14240 /// substrate primitive so a regression at the per-slice negation
14241 /// fails at that primitive's tests rather than as silent drift at
14242 /// either sugar-surface arm. Also pins the composition laws
14243 /// `lacks_*_condition_kind(k) == !has_*_condition_kind(k)` at each
14244 /// arm AND `lacks_condition_kind(k) == lacks_precondition_kind(k) &&
14245 /// lacks_postcondition_kind(k)` (the union AND-composition dual of
14246 /// `has`'s OR-composition).
14247 #[test]
14248 fn lacks_condition_kind_triad_delegates_to_slice_lacks_kind() {
14249 // Empty ephemeral spec — every arm returns true on every kind.
14250 let spec = empty_ephemeral();
14251 for kind in ConditionKind::ALL {
14252 assert!(
14253 spec.lacks_precondition_kind(kind),
14254 "empty ephemeral must return true on lacks_precondition_kind for {kind:?}",
14255 );
14256 assert!(
14257 spec.lacks_postcondition_kind(kind),
14258 "empty ephemeral must return true on lacks_postcondition_kind for {kind:?}",
14259 );
14260 assert!(
14261 spec.lacks_condition_kind(kind),
14262 "empty ephemeral must return true on lacks_condition_kind for {kind:?}",
14263 );
14264 assert_eq!(
14265 spec.lacks_condition_kind(kind),
14266 !spec.has_condition_kind(kind),
14267 "empty lacks_condition_kind must equal !has_condition_kind for {kind:?}",
14268 );
14269 }
14270
14271 // Single-populated per side — sweep ALL × ALL, then probe every
14272 // ConditionKind on the (pre, post, union) triad + two-surface
14273 // parity against the lowered ProcessSpec's Boundary.
14274 for pre_kind in ConditionKind::ALL {
14275 for post_kind in ConditionKind::ALL {
14276 let mut spec = empty_ephemeral();
14277 spec.preconditions.push(cond(pre_kind));
14278 spec.postconditions.push(cond(post_kind));
14279 let lowered: ProcessSpec = spec.clone().into();
14280 for probe in ConditionKind::ALL {
14281 assert_eq!(
14282 spec.lacks_precondition_kind(probe),
14283 spec.preconditions.lacks_kind(probe),
14284 "EphemeralSpec::lacks_precondition_kind must delegate verbatim to preconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14285 );
14286 assert_eq!(
14287 spec.lacks_postcondition_kind(probe),
14288 spec.postconditions.lacks_kind(probe),
14289 "EphemeralSpec::lacks_postcondition_kind must delegate verbatim to postconditions.lacks_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14290 );
14291 let expected_union = pre_kind != probe && post_kind != probe;
14292 assert_eq!(
14293 spec.lacks_condition_kind(probe),
14294 expected_union,
14295 "EphemeralSpec::lacks_condition_kind must equal all-ALL-absent-in-both-slices for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14296 );
14297 assert_eq!(
14298 spec.lacks_condition_kind(probe),
14299 !spec.has_condition_kind(probe),
14300 "EphemeralSpec::lacks_condition_kind must equal !has_condition_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14301 );
14302 assert_eq!(
14303 spec.lacks_condition_kind(probe),
14304 spec.lacks_precondition_kind(probe)
14305 && spec.lacks_postcondition_kind(probe),
14306 "EphemeralSpec::lacks_condition_kind must equal AND-of-half-slice-arms for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14307 );
14308
14309 // Two-surface parity: lowered ProcessSpec's Boundary
14310 // must agree bit-for-bit with the ephemeral sugar
14311 // triad on every arm.
14312 assert_eq!(
14313 spec.lacks_precondition_kind(probe),
14314 lowered.boundary.lacks_precondition_kind(probe),
14315 "two-surface lacks_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14316 );
14317 assert_eq!(
14318 spec.lacks_postcondition_kind(probe),
14319 lowered.boundary.lacks_postcondition_kind(probe),
14320 "two-surface lacks_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14321 );
14322 assert_eq!(
14323 spec.lacks_condition_kind(probe),
14324 lowered.boundary.lacks_condition_kind(probe),
14325 "two-surface lacks_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14326 );
14327 }
14328 }
14329 }
14330
14331 // Saturated ephemeral — both slices carry every ConditionKind,
14332 // every arm returns false on every kind.
14333 let mut spec = empty_ephemeral();
14334 for k in ConditionKind::ALL {
14335 spec.preconditions.push(cond(k));
14336 spec.postconditions.push(cond(k));
14337 }
14338 for kind in ConditionKind::ALL {
14339 assert!(
14340 !spec.lacks_precondition_kind(kind),
14341 "saturated ephemeral must return false on lacks_precondition_kind for {kind:?}",
14342 );
14343 assert!(
14344 !spec.lacks_postcondition_kind(kind),
14345 "saturated ephemeral must return false on lacks_postcondition_kind for {kind:?}",
14346 );
14347 assert!(
14348 !spec.lacks_condition_kind(kind),
14349 "saturated ephemeral must return false on lacks_condition_kind for {kind:?}",
14350 );
14351 }
14352 }
14353
14354 /// TRIAD delegation pin — the (precondition, postcondition,
14355 /// condition-union) kind-scoped strict-refinement triad on
14356 /// [`EphemeralSpec`] agrees byte-for-byte with the slice-level
14357 /// substrate primitive
14358 /// [`crate::boundary::ConditionSliceExt::has_only_kind`] on every
14359 /// authored arrangement AND with the lowered
14360 /// [`ProcessSpec::boundary`]'s kind-scoped strict-refinement
14361 /// triad through the `From<EphemeralSpec>` bridge — the two-
14362 /// surface parity contract at the well-formed-diagonal arm.
14363 ///
14364 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
14365 /// single-populated-per-side arrangements (the well-formed
14366 /// diagonal), probing every [`ConditionKind`] at the union arm
14367 /// against the DERIVED oracle `pre_kind == probe && post_kind ==
14368 /// probe`. Also sweeps the single-side-only-populated arms (the
14369 /// union carries a singleton distinct set — pins the union arm
14370 /// reaches the union primitive, not the (pre AND post) AND-
14371 /// composition). A regression at the union arm's fused walk or
14372 /// at the `From<EphemeralSpec>` bridge surfaces HERE.
14373 #[test]
14374 fn has_only_condition_kind_triad_delegates_to_slice_has_only_kind() {
14375 // Empty ephemeral spec — every arm returns false on every
14376 // kind (no kind is populated, so no kind is "only").
14377 let spec = empty_ephemeral();
14378 for kind in ConditionKind::ALL {
14379 assert!(
14380 !spec.has_only_precondition_kind(kind),
14381 "empty ephemeral must return false on has_only_precondition_kind for {kind:?}",
14382 );
14383 assert!(
14384 !spec.has_only_postcondition_kind(kind),
14385 "empty ephemeral must return false on has_only_postcondition_kind for {kind:?}",
14386 );
14387 assert!(
14388 !spec.has_only_condition_kind(kind),
14389 "empty ephemeral must return false on has_only_condition_kind for {kind:?}",
14390 );
14391 }
14392
14393 // Single-populated per side — sweep ALL × ALL, then probe
14394 // every ConditionKind on the (pre, post, union) triad + two-
14395 // surface parity against the lowered ProcessSpec's Boundary.
14396 for pre_kind in ConditionKind::ALL {
14397 for post_kind in ConditionKind::ALL {
14398 let mut spec = empty_ephemeral();
14399 spec.preconditions.push(cond(pre_kind));
14400 spec.postconditions.push(cond(post_kind));
14401 let lowered: ProcessSpec = spec.clone().into();
14402 for probe in ConditionKind::ALL {
14403 assert_eq!(
14404 spec.has_only_precondition_kind(probe),
14405 spec.preconditions.has_only_kind(probe),
14406 "EphemeralSpec::has_only_precondition_kind must delegate verbatim to preconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14407 );
14408 assert_eq!(
14409 spec.has_only_postcondition_kind(probe),
14410 spec.postconditions.has_only_kind(probe),
14411 "EphemeralSpec::has_only_postcondition_kind must delegate verbatim to postconditions.has_only_kind for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14412 );
14413 let expected_union = pre_kind == probe && post_kind == probe;
14414 assert_eq!(
14415 spec.has_only_condition_kind(probe),
14416 expected_union,
14417 "EphemeralSpec::has_only_condition_kind must equal (pre_kind == probe && post_kind == probe) for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14418 );
14419
14420 // Two-surface parity: lowered ProcessSpec's
14421 // Boundary must agree bit-for-bit with the
14422 // ephemeral sugar triad on every arm.
14423 assert_eq!(
14424 spec.has_only_precondition_kind(probe),
14425 lowered.boundary.has_only_precondition_kind(probe),
14426 "two-surface has_only_precondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14427 );
14428 assert_eq!(
14429 spec.has_only_postcondition_kind(probe),
14430 lowered.boundary.has_only_postcondition_kind(probe),
14431 "two-surface has_only_postcondition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14432 );
14433 assert_eq!(
14434 spec.has_only_condition_kind(probe),
14435 lowered.boundary.has_only_condition_kind(probe),
14436 "two-surface has_only_condition_kind parity drift for pre={pre_kind:?} post={post_kind:?} probe={probe:?}",
14437 );
14438 }
14439 }
14440 }
14441
14442 // Single-side-only populated — the union carries a singleton
14443 // distinct set; the union arm returns `true` for the populated
14444 // kind and `false` for every other kind, DESPITE the empty
14445 // side's `has_only_kind` returning `false`. Pins that the
14446 // union arm reaches the union primitive
14447 // [`Self::has_condition_kind`], not the (pre AND post) AND-
14448 // composition of the per-slice arms. Also pins two-surface
14449 // parity on the single-side arrangement.
14450 for populated in ConditionKind::ALL {
14451 let mut spec = empty_ephemeral();
14452 spec.preconditions.push(cond(populated));
14453 let lowered: ProcessSpec = spec.clone().into();
14454 for probe in ConditionKind::ALL {
14455 let expected = probe == populated;
14456 assert_eq!(
14457 spec.has_only_condition_kind(probe),
14458 expected,
14459 "pre-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
14460 );
14461 assert_eq!(
14462 spec.has_only_condition_kind(probe),
14463 lowered.boundary.has_only_condition_kind(probe),
14464 "two-surface pre-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
14465 );
14466 }
14467
14468 let mut spec = empty_ephemeral();
14469 spec.postconditions.push(cond(populated));
14470 let lowered: ProcessSpec = spec.clone().into();
14471 for probe in ConditionKind::ALL {
14472 let expected = probe == populated;
14473 assert_eq!(
14474 spec.has_only_condition_kind(probe),
14475 expected,
14476 "post-only ephemeral populated={populated:?} must return {expected} on has_only_condition_kind({probe:?})",
14477 );
14478 assert_eq!(
14479 spec.has_only_condition_kind(probe),
14480 lowered.boundary.has_only_condition_kind(probe),
14481 "two-surface post-only has_only_condition_kind parity drift for populated={populated:?} probe={probe:?}",
14482 );
14483 }
14484 }
14485
14486 // Saturated ephemeral — both slices carry every ConditionKind,
14487 // every arm returns false on every kind (N distinct kinds, no
14488 // kind is "only").
14489 let mut spec = empty_ephemeral();
14490 for k in ConditionKind::ALL {
14491 spec.preconditions.push(cond(k));
14492 spec.postconditions.push(cond(k));
14493 }
14494 for kind in ConditionKind::ALL {
14495 assert!(
14496 !spec.has_only_precondition_kind(kind),
14497 "saturated ephemeral must return false on has_only_precondition_kind for {kind:?}",
14498 );
14499 assert!(
14500 !spec.has_only_postcondition_kind(kind),
14501 "saturated ephemeral must return false on has_only_postcondition_kind for {kind:?}",
14502 );
14503 assert!(
14504 !spec.has_only_condition_kind(kind),
14505 "saturated ephemeral must return false on has_only_condition_kind for {kind:?}",
14506 );
14507 }
14508 }
14509
14510 /// TRIAD delegation pin — the (precondition, postcondition,
14511 /// condition-union) kind-scoped strict-refinement-on-missing triad
14512 /// on [`EphemeralSpec`] agrees byte-for-byte with the slice-level
14513 /// substrate primitive
14514 /// [`crate::boundary::ConditionSliceExt::lacks_only_kind`] on every
14515 /// authored arrangement, AND agrees bit-for-bit with the lowered
14516 /// [`ProcessSpec::boundary`]'s triad via the [`From`] bridge.
14517 ///
14518 /// Sweeps [`ConditionKind::ALL`] × [`ConditionKind::ALL`] over
14519 /// single-populated-per-side arrangements + near-saturation-per-
14520 /// side arrangements + single-side-only near-saturation
14521 /// arrangements. The union arm is probed against the DERIVED
14522 /// oracle `spec.missing_condition_kinds() == vec![probe]`, and
14523 /// the per-slice arms delegate to the slice substrate primitive
14524 /// verbatim. Two-surface parity ensures a regression at the
14525 /// `From<EphemeralSpec>` bridge (a re-ordered condition Vec, a
14526 /// dropped ClosedLoopAuth default) surfaces HERE at the union arm.
14527 #[test]
14528 fn lacks_only_condition_kind_triad_delegates_to_slice_lacks_only_kind() {
14529 // Empty ephemeral spec — every kind is missing on N ≥ 2, so
14530 // no kind is "only" missing on any arm.
14531 let spec = empty_ephemeral();
14532 let lowered: ProcessSpec = spec.clone().into();
14533 for kind in ConditionKind::ALL {
14534 assert_eq!(
14535 spec.lacks_only_precondition_kind(kind),
14536 spec.preconditions.lacks_only_kind(kind),
14537 "empty ephemeral lacks_only_precondition_kind must delegate to preconditions.lacks_only_kind for {kind:?}",
14538 );
14539 assert_eq!(
14540 spec.lacks_only_postcondition_kind(kind),
14541 spec.postconditions.lacks_only_kind(kind),
14542 "empty ephemeral lacks_only_postcondition_kind must delegate to postconditions.lacks_only_kind for {kind:?}",
14543 );
14544 assert_eq!(
14545 spec.lacks_only_condition_kind(kind),
14546 lowered.boundary.lacks_only_condition_kind(kind),
14547 "two-surface empty lacks_only_condition_kind parity drift for {kind:?}",
14548 );
14549 }
14550
14551 // Near-saturation per side — build an ephemeral spec whose both
14552 // sides carry every kind except one; sweep every omitted kind
14553 // and probe every ConditionKind on the (pre, post, union) triad.
14554 for omitted in ConditionKind::ALL {
14555 let mut spec = empty_ephemeral();
14556 for k in ConditionKind::ALL {
14557 if k != omitted {
14558 spec.preconditions.push(cond(k));
14559 spec.postconditions.push(cond(k));
14560 }
14561 }
14562 let lowered: ProcessSpec = spec.clone().into();
14563 for probe in ConditionKind::ALL {
14564 let expected = probe == omitted;
14565 assert_eq!(
14566 spec.lacks_only_precondition_kind(probe),
14567 expected,
14568 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_precondition_kind({probe:?})",
14569 );
14570 assert_eq!(
14571 spec.lacks_only_postcondition_kind(probe),
14572 expected,
14573 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_postcondition_kind({probe:?})",
14574 );
14575 assert_eq!(
14576 spec.lacks_only_condition_kind(probe),
14577 expected,
14578 "near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
14579 );
14580 assert_eq!(
14581 spec.lacks_only_condition_kind(probe),
14582 spec.missing_condition_kinds() == vec![probe],
14583 "near-saturation ephemeral omitted={omitted:?} must agree with missing_condition_kinds() == vec![{probe:?}]",
14584 );
14585
14586 // Two-surface parity via lowered ProcessSpec.
14587 assert_eq!(
14588 spec.lacks_only_precondition_kind(probe),
14589 lowered.boundary.lacks_only_precondition_kind(probe),
14590 "two-surface lacks_only_precondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14591 );
14592 assert_eq!(
14593 spec.lacks_only_postcondition_kind(probe),
14594 lowered.boundary.lacks_only_postcondition_kind(probe),
14595 "two-surface lacks_only_postcondition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14596 );
14597 assert_eq!(
14598 spec.lacks_only_condition_kind(probe),
14599 lowered.boundary.lacks_only_condition_kind(probe),
14600 "two-surface lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14601 );
14602 }
14603 }
14604
14605 // Single-side-only near-saturation — the populated side covers
14606 // every kind except one; the OTHER side is empty. The union
14607 // still has missing set `{omitted}` (the populated side's hole
14608 // wins), so the union arm returns `true` for `omitted` and
14609 // `false` for every other kind, DESPITE the empty side's
14610 // `lacks_only_kind` returning `false` on every kind for N ≥ 2.
14611 // Pins that the union arm reaches the union primitive, not the
14612 // (pre AND post) AND-composition.
14613 for omitted in ConditionKind::ALL {
14614 let mut spec = empty_ephemeral();
14615 for k in ConditionKind::ALL {
14616 if k != omitted {
14617 spec.preconditions.push(cond(k));
14618 }
14619 }
14620 let lowered: ProcessSpec = spec.clone().into();
14621 for probe in ConditionKind::ALL {
14622 let expected = probe == omitted;
14623 assert_eq!(
14624 spec.lacks_only_condition_kind(probe),
14625 expected,
14626 "pre-only near-saturation ephemeral omitted={omitted:?} must return {expected} on lacks_only_condition_kind({probe:?})",
14627 );
14628 assert_eq!(
14629 spec.lacks_only_condition_kind(probe),
14630 lowered.boundary.lacks_only_condition_kind(probe),
14631 "two-surface pre-only near-saturation lacks_only_condition_kind parity drift for omitted={omitted:?} probe={probe:?}",
14632 );
14633 }
14634 }
14635
14636 // Saturated ephemeral — every kind populated, no kind missing,
14637 // every arm returns false on every kind.
14638 let mut spec = empty_ephemeral();
14639 for k in ConditionKind::ALL {
14640 spec.preconditions.push(cond(k));
14641 spec.postconditions.push(cond(k));
14642 }
14643 for kind in ConditionKind::ALL {
14644 assert!(
14645 !spec.lacks_only_precondition_kind(kind),
14646 "saturated ephemeral must return false on lacks_only_precondition_kind for {kind:?}",
14647 );
14648 assert!(
14649 !spec.lacks_only_postcondition_kind(kind),
14650 "saturated ephemeral must return false on lacks_only_postcondition_kind for {kind:?}",
14651 );
14652 assert!(
14653 !spec.lacks_only_condition_kind(kind),
14654 "saturated ephemeral must return false on lacks_only_condition_kind for {kind:?}",
14655 );
14656 }
14657 }
14658
14659 /// SUBSTRATE-DELEGATION pin (EphemeralSpec unique-distinct-kind
14660 /// witnessing triad on the closed-set-inversion axis) — the three
14661 /// `unique_distinct_*_condition_kind` methods on [`EphemeralSpec`]
14662 /// delegate to the slice-level substrate primitive
14663 /// [`crate::boundary::ConditionSliceExt::unique_distinct_kind`]
14664 /// over the two `Vec<Condition>` slots (precondition +
14665 /// postcondition) and compose the union via a two-step-short-
14666 /// circuit walk over [`ConditionKind::ALL`] under
14667 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
14668 /// against
14669 /// [`crate::boundary::Boundary::unique_distinct_condition_kind`]
14670 /// on the point-domain [`ProcessSpec`] surface — the two struct-
14671 /// level singleton-coverage witnesses compose against the SAME
14672 /// slice-level substrate primitive so a regression at the per-
14673 /// slice two-step short-circuit witnessing walk fails at that
14674 /// primitive's tests rather than as silent drift at either sugar-
14675 /// surface arm.
14676 #[test]
14677 fn unique_distinct_condition_kind_triad_delegates_to_slice_unique_distinct_kind() {
14678 // Empty ephemeral spec — every arm returns None.
14679 let spec = empty_ephemeral();
14680 assert_eq!(
14681 spec.unique_distinct_precondition_kind(),
14682 None,
14683 "empty ephemeral must return None on unique_distinct_precondition_kind",
14684 );
14685 assert_eq!(
14686 spec.unique_distinct_postcondition_kind(),
14687 None,
14688 "empty ephemeral must return None on unique_distinct_postcondition_kind",
14689 );
14690 assert_eq!(
14691 spec.unique_distinct_condition_kind(),
14692 None,
14693 "empty ephemeral must return None on unique_distinct_condition_kind",
14694 );
14695
14696 // Single-populated per side — sweep ALL × ALL.
14697 for pre_kind in ConditionKind::ALL {
14698 for post_kind in ConditionKind::ALL {
14699 let mut spec = empty_ephemeral();
14700 spec.preconditions.push(cond(pre_kind));
14701 spec.postconditions.push(cond(post_kind));
14702
14703 assert_eq!(
14704 spec.unique_distinct_precondition_kind(),
14705 spec.preconditions.unique_distinct_kind(),
14706 "EphemeralSpec::unique_distinct_precondition_kind must delegate verbatim to \
14707 preconditions.unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
14708 );
14709 assert_eq!(
14710 spec.unique_distinct_precondition_kind(),
14711 Some(pre_kind),
14712 "EphemeralSpec::unique_distinct_precondition_kind must equal Some(pre_kind) on \
14713 single-populated preconditions for pre={pre_kind:?} post={post_kind:?}",
14714 );
14715 assert_eq!(
14716 spec.unique_distinct_postcondition_kind(),
14717 spec.postconditions.unique_distinct_kind(),
14718 "EphemeralSpec::unique_distinct_postcondition_kind must delegate verbatim to \
14719 postconditions.unique_distinct_kind() for pre={pre_kind:?} post={post_kind:?}",
14720 );
14721 assert_eq!(
14722 spec.unique_distinct_postcondition_kind(),
14723 Some(post_kind),
14724 "EphemeralSpec::unique_distinct_postcondition_kind must equal Some(post_kind) on \
14725 single-populated postconditions for pre={pre_kind:?} post={post_kind:?}",
14726 );
14727
14728 let covered: Vec<ConditionKind> = ConditionKind::ALL
14729 .into_iter()
14730 .filter(|k| pre_kind == *k || post_kind == *k)
14731 .collect();
14732 let expected_union = if covered.len() == 1 {
14733 Some(covered[0])
14734 } else {
14735 None
14736 };
14737 assert_eq!(
14738 spec.unique_distinct_condition_kind(),
14739 expected_union,
14740 "EphemeralSpec::unique_distinct_condition_kind must equal Some(k) iff the \
14741 ALL-entries covered by either half-slice sum to exactly one for \
14742 pre={pre_kind:?} post={post_kind:?}",
14743 );
14744
14745 // Boolean-witness composition laws.
14746 assert_eq!(
14747 spec.unique_distinct_condition_kind().is_some(),
14748 spec.has_unique_distinct_condition_kind(),
14749 "unique_distinct_condition_kind().is_some() must equal \
14750 has_unique_distinct_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
14751 );
14752
14753 // Two-surface parity — lowered ProcessSpec's Boundary
14754 // must agree bit-for-bit with the ephemeral sugar
14755 // triad on every arm.
14756 let lowered: ProcessSpec = spec.clone().into();
14757 assert_eq!(
14758 spec.unique_distinct_precondition_kind(),
14759 lowered.boundary.unique_distinct_precondition_kind(),
14760 "two-surface unique_distinct_precondition_kind parity drift for \
14761 pre={pre_kind:?} post={post_kind:?}",
14762 );
14763 assert_eq!(
14764 spec.unique_distinct_postcondition_kind(),
14765 lowered.boundary.unique_distinct_postcondition_kind(),
14766 "two-surface unique_distinct_postcondition_kind parity drift for \
14767 pre={pre_kind:?} post={post_kind:?}",
14768 );
14769 assert_eq!(
14770 spec.unique_distinct_condition_kind(),
14771 lowered.boundary.unique_distinct_condition_kind(),
14772 "two-surface unique_distinct_condition_kind parity drift for \
14773 pre={pre_kind:?} post={post_kind:?}",
14774 );
14775 }
14776 }
14777
14778 // Saturated ephemeral — every arm returns None on N ≥ 2.
14779 if ConditionKind::ALL.len() >= 2 {
14780 let mut spec = empty_ephemeral();
14781 for k in ConditionKind::ALL {
14782 spec.preconditions.push(cond(k));
14783 spec.postconditions.push(cond(k));
14784 }
14785 assert_eq!(
14786 spec.unique_distinct_precondition_kind(),
14787 None,
14788 "saturated ephemeral must return None on unique_distinct_precondition_kind",
14789 );
14790 assert_eq!(
14791 spec.unique_distinct_postcondition_kind(),
14792 None,
14793 "saturated ephemeral must return None on unique_distinct_postcondition_kind",
14794 );
14795 assert_eq!(
14796 spec.unique_distinct_condition_kind(),
14797 None,
14798 "saturated ephemeral must return None on unique_distinct_condition_kind",
14799 );
14800 }
14801 }
14802
14803 /// SUBSTRATE-DELEGATION pin (EphemeralSpec unique-missing-kind
14804 /// witnessing triad on the closed-set-complement axis) — the three
14805 /// `unique_missing_*_condition_kind` methods on [`EphemeralSpec`]
14806 /// delegate to the slice-level substrate primitive
14807 /// [`crate::boundary::ConditionSliceExt::unique_missing_kind`]
14808 /// over the two `Vec<Condition>` slots (precondition +
14809 /// postcondition) and compose the union via a two-step-short-
14810 /// circuit walk over [`ConditionKind::ALL`] under a NEGATED
14811 /// [`EphemeralSpec::has_condition_kind`]. Two-surface parity pin
14812 /// against
14813 /// [`crate::boundary::Boundary::unique_missing_condition_kind`]
14814 /// on the point-domain [`ProcessSpec`] surface.
14815 #[test]
14816 fn unique_missing_condition_kind_triad_delegates_to_slice_unique_missing_kind() {
14817 // Empty ephemeral spec — every arm returns None on N ≥ 2
14818 // (every kind is missing, not exactly one).
14819 let spec = empty_ephemeral();
14820 if ConditionKind::ALL.len() >= 2 {
14821 assert_eq!(
14822 spec.unique_missing_precondition_kind(),
14823 None,
14824 "empty ephemeral must return None on unique_missing_precondition_kind on N ≥ 2",
14825 );
14826 assert_eq!(
14827 spec.unique_missing_postcondition_kind(),
14828 None,
14829 "empty ephemeral must return None on unique_missing_postcondition_kind on N ≥ 2",
14830 );
14831 assert_eq!(
14832 spec.unique_missing_condition_kind(),
14833 None,
14834 "empty ephemeral must return None on unique_missing_condition_kind on N ≥ 2",
14835 );
14836 }
14837
14838 // Single-populated per side — sweep ALL × ALL.
14839 for pre_kind in ConditionKind::ALL {
14840 for post_kind in ConditionKind::ALL {
14841 let mut spec = empty_ephemeral();
14842 spec.preconditions.push(cond(pre_kind));
14843 spec.postconditions.push(cond(post_kind));
14844
14845 assert_eq!(
14846 spec.unique_missing_precondition_kind(),
14847 spec.preconditions.unique_missing_kind(),
14848 "EphemeralSpec::unique_missing_precondition_kind must delegate verbatim to \
14849 preconditions.unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14850 );
14851 assert_eq!(
14852 spec.unique_missing_postcondition_kind(),
14853 spec.postconditions.unique_missing_kind(),
14854 "EphemeralSpec::unique_missing_postcondition_kind must delegate verbatim to \
14855 postconditions.unique_missing_kind() for pre={pre_kind:?} post={post_kind:?}",
14856 );
14857
14858 let missing: Vec<ConditionKind> = ConditionKind::ALL
14859 .into_iter()
14860 .filter(|k| pre_kind != *k && post_kind != *k)
14861 .collect();
14862 let expected_union = if missing.len() == 1 {
14863 Some(missing[0])
14864 } else {
14865 None
14866 };
14867 assert_eq!(
14868 spec.unique_missing_condition_kind(),
14869 expected_union,
14870 "EphemeralSpec::unique_missing_condition_kind must equal Some(k) iff the \
14871 ALL-entries NOT covered by either half-slice sum to exactly one for \
14872 pre={pre_kind:?} post={post_kind:?}",
14873 );
14874
14875 // Boolean-witness composition laws.
14876 assert_eq!(
14877 spec.unique_missing_condition_kind().is_some(),
14878 spec.has_unique_missing_condition_kind(),
14879 "unique_missing_condition_kind().is_some() must equal \
14880 has_unique_missing_condition_kind() for pre={pre_kind:?} post={post_kind:?}",
14881 );
14882
14883 // Two-surface parity.
14884 let lowered: ProcessSpec = spec.clone().into();
14885 assert_eq!(
14886 spec.unique_missing_precondition_kind(),
14887 lowered.boundary.unique_missing_precondition_kind(),
14888 "two-surface unique_missing_precondition_kind parity drift for \
14889 pre={pre_kind:?} post={post_kind:?}",
14890 );
14891 assert_eq!(
14892 spec.unique_missing_postcondition_kind(),
14893 lowered.boundary.unique_missing_postcondition_kind(),
14894 "two-surface unique_missing_postcondition_kind parity drift for \
14895 pre={pre_kind:?} post={post_kind:?}",
14896 );
14897 assert_eq!(
14898 spec.unique_missing_condition_kind(),
14899 lowered.boundary.unique_missing_condition_kind(),
14900 "two-surface unique_missing_condition_kind parity drift for \
14901 pre={pre_kind:?} post={post_kind:?}",
14902 );
14903 }
14904 }
14905
14906 // Saturated ephemeral — every arm returns None (zero missing).
14907 let mut spec = empty_ephemeral();
14908 for k in ConditionKind::ALL {
14909 spec.preconditions.push(cond(k));
14910 spec.postconditions.push(cond(k));
14911 }
14912 assert_eq!(
14913 spec.unique_missing_precondition_kind(),
14914 None,
14915 "saturated ephemeral must return None on unique_missing_precondition_kind",
14916 );
14917 assert_eq!(
14918 spec.unique_missing_postcondition_kind(),
14919 None,
14920 "saturated ephemeral must return None on unique_missing_postcondition_kind",
14921 );
14922 assert_eq!(
14923 spec.unique_missing_condition_kind(),
14924 None,
14925 "saturated ephemeral must return None on unique_missing_condition_kind",
14926 );
14927
14928 // Near-saturation arm: exactly one ALL entry missing on each
14929 // side (populate every kind except `hole`).
14930 for hole in ConditionKind::ALL {
14931 let mut spec = empty_ephemeral();
14932 for k in ConditionKind::ALL {
14933 if k != hole {
14934 spec.preconditions.push(cond(k));
14935 spec.postconditions.push(cond(k));
14936 }
14937 }
14938 assert_eq!(
14939 spec.unique_missing_precondition_kind(),
14940 Some(hole),
14941 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_precondition_kind",
14942 );
14943 assert_eq!(
14944 spec.unique_missing_postcondition_kind(),
14945 Some(hole),
14946 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_postcondition_kind",
14947 );
14948 assert_eq!(
14949 spec.unique_missing_condition_kind(),
14950 Some(hole),
14951 "near-saturation ephemeral must return Some(hole={hole:?}) on unique_missing_condition_kind",
14952 );
14953 }
14954 }
14955
14956 /// SUBSTRATE-DELEGATION pin (EphemeralSpec per-kind cardinality
14957 /// "≥ 2" many-arm triad on the count axis) — the three
14958 /// `has_multiple_of_*_condition_kind` methods on
14959 /// [`EphemeralSpec`] delegate to the slice-level substrate
14960 /// primitive
14961 /// [`crate::boundary::ConditionSliceExt::has_multiple_of_kind`]
14962 /// over the two `Vec<Condition>` slots and compose the union via
14963 /// a two-step-short-circuit walk over the chained per-kind
14964 /// iterator [`EphemeralSpec::iter_condition_kind`]. Sweeps: (a)
14965 /// the empty spec (every arm returns `false` on every kind); (b)
14966 /// a single-populated-per-side arrangement where each per-slice
14967 /// arm returns `false` but the union goes true iff pre and post
14968 /// carry the SAME kind; (c) the saturated-doubled spec (every
14969 /// arm returns `true` on every kind). Also verifies TWO-SURFACE
14970 /// PARITY — the ephemeral-side arm agrees with the lowered
14971 /// [`crate::boundary::Boundary`] arm through the same slice-
14972 /// level substrate primitive. A regression at either surface
14973 /// fails HERE rather than as silent drift between the two.
14974 #[test]
14975 fn has_multiple_of_condition_kind_triad_delegates_to_slice_has_multiple_of_kind() {
14976 // Empty ephemeral — every arm returns false on every kind.
14977 let spec = empty_ephemeral();
14978 for kind in ConditionKind::ALL {
14979 assert!(
14980 !spec.has_multiple_of_precondition_kind(kind),
14981 "empty ephemeral must return false on has_multiple_of_precondition_kind({kind:?})",
14982 );
14983 assert!(
14984 !spec.has_multiple_of_postcondition_kind(kind),
14985 "empty ephemeral must return false on has_multiple_of_postcondition_kind({kind:?})",
14986 );
14987 assert!(
14988 !spec.has_multiple_of_condition_kind(kind),
14989 "empty ephemeral must return false on has_multiple_of_condition_kind({kind:?})",
14990 );
14991 }
14992
14993 // Single-populated-per-side sweep — per-slice arms stay
14994 // false; union goes true iff pre and post carry the SAME
14995 // kind. Also verifies two-surface parity with Boundary.
14996 for pre_kind in ConditionKind::ALL {
14997 for post_kind in ConditionKind::ALL {
14998 let mut spec = empty_ephemeral();
14999 spec.preconditions.push(cond(pre_kind));
15000 spec.postconditions.push(cond(post_kind));
15001 let lowered: ProcessSpec = spec.clone().into();
15002
15003 for query in ConditionKind::ALL {
15004 assert_eq!(
15005 spec.has_multiple_of_precondition_kind(query),
15006 spec.preconditions.has_multiple_of_kind(query),
15007 "EphemeralSpec::has_multiple_of_precondition_kind must delegate \
15008 verbatim to preconditions.has_multiple_of_kind for \
15009 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15010 );
15011 assert_eq!(
15012 spec.has_multiple_of_postcondition_kind(query),
15013 spec.postconditions.has_multiple_of_kind(query),
15014 "EphemeralSpec::has_multiple_of_postcondition_kind must delegate \
15015 verbatim to postconditions.has_multiple_of_kind for \
15016 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15017 );
15018
15019 let expected_union = pre_kind == query && post_kind == query;
15020 assert_eq!(
15021 spec.has_multiple_of_condition_kind(query),
15022 expected_union,
15023 "EphemeralSpec::has_multiple_of_condition_kind({query:?}) must equal \
15024 (pre == query && post == query) for pre={pre_kind:?} post={post_kind:?}",
15025 );
15026
15027 // Two-surface parity with lowered Boundary.
15028 assert_eq!(
15029 spec.has_multiple_of_condition_kind(query),
15030 lowered.boundary.has_multiple_of_condition_kind(query),
15031 "two-surface has_multiple_of_condition_kind({query:?}) parity drift \
15032 for pre={pre_kind:?} post={post_kind:?}",
15033 );
15034 assert_eq!(
15035 spec.has_multiple_of_precondition_kind(query),
15036 lowered.boundary.has_multiple_of_precondition_kind(query),
15037 "two-surface has_multiple_of_precondition_kind({query:?}) parity drift",
15038 );
15039 assert_eq!(
15040 spec.has_multiple_of_postcondition_kind(query),
15041 lowered.boundary.has_multiple_of_postcondition_kind(query),
15042 "two-surface has_multiple_of_postcondition_kind({query:?}) parity drift",
15043 );
15044 }
15045 }
15046 }
15047
15048 // Saturated-doubled spec — every arm returns true on every
15049 // kind (every slice carries every kind twice).
15050 let mut spec = empty_ephemeral();
15051 for k in ConditionKind::ALL {
15052 spec.preconditions.push(cond(k));
15053 spec.preconditions.push(cond(k));
15054 spec.postconditions.push(cond(k));
15055 spec.postconditions.push(cond(k));
15056 }
15057 for kind in ConditionKind::ALL {
15058 assert!(
15059 spec.has_multiple_of_precondition_kind(kind),
15060 "saturated-doubled ephemeral must return true on has_multiple_of_precondition_kind({kind:?})",
15061 );
15062 assert!(
15063 spec.has_multiple_of_postcondition_kind(kind),
15064 "saturated-doubled ephemeral must return true on has_multiple_of_postcondition_kind({kind:?})",
15065 );
15066 assert!(
15067 spec.has_multiple_of_condition_kind(kind),
15068 "saturated-doubled ephemeral must return true on has_multiple_of_condition_kind({kind:?})",
15069 );
15070 }
15071 }
15072
15073 /// Every arm of the (precondition, postcondition, condition-union)
15074 /// per-kind cardinality "= 1" mid-endpoint triad on
15075 /// [`EphemeralSpec`] delegates verbatim to the slice-level
15076 /// substrate primitive
15077 /// [`crate::boundary::ConditionSliceExt::has_unique_of_kind`].
15078 /// Sweeps three arrangements: (a) an empty ephemeral (every arm
15079 /// returns `false` on every kind); (b) a single-populated-per-
15080 /// side sweep where per-slice arms fire iff their side's kind
15081 /// equals `query`, and the union arm fires iff EXACTLY ONE of
15082 /// `{pre, post}` equals `query` (chain sums to 1 on disjoint,
15083 /// 2 on shared); (c) the saturated-singleton spec (every kind
15084 /// appears exactly once on every slice — per-slice arms return
15085 /// `true` on every kind, union returns `false` on every kind
15086 /// as `= 2` chain matches). Also verifies TWO-SURFACE PARITY —
15087 /// the ephemeral-side arm agrees with the lowered
15088 /// [`crate::boundary::Boundary`] arm through the same slice-
15089 /// level substrate primitive.
15090 #[test]
15091 fn has_unique_of_condition_kind_triad_delegates_to_slice_has_unique_of_kind() {
15092 // Empty ephemeral — every arm returns false on every kind.
15093 let spec = empty_ephemeral();
15094 for kind in ConditionKind::ALL {
15095 assert!(
15096 !spec.has_unique_of_precondition_kind(kind),
15097 "empty ephemeral must return false on has_unique_of_precondition_kind({kind:?})",
15098 );
15099 assert!(
15100 !spec.has_unique_of_postcondition_kind(kind),
15101 "empty ephemeral must return false on has_unique_of_postcondition_kind({kind:?})",
15102 );
15103 assert!(
15104 !spec.has_unique_of_condition_kind(kind),
15105 "empty ephemeral must return false on has_unique_of_condition_kind({kind:?})",
15106 );
15107 }
15108
15109 // Single-populated-per-side sweep — per-slice arm fires iff
15110 // its side's kind equals `query`; union arm fires iff
15111 // EXACTLY ONE of {pre, post} equals `query`. Also verifies
15112 // two-surface parity with Boundary.
15113 for pre_kind in ConditionKind::ALL {
15114 for post_kind in ConditionKind::ALL {
15115 let mut spec = empty_ephemeral();
15116 spec.preconditions.push(cond(pre_kind));
15117 spec.postconditions.push(cond(post_kind));
15118 let lowered: ProcessSpec = spec.clone().into();
15119
15120 for query in ConditionKind::ALL {
15121 assert_eq!(
15122 spec.has_unique_of_precondition_kind(query),
15123 spec.preconditions.has_unique_of_kind(query),
15124 "EphemeralSpec::has_unique_of_precondition_kind must delegate \
15125 verbatim to preconditions.has_unique_of_kind for \
15126 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15127 );
15128 assert_eq!(
15129 spec.has_unique_of_postcondition_kind(query),
15130 spec.postconditions.has_unique_of_kind(query),
15131 "EphemeralSpec::has_unique_of_postcondition_kind must delegate \
15132 verbatim to postconditions.has_unique_of_kind for \
15133 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15134 );
15135
15136 let expected_union = (pre_kind == query) ^ (post_kind == query);
15137 assert_eq!(
15138 spec.has_unique_of_condition_kind(query),
15139 expected_union,
15140 "EphemeralSpec::has_unique_of_condition_kind({query:?}) must equal \
15141 ((pre == query) XOR (post == query)) for \
15142 pre={pre_kind:?} post={post_kind:?}",
15143 );
15144
15145 // Two-surface parity with lowered Boundary.
15146 assert_eq!(
15147 spec.has_unique_of_condition_kind(query),
15148 lowered.boundary.has_unique_of_condition_kind(query),
15149 "two-surface has_unique_of_condition_kind({query:?}) parity drift \
15150 for pre={pre_kind:?} post={post_kind:?}",
15151 );
15152 assert_eq!(
15153 spec.has_unique_of_precondition_kind(query),
15154 lowered.boundary.has_unique_of_precondition_kind(query),
15155 "two-surface has_unique_of_precondition_kind({query:?}) parity drift",
15156 );
15157 assert_eq!(
15158 spec.has_unique_of_postcondition_kind(query),
15159 lowered.boundary.has_unique_of_postcondition_kind(query),
15160 "two-surface has_unique_of_postcondition_kind({query:?}) parity drift",
15161 );
15162 }
15163 }
15164 }
15165
15166 // Saturated-singleton spec — every kind appears exactly once
15167 // on every slice; per-slice arms return true on every kind,
15168 // union returns false on every kind (= 2 chain matches).
15169 let mut spec = empty_ephemeral();
15170 for k in ConditionKind::ALL {
15171 spec.preconditions.push(cond(k));
15172 spec.postconditions.push(cond(k));
15173 }
15174 for kind in ConditionKind::ALL {
15175 assert!(
15176 spec.has_unique_of_precondition_kind(kind),
15177 "saturated-singleton ephemeral must return true on has_unique_of_precondition_kind({kind:?})",
15178 );
15179 assert!(
15180 spec.has_unique_of_postcondition_kind(kind),
15181 "saturated-singleton ephemeral must return true on has_unique_of_postcondition_kind({kind:?})",
15182 );
15183 assert!(
15184 !spec.has_unique_of_condition_kind(kind),
15185 "saturated-singleton ephemeral must return false on union has_unique_of_condition_kind({kind:?}) (2 chain matches)",
15186 );
15187 }
15188 }
15189
15190 // ── EphemeralSpec::has_at_most_one_of_(pre|post|)condition_kind ─
15191 //
15192 // Two-surface parity contract with
15193 // `Boundary::has_at_most_one_of_condition_kind` on the "≤ 1"
15194 // per-kind negation arm. Ephemeral composes against the SAME
15195 // slice-level substrate primitive
15196 // `ConditionSliceExt::has_at_most_one_of_kind` via delegation on
15197 // each side and via the definitional negation of
15198 // `has_multiple_of_condition_kind` on the union chain. Regression
15199 // at either the per-slice negation walk or the ephemeral→boundary
15200 // lowering fails here.
15201
15202 /// EphemeralSpec triad delegation + two-surface parity pin —
15203 /// sweeps every kind on every reachable arrangement of a single
15204 /// condition-per-side spec, asserts each per-slice arm delegates
15205 /// verbatim to the slice-level primitive, and asserts the union
15206 /// arm agrees with the lowered [`ProcessSpec`]'s
15207 /// [`Boundary::has_at_most_one_of_condition_kind`] on every
15208 /// arm. Also pins the trichotomy-union arm equivalence
15209 /// `has_at_most_one_of_condition_kind == lacks_condition_kind ||
15210 /// has_unique_of_condition_kind` and the tetrachotomy partition
15211 /// (`{≤ 1, ≥ 2}` exactly one arm on every arrangement).
15212 #[test]
15213 fn has_at_most_one_of_condition_kind_triad_delegates_to_slice_has_at_most_one_of_kind() {
15214 // Empty ephemeral — every arm returns true on every kind
15215 // (0 matches, `≤ 1`).
15216 let spec = empty_ephemeral();
15217 for kind in ConditionKind::ALL {
15218 assert!(
15219 spec.has_at_most_one_of_precondition_kind(kind),
15220 "empty ephemeral must return true on has_at_most_one_of_precondition_kind({kind:?})",
15221 );
15222 assert!(
15223 spec.has_at_most_one_of_postcondition_kind(kind),
15224 "empty ephemeral must return true on has_at_most_one_of_postcondition_kind({kind:?})",
15225 );
15226 assert!(
15227 spec.has_at_most_one_of_condition_kind(kind),
15228 "empty ephemeral must return true on has_at_most_one_of_condition_kind({kind:?})",
15229 );
15230 }
15231
15232 // Single-populated-per-side sweep — per-slice arms always
15233 // fire; union arm fires iff at most one of `{pre, post}`
15234 // equals `query` (`!(pre_hit && post_hit)`). Also verifies
15235 // two-surface parity with Boundary on every arm.
15236 for pre_kind in ConditionKind::ALL {
15237 for post_kind in ConditionKind::ALL {
15238 let mut spec = empty_ephemeral();
15239 spec.preconditions.push(cond(pre_kind));
15240 spec.postconditions.push(cond(post_kind));
15241 let lowered: ProcessSpec = spec.clone().into();
15242
15243 for query in ConditionKind::ALL {
15244 assert_eq!(
15245 spec.has_at_most_one_of_precondition_kind(query),
15246 spec.preconditions.has_at_most_one_of_kind(query),
15247 "EphemeralSpec::has_at_most_one_of_precondition_kind must delegate \
15248 verbatim to preconditions.has_at_most_one_of_kind for \
15249 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15250 );
15251 assert_eq!(
15252 spec.has_at_most_one_of_postcondition_kind(query),
15253 spec.postconditions.has_at_most_one_of_kind(query),
15254 "EphemeralSpec::has_at_most_one_of_postcondition_kind must delegate \
15255 verbatim to postconditions.has_at_most_one_of_kind for \
15256 pre={pre_kind:?} post={post_kind:?} query={query:?}",
15257 );
15258
15259 let pre_hit = pre_kind == query;
15260 let post_hit = post_kind == query;
15261 let expected_union = !(pre_hit && post_hit);
15262 assert_eq!(
15263 spec.has_at_most_one_of_condition_kind(query),
15264 expected_union,
15265 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) must equal \
15266 !(pre_hit && post_hit) for pre={pre_kind:?} post={post_kind:?}",
15267 );
15268
15269 // Definitional negation of the many-arm peer.
15270 assert_eq!(
15271 spec.has_at_most_one_of_condition_kind(query),
15272 !spec.has_multiple_of_condition_kind(query),
15273 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) drifted \
15274 from !has_multiple_of_condition_kind for pre={pre_kind:?} \
15275 post={post_kind:?}",
15276 );
15277
15278 // Trichotomy-union arm: {= 0} ∪ {= 1} == {≤ 1}.
15279 assert_eq!(
15280 spec.has_at_most_one_of_condition_kind(query),
15281 spec.lacks_condition_kind(query)
15282 || spec.has_unique_of_condition_kind(query),
15283 "EphemeralSpec::has_at_most_one_of_condition_kind({query:?}) drifted \
15284 from (lacks || has_unique) trichotomy-union for pre={pre_kind:?} \
15285 post={post_kind:?}",
15286 );
15287
15288 // Two-surface parity with lowered Boundary.
15289 assert_eq!(
15290 spec.has_at_most_one_of_condition_kind(query),
15291 lowered.boundary.has_at_most_one_of_condition_kind(query),
15292 "two-surface has_at_most_one_of_condition_kind({query:?}) parity drift \
15293 for pre={pre_kind:?} post={post_kind:?}",
15294 );
15295 assert_eq!(
15296 spec.has_at_most_one_of_precondition_kind(query),
15297 lowered.boundary.has_at_most_one_of_precondition_kind(query),
15298 "two-surface has_at_most_one_of_precondition_kind({query:?}) parity \
15299 drift for pre={pre_kind:?} post={post_kind:?}",
15300 );
15301 assert_eq!(
15302 spec.has_at_most_one_of_postcondition_kind(query),
15303 lowered
15304 .boundary
15305 .has_at_most_one_of_postcondition_kind(query),
15306 "two-surface has_at_most_one_of_postcondition_kind({query:?}) parity \
15307 drift for pre={pre_kind:?} post={post_kind:?}",
15308 );
15309
15310 // {≤ 1, ≥ 2} Boolean-negation partition at the
15311 // union level — EXACTLY ONE arm fires.
15312 let at_most_one = spec.has_at_most_one_of_condition_kind(query);
15313 let multiple = spec.has_multiple_of_condition_kind(query);
15314 assert_ne!(
15315 at_most_one, multiple,
15316 "union {{≤ 1, ≥ 2}} Boolean-negation partition for query={query:?} \
15317 (pre={pre_kind:?} post={post_kind:?}) must fire EXACTLY one arm",
15318 );
15319 }
15320 }
15321 }
15322
15323 // Saturated-singleton spec — every kind appears exactly once
15324 // on every slice. Per-slice arms return true on every kind;
15325 // union returns false on every kind (2 chain matches, not ≤ 1).
15326 let mut spec = empty_ephemeral();
15327 for k in ConditionKind::ALL {
15328 spec.preconditions.push(cond(k));
15329 spec.postconditions.push(cond(k));
15330 }
15331 for kind in ConditionKind::ALL {
15332 assert!(
15333 spec.has_at_most_one_of_precondition_kind(kind),
15334 "saturated-singleton ephemeral must return true on has_at_most_one_of_precondition_kind({kind:?})",
15335 );
15336 assert!(
15337 spec.has_at_most_one_of_postcondition_kind(kind),
15338 "saturated-singleton ephemeral must return true on has_at_most_one_of_postcondition_kind({kind:?})",
15339 );
15340 assert!(
15341 !spec.has_at_most_one_of_condition_kind(kind),
15342 "saturated-singleton ephemeral must return false on union has_at_most_one_of_condition_kind({kind:?}) (2 chain matches)",
15343 );
15344 }
15345 }
15346}